接上一篇,本文主要是实现计算的Python代码和C++代码
1、Python代码
Python代码逻辑主要参考《用CTP接口实现期货交易明细分析(1)》,《用CTP接口实现期货交易明细分析(2)》,请知悉。但是原文中运用了vnpy的框架,我是用的自己编译的PythonAPI《CTP Python API(利用Swig 封装)Windows版(mduserapi)》
代码如下:
# -*- coding:utf-8 -*-
import time
import thostmduserapi as mdapi
import copy
def enum(**enums):
return type('Enum', (), enums)
# 仓位变化方向
open_interest_delta_forward_enum = enum(OPEN="Open", CLOSE="Close", EXCHANGE="Exchange", NONE="None",
OPENFWDOUBLE="OpenFwDouble", CLOSEFWDOUBLE="CloseFwDOuble")
# 订单成交区域,决定是多还是空
order_forward_enum = enum(UP="Up", DOWN="Down", MIDDLE="Middle")
# 最终需要的tick方向
tick_type_enum = enum(OPENLONG="OpenLong", OPENSHORT="OpenShort", OPENDOUBLE="OpenDouble",
CLOSELONG="CloseLong", CLOSESHORT="CloseShort", CLOSEDOUBLE="CloseDouble",
EXCHANGELONG="ExchangeLong", EXCHANGESHORT="ExchangeShort",
OPENUNKOWN="OpenUnkown", CLOSEUNKOWN="CloseUnkown", EXCHANGEUNKOWN="ExchangeUnkown",
UNKOWN="Unkown", NOCHANGE="NoChange")
tick_color_enum = enum(RED="Red", GREEN="Green", WHITE="White")
tick_type_key_enum = enum(TICKTYPE="TickType", TICKCOLOR="TickColor")
# 只与计算对手单的组成相关
opponent_key_enum = enum(OPPOSITE="Opposite", SIMILAR="Similar")
# 只做翻译成中文使用,对应 tick_type_enum
tick_type_str_dict = {tick_type_enum.OPENLONG: "多开", tick_type_enum.OPENSHORT: "空开",
tick_type_enum.OPENDOUBLE: "双开",
tick_type_enum.CLOSELONG: "多平", tick_type_enum.CLOSESHORT: "空平",
tick_type_enum.CLOSEDOUBLE: "双平",
tick_type_enum.EXCHANGELONG: "多换", tick_type_enum.EXCHANGESHORT: "空换",
tick_type_enum.OPENUNKOWN: "未知开仓", tick_type_enum.CLOSEUNKOWN: "未知平仓",
tick_type_enum.EXCHANGEUNKOWN: "未知换仓",
tick_type_enum.UNKOWN: "未知", tick_type_enum.NOCHANGE: "没有变化",
tick_color_enum.RED: "红", tick_color_enum.GREEN: "绿", tick_color_enum.WHITE: "白"}
# 根据 open_interest_delta_forward_enum 和 order_forward_enum 计算出tick类型的字典
tick_type_cal_dict = {
open_interest_delta_forward_enum.NONE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.NOCHANGE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.NOCHANGE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.NOCHANGE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.EXCHANGE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.EXCHANGELONG,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.EXCHANGESHORT,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.EXCHANGEUNKOWN,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.OPENFWDOUBLE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.OPEN:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENLONG,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENSHORT,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENUNKOWN,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.CLOSEFWDOUBLE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.CLOSE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSESHORT,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSELONG,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEUNKOWN,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
}
# 只与计算对手单的组成相关,只有4种tick类型才需要计算对手单的组成
handicap_dict = {tick_type_enum.OPENLONG: {opponent_key_enum.OPPOSITE: tick_type_enum.CLOSELONG,
opponent_key_enum.SIMILAR: tick_type_enum.OPENSHORT},
tick_type_enum.OPENSHORT: {opponent_key_enum.OPPOSITE: tick_type_enum.CLOSESHORT,
opponent_key_enum.SIMILAR: tick_type_enum.OPENLONG},
tick_type_enum.CLOSELONG: {opponent_key_enum.OPPOSITE: tick_type_enum.OPENLONG,
opponent_key_enum.SIMILAR: tick_type_enum.CLOSESHORT},
tick_type_enum.CLOSESHORT: {opponent_key_enum.OPPOSITE: tick_type_enum.OPENSHORT,
opponent_key_enum.SIMILAR: tick_type_enum.CLOSELONG}
}
class CFtdcMdSpi(mdapi.CThostFtdcMdSpi):
tapi=''
def __init__(self,tapi):
mdapi.CThostFtdcMdSpi.__init__(self)
self.tapi=tapi
self.PreDepthMarketData = None
def OnRspUserLogin(self, *args):
print "OnRspUserLogin"
rsploginfield=args[0]
rspinfofield=args[1]
print "SessionID=",rsploginfield.SessionID
print "ErrorID=",rspinfofield.ErrorID
print "ErrorMsg=",rspinfofield.ErrorMsg
mdapi.SubscribeMarketDataByManual(self.tapi,"T1803")
def onFrontConnected(self):
print "onFrontConnected"
# ----------------------------------------------------------------------
def onFrontDisconnected(self, *args):
print "onFrontDisconnected"
def OnRtnDepthMarketData(self, *args):
depthdata={}
depthdata['AskPrice1']=args[0].AskPrice1
depthdata['AskVolume1']=args[0].AskVolume1
depthdata['BidPrice1']=args[0].BidPrice1
depthdata['BidVolume1']=args[0].BidVolume1
depthdata['BidVolume1']=args[0].BidVolume1
depthdata['LastPrice']=args[0].LastPrice
depthdata['Volume']=args[0].Volume
depthdata['OpenInterest']=args[0].OpenInterest
depthdata['UpdateTime']=args[0].UpdateTime
depthdata['UpdateMillisec']=args[0].UpdateMillisec
if self.PreDepthMarketData is not None:
# 计算两tick之间的差值
ask_price_delta = self.PreDepthMarketData['AskPrice1'] - depthdata['AskPrice1']
ask_volume_delta = self.PreDepthMarketData['AskVolume1'] - depthdata['AskVolume1']
bid_price_delta = self.PreDepthMarketData['BidPrice1'] - depthdata['BidPrice1']
bid_volume_delta = self.PreDepthMarketData['BidVolume1'] - depthdata['BidVolume1']
last_price_delta = self.PreDepthMarketData['LastPrice'] - depthdata['LastPrice']
volume_delta = depthdata['Volume'] - self.PreDepthMarketData['Volume']
open_interest_delta = int(depthdata['OpenInterest'] - self.PreDepthMarketData['OpenInterest'])
# 编移量的显示字符串
ask_price_delta_str = self.get_delta_str(self.PreDepthMarketData['AskPrice1'], depthdata['AskPrice1'])
ask_volume_delta_str = self.get_delta_str(self.PreDepthMarketData['AskVolume1'], depthdata['AskVolume1'])
bid_price_delta_str = self.get_delta_str(self.PreDepthMarketData['BidPrice1'], depthdata['BidPrice1'])
bid_volume_delta_str = self.get_delta_str(self.PreDepthMarketData['BidVolume1'], depthdata['BidVolume1'])
last_price_delta_str = self.get_delta_str(self.PreDepthMarketData['LastPrice'], depthdata['LastPrice'])
# 如果ask或者bid价格对比上一个tick都发生了变化则不显示价格变化幅度
if ask_price_delta != 0:
ask_volume_delta_str = ''
if bid_price_delta != 0:
bid_volume_delta_str = ''
# input1 计算订单是在ask范围内成交还是在bid范围内成交
order_forward = self.get_order_forward(depthdata['LastPrice'], depthdata['AskPrice1'], depthdata['BidPrice1'],
self.PreDepthMarketData['LastPrice'],
self.PreDepthMarketData['AskPrice1'],
self.PreDepthMarketData['BidPrice1'])
# input2 计算仓位变化方向
open_interest_delta_forward = self.get_open_interest_delta_forward(open_interest_delta,
volume_delta)
# f(input1,input2) = output1 根据成交区域和仓位变化方向计算出tick的类型
tick_type_dict = tick_type_cal_dict[open_interest_delta_forward][order_forward]
if open_interest_delta_forward != open_interest_delta_forward_enum.NONE:
# 输出相关变量
print "Ask\t" + str(depthdata['AskPrice1']) + ask_price_delta_str + "\t" + str(
depthdata['AskVolume1']) + ask_volume_delta_str \
+ "\tBid\t" + str(depthdata['BidPrice1']) + bid_price_delta_str + "\t" + str(
depthdata['BidVolume1']) + bid_volume_delta_str
print str(depthdata['UpdateTime']) + "." + str(depthdata['UpdateMillisec']) \
+ "\t" + str(depthdata['LastPrice']) + last_price_delta_str \
+ "\t成交 " + str(volume_delta) \
+ "\t增仓 " + str(open_interest_delta) \
+ "\t" + tick_type_str_dict[tick_type_dict[tick_type_key_enum.TICKTYPE]] \
+ "\t" + tick_type_str_dict[tick_type_dict[tick_type_key_enum.TICKCOLOR]]
if tick_type_dict[tick_type_key_enum.TICKTYPE] in handicap_dict.keys():
order_opposite, order_similar = CFtdcMdSpi.get_order_combination(open_interest_delta,
volume_delta)
print "对手单:" + tick_type_str_dict[
handicap_dict[tick_type_dict[tick_type_key_enum.TICKTYPE]][opponent_key_enum.OPPOSITE]] \
+ " " + str(order_opposite) \
+ "\t" + tick_type_str_dict[
handicap_dict[tick_type_dict[tick_type_key_enum.TICKTYPE]][opponent_key_enum.SIMILAR]] \
+ " " + str(order_similar)
print '--------------------------------------'
self.PreDepthMarketData = copy.copy(depthdata)
# -----------------------------------------------------------------------
@staticmethod
def float_smaller_equal(smaller, bigger):
return CFtdcMdSpi.float_bigger_equal(bigger, smaller)
@staticmethod
def float_bigger_equal(bigger, smaller):
""" float型的数不能直接相等
http://www.sharejs.com/codes/python/223
"""
ret = False
if abs(bigger - smaller) < 0.00001:
ret = True
elif bigger > smaller:
ret = True
return ret
# ----------------------------------------------------------------------
@staticmethod
def get_open_interest_delta_forward(open_interest_delta, volume_delta):
"""根据成交量的差和持仓量的差来获取仓位变化的方向
return: open_interest_delta_forward_enum
"""
if open_interest_delta == 0 and volume_delta == 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.NONE
elif open_interest_delta == 0 and volume_delta > 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.EXCHANGE
elif open_interest_delta > 0:
if open_interest_delta - volume_delta == 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.OPENFWDOUBLE
else:
local_open_interest_delta_forward = open_interest_delta_forward_enum.OPEN
elif open_interest_delta < 0:
if open_interest_delta + volume_delta == 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.CLOSEFWDOUBLE
else:
local_open_interest_delta_forward = open_interest_delta_forward_enum.CLOSE
return local_open_interest_delta_forward
# ----------------------------------------------------------------------
@staticmethod
def get_order_forward(last_price, ask_price1, bid_price1, pre_last_price, pre_ask_price1, pre_bid_price1):
"""获取成交的区域,根据当前tick的成交价和上个tick的ask和bid价格进行比对
return: order_forward_enum
"""
if CFtdcMdSpi.float_bigger_equal(last_price, pre_ask_price1):
local_order_forward = order_forward_enum.UP
elif CFtdcMdSpi.float_smaller_equal(last_price, pre_bid_price1):
local_order_forward = order_forward_enum.DOWN
else:
if CFtdcMdSpi.float_bigger_equal(last_price, ask_price1):
local_order_forward = order_forward_enum.UP
elif CFtdcMdSpi.float_smaller_equal(last_price, bid_price1):
local_order_forward = order_forward_enum.DOWN
else:
local_order_forward = order_forward_enum.MIDDLE
return local_order_forward
# ----------------------------------------------------------------------
@staticmethod
def get_order_combination(open_interest_delta, volume_delta):
"""根据成交量变化和持仓量的变化计算出对手单的组合
仓位变化方向相反的单
order_opposite
仓位变化方向相同的单
order_similar
"""
open_interest_delta = open_interest_delta if open_interest_delta > 0 else -open_interest_delta
volume_delta_single_side = volume_delta / 2.0
open_close_delta = open_interest_delta - volume_delta_single_side + 0.0
order_similar = volume_delta_single_side / 2 + open_close_delta / 2
order_opposite = volume_delta_single_side / 2 - open_close_delta / 2
return int(order_opposite), int(order_similar)
@staticmethod
def get_delta_str(pre, data):
offset_str = ''
if data > pre:
offset_str = '(+' + str(data - pre) + ")"
elif data < pre:
offset_str = '(-' + str(pre - data) + ")"
else:
pass
return offset_str
def main():
mduserapi=mdapi.CThostFtdcMdApi_CreateFtdcMdApi()
mduserspi=CFtdcMdSpi(mduserapi)
loginfield = mdapi.CThostFtdcReqUserLoginField()
loginfield.BrokerID=""
loginfield.UserID=""
loginfield.Password=""
loginfield.UserProductInfo="python dll"
mduserapi.RegisterFront("tcp://180.168.146.187:10010")
mduserapi.RegisterSpi(mduserspi)
mduserapi.Init()
time.sleep(1)
mduserapi.ReqUserLogin(loginfield,0)
mduserapi.Join()
if __name__ == '__main__':
main()
2、C++代码
C++这块对手单的计算我没写。
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
using namespace std;
#include "ThostFtdcMdApi.h"
#pragma warning(disable:4996)
#define SIMNOW "tcp://180.168.146.187:10010"
TThostFtdcBrokerIDType g_chBrokerID = "";
TThostFtdcUserIDType g_chUserID = "";
TThostFtdcInvestorIDType g_chInvestorID = "";
TThostFtdcPasswordType g_chPassword = "";
class CSimpleHandler : public CThostFtdcMdSpi
{
public:
enum open_interest_delta_forward_enum
{
OPEN, CLOSE, EXCHANGE, NONE, OPENFWDOUBLE, CLOSEFWDOUBLE
};
enum order_forward_enum
{
UP, DOWN, MIDDLE
};
enum tick_type_enum
{
OPENLONG, OPENSHORT, OPENDOUBLE,
CLOSELONG, CLOSESHORT, CLOSEDOUBLE,
EXCHANGELONG, EXCHANGESHORT,
OPENUNKOWN, CLOSEUNKOWN, EXCHANGEUNKOWN,
UNKOWN, NOCHANGE
};
enum tick_color_enum
{
RED, GREEN, WHITE
};
enum tick_type_key_enum
{
TICKTYPE, TICKCOLOR
};
enum opponent_key_enum
{
OPPOSITE, SIMILAR
};
// 构造函数,需要一个有效的指向CThostFtdcMduserApi实例的指针
CSimpleHandler(CThostFtdcMdApi *pUserApi) :
m_pUserApi(pUserApi) {
memset(&m_preDepthMarketData, 0, sizeof(m_preDepthMarketData));
init_tick_type_dict();
init_tick_type_str_dict();
init_handicap_dict();
}
~CSimpleHandler() {}
// 当客户端与交易托管系统建立起通信连接,客户端需要进行登录
virtual void OnFrontConnected()
{
printf("OnFrontConnected. \n");
CThostFtdcReqUserLoginField reqUserLogin;
memset(&reqUserLogin, 0, sizeof(reqUserLogin));
strcpy(reqUserLogin.BrokerID, g_chBrokerID);
strcpy(reqUserLogin.UserID, g_chUserID);
strcpy(reqUserLogin.Password, g_chPassword);
// 发出登陆请求
int ret = m_pUserApi->ReqUserLogin(&reqUserLogin, 1234);
}
// 当客户端与交易托管系统通信连接断开时,该方法被调用
virtual void OnFrontDisconnected(int nReason)
{
// 当发生这个情况后,API会自动重新连接,客户端可不做处理
printf("OnFrontDisconnected.\n");
}
// 当客户端发出登录请求之后,该方法会被调用,通知客户端登录是否成功
virtual void OnRspUserLogin(CThostFtdcRspUserLoginField
*pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool
bIsLast)
{
if (pRspInfo->ErrorID != 0) {
// 端登失败,客户端需进行错误处理
printf("Failed to login, errorcode=%d errormsg=%s requestid = %d chain = %d", pRspInfo->ErrorID, pRspInfo->ErrorMsg, nRequestID, bIsLast);
return;
}
printf("OnRspUserLogin success.\n");
printf("bIsLast[%d]", bIsLast);
printf("nRequestID[%d]", nRequestID);
printf("BrokerID[%s]", pRspUserLogin->BrokerID);
printf("UserID[%s]", pRspUserLogin->UserID);
printf("FrontID[%d]", pRspUserLogin->FrontID);
printf("SessionID[%d]\n\n", pRspUserLogin->SessionID);
char *ppInstrumentID[1];
ppInstrumentID[0] = "T1803";
//ppInstrumentID[0] = "IF1803";
m_pUserApi->SubscribeMarketData(ppInstrumentID, 1);
}
virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo->ErrorID != 0) {
// 端登失败,客户端需进行错误处理
printf("OnRspError, errorcode=%d errormsg=%s requestid = %d chain = %d", pRspInfo->ErrorID, pRspInfo->ErrorMsg, nRequestID, bIsLast);
return;
}
}
virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pSpecificInstrument)
{
printf("InstrumentID[%s]\n", pSpecificInstrument->InstrumentID);
}
else
{
printf("Null OnRspSubMarketData\n");
}
}
virtual void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
{
if (pDepthMarketData && m_preDepthMarketData.LastPrice != 0)
{
// 计算两tick之间的差值
cout << "Volume" << pDepthMarketData->Volume << "PreVolume" << m_preDepthMarketData.Volume << endl;
cout << "OpenInterest" << pDepthMarketData->OpenInterest << "PreOpenInterest" << m_preDepthMarketData.OpenInterest << endl;
double ask_price_delta = m_preDepthMarketData.AskPrice1 - pDepthMarketData->AskPrice1;
int ask_volume_delta = m_preDepthMarketData.AskVolume1 - pDepthMarketData->AskVolume1;
double bid_price_delta = m_preDepthMarketData.BidPrice1 - pDepthMarketData->BidPrice1;
int bid_volume_delta = m_preDepthMarketData.BidVolume1 - pDepthMarketData->BidVolume1;
double last_price_delta = m_preDepthMarketData.LastPrice - pDepthMarketData->LastPrice;
int volume_delta = pDepthMarketData->Volume - m_preDepthMarketData.Volume;
int open_interest_delta = int(pDepthMarketData->OpenInterest - m_preDepthMarketData.OpenInterest);
//编移量的显示字符串
string ask_price_delta_str = get_delta_str(m_preDepthMarketData.AskPrice1, pDepthMarketData->AskPrice1);
string ask_volume_delta_str = get_delta_str(m_preDepthMarketData.AskVolume1, pDepthMarketData->AskVolume1);
string bid_price_delta_str = get_delta_str(m_preDepthMarketData.BidPrice1, pDepthMarketData->BidPrice1);
string bid_volume_delta_str = get_delta_str(m_preDepthMarketData.BidVolume1, pDepthMarketData->BidVolume1);
string last_price_delta_str = get_delta_str(m_preDepthMarketData.LastPrice, pDepthMarketData->LastPrice);
//如果ask或者bid价格对比上一个tick都发生了变化则不显示价格变化幅度
if (ask_price_delta != 0)
ask_volume_delta_str = "";
if (bid_price_delta != 0)
bid_volume_delta_str = "";
//input1 计算订单是在ask范围内成交还是在bid范围内成交
order_forward_enum order_forward = get_order_forward(pDepthMarketData->LastPrice,
pDepthMarketData->AskPrice1, pDepthMarketData->BidPrice1,
m_preDepthMarketData.LastPrice, m_preDepthMarketData.AskPrice1, m_preDepthMarketData.BidPrice1);
//input2 计算仓位变化方向
open_interest_delta_forward_enum open_interest_delta_forward = get_open_interest_delta_forward(open_interest_delta,
volume_delta);
//f(input1, input2) = output1 根据成交区域和仓位变化方向计算出tick的类型
TICK_TYPE tick_type_dict = m_tick_type_dict[open_interest_delta_forward][order_forward];
if (open_interest_delta_forward != open_interest_delta_forward_enum::NONE)
{ //# 输出相关变量
cout << "Ask\t" << pDepthMarketData->AskPrice1 << ask_price_delta_str << "\t" << pDepthMarketData->AskVolume1
<< ask_volume_delta_str << "\tBid\t" << pDepthMarketData->BidPrice1 << bid_price_delta_str << "\t" <<
pDepthMarketData->BidVolume1 << bid_volume_delta_str << endl;
cout << pDepthMarketData->UpdateTime << "." << pDepthMarketData->UpdateMillisec
<< "\t" << pDepthMarketData->LastPrice << last_price_delta_str
<< "\t成交 " << volume_delta
<< "\t增仓 " << open_interest_delta << endl;
cout << m_tick_type_str_dict[tick_type_dict[tick_type_key_enum::TICKTYPE]]
<< "\t" << m_color_type_str_dict[tick_type_dict[tick_type_key_enum::TICKCOLOR]] << endl;
cout<< "--------------------------------------" <<endl;
}
}
else
{
printf("Null depthMarketdata\n");
}
memcpy(&m_preDepthMarketData, pDepthMarketData, sizeof(m_preDepthMarketData));
}
template <typename T>
string get_delta_str(T pre,T data)
{
string offset_str = "";
if (data > pre)
{
offset_str = "(+" + to_string(data - pre) + ")";
}
else if (data < pre)
{
offset_str = "(-" + to_string(pre - data) + ")";
}
return offset_str;
}
open_interest_delta_forward_enum get_open_interest_delta_forward(int open_interest_delta,int volume_delta)
{ /*根据成交量的差和持仓量的差来获取仓位变化的方向
return : open_interest_delta_forward_enum
*/
open_interest_delta_forward_enum local_open_interest_delta_forward;
if (open_interest_delta == 0 && volume_delta == 0)
local_open_interest_delta_forward = open_interest_delta_forward_enum::NONE;
else if (open_interest_delta == 0 && volume_delta > 0)
local_open_interest_delta_forward = open_interest_delta_forward_enum::EXCHANGE;
else if (open_interest_delta > 0)
{
if (open_interest_delta - volume_delta == 0)
local_open_interest_delta_forward = open_interest_delta_forward_enum::OPENFWDOUBLE;
else
local_open_interest_delta_forward = open_interest_delta_forward_enum::OPEN;
}
else if (open_interest_delta < 0 )
{
if (open_interest_delta + volume_delta == 0)
local_open_interest_delta_forward = open_interest_delta_forward_enum::CLOSEFWDOUBLE;
else
local_open_interest_delta_forward = open_interest_delta_forward_enum::CLOSE;
}
return local_open_interest_delta_forward;
}
order_forward_enum get_order_forward(double last_price, double ask_price1, double bid_price1,
double pre_last_price, double pre_ask_price1, double pre_bid_price1)
{
enum order_forward_enum local_order_forward;
//获取成交的区域,根据当前tick的成交价和上个tick的ask和bid价格进行比对
if (last_price >= pre_ask_price1)
{
local_order_forward = order_forward_enum::UP;
}
else if (last_price <= pre_bid_price1)
{
local_order_forward = order_forward_enum::DOWN;
}
else
{
if (last_price >= ask_price1)
{
local_order_forward = order_forward_enum::UP;
}
else if (last_price <= bid_price1)
{
local_order_forward = order_forward_enum::DOWN;
}
else
{
local_order_forward = order_forward_enum::MIDDLE;
}
}
return local_order_forward;
}
void init_tick_type_dict()
{
TICK_TYPE tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::NOCHANGE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::WHITE;
m_tick_type_dict[open_interest_delta_forward_enum::NONE][order_forward_enum::UP] = tick_type;
m_tick_type_dict[open_interest_delta_forward_enum::NONE][order_forward_enum::DOWN] = tick_type;
m_tick_type_dict[open_interest_delta_forward_enum::NONE][order_forward_enum::MIDDLE] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::EXCHANGELONG;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::RED;
m_tick_type_dict[open_interest_delta_forward_enum::EXCHANGE][order_forward_enum::UP] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::EXCHANGESHORT;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::GREEN;
m_tick_type_dict[open_interest_delta_forward_enum::EXCHANGE][order_forward_enum::DOWN] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::EXCHANGEUNKOWN;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::WHITE;
m_tick_type_dict[open_interest_delta_forward_enum::EXCHANGE][order_forward_enum::MIDDLE] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::OPENDOUBLE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::RED;
m_tick_type_dict[open_interest_delta_forward_enum::OPENFWDOUBLE][order_forward_enum::UP] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::OPENDOUBLE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::GREEN;
m_tick_type_dict[open_interest_delta_forward_enum::OPENFWDOUBLE][order_forward_enum::DOWN] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::OPENDOUBLE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::WHITE;
m_tick_type_dict[open_interest_delta_forward_enum::OPENFWDOUBLE][order_forward_enum::MIDDLE] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::OPENLONG;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::RED;
m_tick_type_dict[open_interest_delta_forward_enum::OPEN][order_forward_enum::UP] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::OPENSHORT;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::GREEN;
m_tick_type_dict[open_interest_delta_forward_enum::OPEN][order_forward_enum::DOWN] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::OPENUNKOWN;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::WHITE;
m_tick_type_dict[open_interest_delta_forward_enum::OPEN][order_forward_enum::MIDDLE] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::CLOSEDOUBLE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::RED;
m_tick_type_dict[open_interest_delta_forward_enum::CLOSEFWDOUBLE][order_forward_enum::UP] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::CLOSEDOUBLE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::GREEN;
m_tick_type_dict[open_interest_delta_forward_enum::CLOSEFWDOUBLE][order_forward_enum::DOWN] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::CLOSEDOUBLE;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::WHITE;
m_tick_type_dict[open_interest_delta_forward_enum::CLOSEFWDOUBLE][order_forward_enum::MIDDLE] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::CLOSESHORT;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::RED;
m_tick_type_dict[open_interest_delta_forward_enum::CLOSE][order_forward_enum::UP] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::CLOSELONG;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::GREEN;
m_tick_type_dict[open_interest_delta_forward_enum::CLOSE][order_forward_enum::DOWN] = tick_type;
tick_type[tick_type_key_enum::TICKTYPE] = tick_type_enum::CLOSEUNKOWN;
tick_type[tick_type_key_enum::TICKCOLOR] = tick_color_enum::WHITE;
m_tick_type_dict[open_interest_delta_forward_enum::CLOSE][order_forward_enum::MIDDLE] = tick_type;
}
void init_handicap_dict()
{
m_handicap_dict[tick_type_enum::OPENLONG][opponent_key_enum::OPPOSITE] = tick_type_enum::CLOSELONG;
m_handicap_dict[tick_type_enum::OPENLONG][opponent_key_enum::SIMILAR] = tick_type_enum::OPENSHORT;
m_handicap_dict[tick_type_enum::OPENSHORT][opponent_key_enum::OPPOSITE] = tick_type_enum::CLOSESHORT;
m_handicap_dict[tick_type_enum::OPENSHORT][opponent_key_enum::SIMILAR] = tick_type_enum::OPENLONG;
m_handicap_dict[tick_type_enum::CLOSELONG][opponent_key_enum::OPPOSITE] = tick_type_enum::OPENLONG;
m_handicap_dict[tick_type_enum::CLOSELONG][opponent_key_enum::SIMILAR] = tick_type_enum::CLOSESHORT;
m_handicap_dict[tick_type_enum::CLOSESHORT][opponent_key_enum::OPPOSITE] = tick_type_enum::OPENSHORT;
m_handicap_dict[tick_type_enum::CLOSESHORT][opponent_key_enum::SIMILAR] = tick_type_enum::CLOSELONG;
}
void init_tick_type_str_dict()
{
m_tick_type_str_dict[tick_type_enum::OPENLONG] = "多开";
m_tick_type_str_dict[tick_type_enum::OPENSHORT] = "空开";
m_tick_type_str_dict[tick_type_enum::OPENDOUBLE] = "双开";
m_tick_type_str_dict[tick_type_enum::CLOSELONG] = "多平";
m_tick_type_str_dict[tick_type_enum::CLOSESHORT] = "空平";
m_tick_type_str_dict[tick_type_enum::CLOSEDOUBLE] = "双平";
m_tick_type_str_dict[tick_type_enum::EXCHANGELONG] = "多换";
m_tick_type_str_dict[tick_type_enum::EXCHANGESHORT] = "空换";
m_tick_type_str_dict[tick_type_enum::OPENUNKOWN] = "未知开仓";
m_tick_type_str_dict[tick_type_enum::CLOSEUNKOWN] = "未知平仓";
m_tick_type_str_dict[tick_type_enum::EXCHANGEUNKOWN] = "未知换仓";
m_tick_type_str_dict[tick_type_enum::UNKOWN] = "未知";
m_tick_type_str_dict[tick_type_enum::NOCHANGE] = "没有变化";
m_color_type_str_dict[tick_color_enum::RED] = "红";
m_color_type_str_dict[tick_color_enum::GREEN] = "绿";
m_color_type_str_dict[tick_color_enum::WHITE] = "白";
}
private:
// 指向CThostFtdcMduserApi实例的指针
CThostFtdcMdApi *m_pUserApi;
CThostFtdcDepthMarketDataField m_preDepthMarketData;
typedef map<tick_type_key_enum, int> TICK_TYPE;
typedef map<open_interest_delta_forward_enum, map<order_forward_enum, TICK_TYPE>> TICK_TYPE_DICT;
TICK_TYPE_DICT m_tick_type_dict;
typedef map<tick_type_enum, map<opponent_key_enum, int> > HANDICAP_DICT;
HANDICAP_DICT m_handicap_dict;
typedef map<int, string> TICK_TYPE_STR_DICT;
TICK_TYPE_STR_DICT m_tick_type_str_dict;
TICK_TYPE_STR_DICT m_color_type_str_dict;
};
int main()
{
// 产生一个CThostFtdcTraderApi实例
CThostFtdcMdApi *pUserApi = CThostFtdcMdApi::CreateFtdcMdApi();
printf("ApiVersion[%s]\n", pUserApi->GetApiVersion());
// 产生一个事件处理的实例
CSimpleHandler sh(pUserApi);
// 注册一事件处理的实例
pUserApi->RegisterSpi(&sh);
pUserApi->RegisterFront(SIMNOW);
pUserApi->Init();
pUserApi->Join();
// 释放API实例
pUserApi->Release();
return 0;
}