策略为王C++股票软件利用第三方通视接口标准stock.dll接收数据原理分析

Published
策略为王C++股票软件利用第三方通视接口标准stock.dll接收数据原理分析


描述了数据模块和股票软件关系
数据模块实体是stock.dll,策略为王通过一些函数激活DLL里的窗体和内部功能,再用约定的接口机制通信。接口通常是消息。有的可能也用回调机制,比如函数回调或者多态回调。

股票软件会把数据模块实体DLL加载到自己的内存区里使用,但是开发人员是接触不到DLL里的源代码,只能使用接口机制来使用。这里模块和宿主股票软件是有明显界限的。
这个界限是理论上的界限,不是实际的界限,如果用图像描述,可能好理解些。在图像里,数据模块是一个矩形,宿主股票软件是个大矩形,大矩形里包含数据模块矩形。

接收数据技术
作为数据分析的基础,数据接收虽然简单,但是也很容易对初学者和刚刚接触股软的朋友造成困扰。最近经常有朋友谈起数据接收方面的疑问,对此,写了一个最基本的数据接收的类供大家参考。

现在市面上的数据引擎和各厂商的软件种类虽然很多,但或多或少的都遵循着一种规范,然后各自添加一些自己的东西。这个规范就是通视接口规范,后来分析家的流行,大家见的最多的是分析家发布的一个规范文件,其实和通视规范是一回事。我们也就拿这个做举例说明。

本文虽是初级教程,但需要一定的C++基础和编程经验。为照顾一写新手,力求做到简单易懂,配套代码在VC2008下写成,可在VC2005和VC2008下正常编译,如果您出现编译上的问题,请检查软件环境或重新安装VC。

规范规定数据接口程序需用一个动态连接库DLL的形式存在,安装好之后在HKEY_LOCAL_MACHINE/SOFTWARE/StockDrv中添加键值Driver,指示DLL所在路径。程序只要查询这个键值就能调用数据接收接口。事实上有些接口是以EXE和DLL共存的形式存在,甚至只有EXE程序,这个我们不做研究,原理是一样的。

在接口的DLL中提供几个API函数接口供其他程序调用,在通视和分析家公布的接口文件中有详细的说明。在这里我们只介绍两个Stock_Init和Stock_Quit启动和退出接收。

// 股票初始化
// 入口参数:
// hWnd 处理消息的窗口句柄
// Msg 用户自定义消息
// nWorkMode 接口工作方式
// 返回参数:
// 1 成功
// -1 失败
// 注:
// 注册后,驱动程序会向处理窗口发送消息; 若不注册,通过查询方式亦可取得数据
// 若股票接收没启动,则启动股票接收程序
int WINAPI Stock_Init(HWND hWnd,UINT Msg,int nWorkMode);

// 退出,停止发送消息
// 入口参数:
// hWnd 处理消息的窗口句柄,同 Stock_Init 的调用入口参数
// 返回参数:
// 1 成功 
// -1 失败
int WINAPI Stock_Quit(HWND hWnd);

值得一说的是Stock_Init接口提供两种接收方式,内存查询和消息发布,目前只用消息模式,也就是第三个参数 是 RCV_WORK_SENDMSG。第一个hWnd是消息接收的窗口,我们设置成自己程序的一个窗口来接收消息。第二个参数Msg是自定义消息,我们需在hWnd的窗口中添加一个函数来接收这个消息。

我们写两个类
一个是CStkDriver,用来封装对DLL的调用,另外一个就是CStkReceiver,主要有以下几个函数

BOOL StartEngine(TskEngineMode nMode = TSK_TONGSHI);
启动数据接收,默认参数为启用通视接收方式,由于数畅、网际风等扩展了自己的接口函数,这个我们在以后添加。
函数中
BOOL bRet = m_pDriver->LoadDriver(_T("D:\\NetStock\\WJF353\\Stock.dll"));
是加载接口的DLL,请改成实际的路径,如银江的默认安装目录 是C:\\JStockclt\Stock.dll,或者直接查询注册表HKEY_LOCAL_MACHINE/SOFTWARE/StockDrv中的Driver值,得到DLL路径

BOOL StopEngine();
停止数据接收

virtual LRESULT NotifyReceiverData(UINT nType, void* pData, int nSize);
数据处理函数,当接收到数据后会确发此函数,我们可以在此添加数据处理过程,或者直接重载此函数。 
分析数据技术
接口会提供一个整体数据包结构体类型指针,在整体数据包结构体里有很多当数组用的指针,当然也提供长度。结合长度和和指针,就可以找出一个一个的结构体,这些小结构体里就有价格和成交量这些数据

比如行情数据:

typedef struct tagRCV_DATA
{
int	m_wDataType;	// 文件类型
int	m_nPacketNum;	// 记录数,参见注一
RCV_FILE_HEADEx	m_File;	// 文件接口
BOOL	m_bDISK;	// 文件是否已存盘的文件
union
{
RCV_REPORT_STRUCTEx *	m_pReport;
RCV_HISTORY_STRUCTEx *	m_pDay;
RCV_MINUTE_STRUCTEx *	m_pMinute;
RCV_POWER_STRUCTEx	*	m_pPower;
void	*	m_pData;	// 参见注二
};
} RCV_DATA,*PRCV_DATA;
里面的记录数就是长度。

处理实时行情的代码示例如下:

case RCV_REPORT:
{//实时行情

int nBufSize = pHeader->m_pReport[0].m_cbSize;
PBYTE pBaseBuf = (PBYTE)&pHeader->m_pReport[0];

 

D:\\Scengine\\Stock.dll 数畅

D:\\yj\\Stock.dll   银江

D:\\wjf\\Stock.dll  网际风

龙卷风接口