vnpy/vn.lts/vnltsmd/pyltsmd/vnltsmd.h

273 lines
7.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//说明部分
//系统
#include "stdafx.h"
#include <string>
#include <queue>
//Boost
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python/module.hpp> //python封装
#include <boost/python/def.hpp> //python封装
#include <boost/python/dict.hpp> //python封装
#include <boost/python/object.hpp> //python封装
#include <boost/python.hpp> //python封装
#include <boost/thread.hpp> //任务队列的线程功能
#include <boost/bind.hpp> //任务队列的线程功能
#include <boost/any.hpp> //任务队列的任务实现
//API
#include "SecurityFtdcMdApi.h"
//命名空间
using namespace std;
using namespace boost::python;
using namespace boost;
//常量
#define ONFRONTCONNECTED 0
#define ONFRONTDISCONNECTED 1
#define ONHEARTBEATWARNING 2
#define ONRSPERROR 3
#define ONRSPUSERLOGIN 4
#define ONRSPUSERLOGOUT 5
#define ONRSPSUBMARKETDATA 6
#define ONRSPUNSUBMARKETDATA 7
#define ONRTNDEPTHMARKETDATA 8
#define EXIT 0
///-------------------------------------------------------------------------------------
///API中的部分组件
///-------------------------------------------------------------------------------------
//GIL全局锁简化获取用
//用于帮助C++线程获得GIL锁从而防止python崩溃
class PyLock
{
private:
PyGILState_STATE gil_state;
public:
//在某个函数方法中创建该对象时获得GIL锁
PyLock()
{
gil_state = PyGILState_Ensure();
}
//在某个函数完成后销毁该对象时解放GIL锁
~PyLock()
{
PyGILState_Release(gil_state);
}
};
//任务结构体
struct Task
{
int task_name; //回调函数名称对应的常量
any task_data; //数据结构体
any task_error; //错误结构体
int task_id; //请求id
bool task_last; //是否为最后返回
};
///线程安全的队列
template<typename Data>
class ConcurrentQueue
{
private:
queue<Data> the_queue; //标准库队列
mutable mutex the_mutex; //boost互斥锁
condition_variable the_condition_variable; //boost条件变量
public:
//存入新的任务
void push(Data const& data)
{
mutex::scoped_lock lock(the_mutex); //获取互斥锁
the_queue.push(data); //向队列中存入数据
lock.unlock(); //释放锁
the_condition_variable.notify_one(); //通知正在阻塞等待的线程
}
//检查队列是否为空
bool empty() const
{
mutex::scoped_lock lock(the_mutex);
return the_queue.empty();
}
//取出
Data wait_and_pop()
{
mutex::scoped_lock lock(the_mutex);
while (the_queue.empty()) //当队列为空时
{
the_condition_variable.wait(lock); //等待条件变量通知
}
Data popped_value = the_queue.front(); //获取队列中的最后一个任务
the_queue.pop(); //删除该任务
return popped_value; //返回该任务
}
};
//从字典中获取某个建值对应的整数,并赋值到请求结构体对象的值上
void getInt(dict d, string key, int* value);
//从字典中获取某个建值对应的浮点数,并赋值到请求结构体对象的值上
void getDouble(dict d, string key, double* value);
//从字典中获取某个建值对应的字符串,并赋值到请求结构体对象的值上
void getChar(dict d, string key, char* value);
///-------------------------------------------------------------------------------------
///C++ SPI的回调函数方法实现
///-------------------------------------------------------------------------------------
//API的继承实现
class MdApi : public CSecurityFtdcMdSpi
{
private:
CSecurityFtdcMdApi* api; //API对象
thread *task_thread; //工作线程指针向python中推送数据
ConcurrentQueue<Task> task_queue; //任务队列
public:
MdApi()
{
function0<void> f = boost::bind(&MdApi::processTask, this);
thread t(f);
this->task_thread = &t;
};
~MdApi()
{
};
//-------------------------------------------------------------------------------------
//API回调函数
//-------------------------------------------------------------------------------------
//当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。
virtual void OnFrontConnected();
//当客户端与交易后台通信连接断开时该方法被调用。当发生这个情况后API会自动重新连接客户端可不做处理。
//@param nReason 错误原因
// 0x1001 网络读失败
// 0x1002 网络写失败
// 0x2001 接收心跳超时
// 0x2002 发送心跳失败
// 0x2003 收到错误报文
virtual void OnFrontDisconnected(int nReason);
//心跳超时警告。当长时间未收到报文时,该方法被调用。
//@param nTimeLapse 距离上次接收报文的时间
virtual void OnHeartBeatWarning(int nTimeLapse);
//错误应答
virtual void OnRspError(CSecurityFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
//登录请求响应
virtual void OnRspUserLogin(CSecurityFtdcRspUserLoginField *pRspUserLogin, CSecurityFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
//登出请求响应
virtual void OnRspUserLogout(CSecurityFtdcUserLogoutField *pUserLogout, CSecurityFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
//订阅行情应答
virtual void OnRspSubMarketData(CSecurityFtdcSpecificInstrumentField *pSpecificInstrument, CSecurityFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
//取消订阅行情应答
virtual void OnRspUnSubMarketData(CSecurityFtdcSpecificInstrumentField *pSpecificInstrument, CSecurityFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
//深度行情通知
virtual void OnRtnDepthMarketData(CSecurityFtdcDepthMarketDataField *pDepthMarketData);
//-------------------------------------------------------------------------------------
//task任务
//-------------------------------------------------------------------------------------
void processTask();
void processFrontConnected(Task task);
void processFrontDisconnected(Task task);
void processHeartBeatWarning(Task task);
void processRspError(Task task);
void processRspUserLogin(Task task);
void processRspUserLogout(Task task);
void processRspSubMarketData(Task task);
void processRspUnSubMarketData(Task task);
void processRtnDepthMarketData(Task task);
//-------------------------------------------------------------------------------------
//data回调函数的数据字典
//error回调函数的错误字典
//id请求id
//last是否为最后返回
//i整数
//-------------------------------------------------------------------------------------
virtual void onFrontConnected(){};
virtual void onFrontDisconnected(int i){};
virtual void onHeartBeatWarning(int i){};
virtual void onRspError(dict data, int id, bool last) {};
virtual void onRspUserLogin(dict data, dict error, int id, bool last) {};
virtual void onRspUserLogout(dict data, dict error, int id, bool last) {};
virtual void onRspSubMarketData(dict data, dict error, int id, bool last) {};
virtual void onRspUnSubMarketData(dict data, dict error, int id, bool last) {};
virtual void onRtnDepthMarketData(dict data) {};
//-------------------------------------------------------------------------------------
//req:主动函数的请求字典
//-------------------------------------------------------------------------------------
void createFtdcMdApi(string pszFlowPath = "");
void release();
void init();
int join();
string getTradingDay();
void registerFront(string pszFrontAddress);
int subscribeMarketData(dict req);
int unSubscribeMarketData(dict req);
int reqUserLogin(dict req, int nRequestID);
int reqUserLogout(dict req, int nRequestID);
};