程序化交易

几年前帮朋友写程序化交易的代码,写了一个样例作为基础,后来在此基础上做了些开发。现在把步骤简单记录一下。

 

首先下载CTP交易接口

https://www.citicsf.com/download/ctp/

我下载了linux版本tradeapi(V6.3.5/6.3.6)

 

下载后解压,得到32位和64位动态库,分别放在两个文件夹中

d1370c7f9cfcf9abdfb86006d67d47f3b67.jpg

 

根据本机的操作系统,选择合适的版本,将其内的文件复制到合适的位置

019996d4321cf5c3e831bbe8fff1543f602.jpg

比如将thostmduserapi.so和thosttraderapi.so放到lib文件夹,而*.h文件则放到include文件夹下,剩下的两个文件定义了标准错误信息,但写程序的时候用不到。

这样在Demo文件夹中就构造了如下路径,lib包含了两个*.so文件,include包含了4个*.h文件,src中则包含了样例源文件

96fa9c75763d6b5cc82e8df634ddf5160f8.jpg

其中conn中的文件是自动生成的。

 

接下来看看make文件

SRCS := $(wildcard src/*.cpp)
OBJS := $(patsubst %.cpp, %.o, $(SRCS))
CPP = g++
LIBS = $(wildcard lib/*.so)
INCS = -Iinclude
#FLAGS = -Wformat=0
FLAGS =
EXEC = run.exe

all: $(OBJS)
        $(CPP) -o $(EXEC) $(OBJS) $(LIBS) $(FLAGS)

$(OBJS): %.o:%.cpp
        $(CPP) -c $< -o $@ $(FLAGS) $(INCS)

.PHONY: clean
clean:
        rm $(OBJS) $(EXEC)

该文件自动将src中的*.cpp文件替换为*.o文件,并作为生成目标,将lib中的*.so文件作为链接库,最终连接为可执行文件run.exe

 

最后看看源文件quotaapitest.cpp

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <semaphore.h>
#include "ThostFtdcMdApi.h"

char* FrontAddress = "tcp://ctp1-md1.citicsf.com:41213";
//char* FrontAddress = "tcp://asp-sim2-md1.financial-trading-platform.com:26213";
char* BrokerID = "6666";   // 中信期货的平台ID
//char* BrokerID = "2030";
char* InvestorID = "000023";   // 申请到的投资者账号
char* Password = "88888888";   // 设置的投资者密码

sem_t g_hEvent;

TThostFtdcBrokerIDType g_chBrokerID;
TThostFtdcUserIDType g_chUserID;

class CSimpleHandler : public CThostFtdcMdSpi
{
public:
  CSimpleHandler(CThostFtdcMdApi *pUserApi) : 
    m_pUserApi(pUserApi), requestID(0) {}
  ~CSimpleHandler() {}

  virtual void OnFrontConnected()
  {
    printf("OnFrontConnected!\n");
    CThostFtdcReqUserLoginField reqUserLogin;
    //printf("BrokerID:");
    //scanf("%s", &g_chBrokerID);
    strcpy(reqUserLogin.BrokerID, BrokerID);

    //printf("userid:");
    //scanf("%s", &g_chUserID);
    strcpy(reqUserLogin.UserID, InvestorID);

    //printf("password:");
    //scanf("%s", &reqUserLogin.Password);
    strcpy(reqUserLogin.Password, Password);

    int ret = m_pUserApi->ReqUserLogin(&reqUserLogin, requestID++);
  }

  virtual void OnFrontDisconnected(int nReason)
  {
    printf("OnFrontDisconnected.\n");
  }

  virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
			      CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
  {
    printf("OnRspUserLogin:\n");
    printf("ErrorCode = [%d], ErrorMsg = [%s]\n", pRspInfo->ErrorID,
	   pRspInfo->ErrorMsg);
    printf("RequestID = [%d], Chain = [%d]\n", nRequestID, bIsLast);

    printf("SHFETime = %s\n", pRspUserLogin->SHFETime);
    printf("DCETime = %s\n", pRspUserLogin->DCETime);
    printf("CZCETime = %s\n", pRspUserLogin->CZCETime);
    printf("FFEXTime = %s\n", pRspUserLogin->FFEXTime);
    printf("INETime = %s\n", pRspUserLogin->INETime);

    if(pRspInfo->ErrorID != 0)
      {
	printf("Failed to login, errorcode = %d errormsg = %s  requestid = %d chain = %d",
	       pRspInfo->ErrorID, pRspInfo->ErrorMsg, nRequestID, bIsLast);
	exit(-1);
      }

    char* Instrument[] = {"cu1608", "cu1606"};  // 注意品种的大小写
    int ret1 = m_pUserApi->SubscribeMarketData(Instrument, 2);
    //int ret2 = m_pUserApi->UnSubscribeMarketData(Instrument, 2);
    int ret3 = m_pUserApi->SubscribeForQuoteRsp(Instrument, 2);
    //int ret4 = m_pUserApi->UnSubscribeForQuoteRsp(Instrument, 2);
  }

  virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
  {
    printf("OnRspSubMarketData:\n");
    printf("ErrorCode = [%d], ErrorMsg = [%s]\n", 
	   pRspInfo->ErrorID, pRspInfo->ErrorMsg);
    printf("RequestID = [%d], Chain = [%d]\n", nRequestID, bIsLast);

    printf("InstrumentID = %s\n", pSpecificInstrument->InstrumentID);
  }
  
  virtual void OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
  {
    printf("OnRspUnSubMarketData:\n");
  }

  virtual void OnRspSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
  {
    printf("OnRspSubForQuoteRsp:\n");
    printf("ErrorCode = [%d], ErrorMsg = [%s]\n", 
	   pRspInfo->ErrorID, pRspInfo->ErrorMsg);
    printf("RequestID = [%d], Chain = [%d]\n", nRequestID, bIsLast);

    printf("InstrumentID = %s\n", pSpecificInstrument->InstrumentID);
  }

  virtual void OnRspUnSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
  {
    printf("OnRspUnSubForQuoteRsp:\n");
  }

  virtual void OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp)
  {
    printf("OnRtnForQuoteRsp:\n");
  }

  virtual void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
  {
    printf("Info: Received market data: %s\n Info: Last price: %g\n Info: Update time: %s\n",
	   pDepthMarketData->InstrumentID, pDepthMarketData->LastPrice, pDepthMarketData->UpdateTime);

    sem_post(&g_hEvent);
  }

  virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
  {
    printf("OnRspError:\n");
    printf("ErrorCode = [%d], ErrorMsg[%s]\n", 
	   pRspInfo->ErrorID, pRspInfo->ErrorMsg);
    printf("RequestID = [%d], Chain = [%d]\n", nRequestID, bIsLast);
  }

  virtual void OnHeartBeatWarning(int nTimeLapse)
  {
    printf("time out: %d\n", nTimeLapse);
  }

private:
  CThostFtdcMdApi *m_pUserApi;
  int requestID;
};

int main()
{
  sem_init(&g_hEvent, 0, 0);

  CThostFtdcMdApi* pUserApi = CThostFtdcMdApi::CreateFtdcMdApi("./conn/", false);
  CSimpleHandler sh(pUserApi);
  pUserApi->RegisterSpi(&sh);

  //pUserApi->SubscribePublicTopic(THOST_TERT_RESTART);
  //pUserApi->SubscribePrivateTopic(THOST_TERT_RESTART);

  pUserApi->RegisterFront(FrontAddress);
  pUserApi->Init();

  printf("date: %s\n", pUserApi->GetTradingDay());
  printf("vertion: %s\n", pUserApi->GetApiVersion());

  sem_wait(&g_hEvent);
  pUserApi->Join();
  pUserApi->Release();

  return 0;
}

 

时间有点久了,需要修改一下品种的代码,但基本流程都列出了,函数名意义也比较清晰,在此做个记录,有空再整理一下。(如果运行时报错,可能需要把lib目录设置为LD_LIBRARY_PATH的值,即在Demo目录中执行export LD_LIBRARY_PATH="lib:$LD_LIBRARY_PATH"后再运行run.exe)

转载于:https://my.oschina.net/propagator/blog/1855840

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值