量化日志——用python接入上期所CTP的C++源码API做看穿式测试撸坑详细全流程

一、前言
作为一名程序员,能用代码自动化解决的问题就绝不动手动脑苦哈哈
包括投资炒股炒期货。
所以就诞生了一门学问叫做量化自动化交易。
量化自动交易既可以用数学公式策略因子去分析一个票值不值得投,什么时候买,什么时候卖,买多少卖多少,还可以自动化执行交易,不用每天盯盘费脑费神费时,屏蔽掉人性中天生固有的难以控制的恐惧与贪婪对交易行为的扭曲。还可以通过把历史交易数据保留下来,不在同一个坑上跌跟头,让经验有效化。还可以通过使用这些数据进行数据回测,检验自己的策略如果放在以往的交易日的正确性。
用数学和代码进行量化交易的构思最先在一个叫做西蒙斯的美国数学家脑中诞生并得以发扬光大。
他成立了一家量化交易公司,叫做文艺复兴科技公司,从1988年至2018年的三十年间,大奖章基金的年化收益率高达66.1%,在2008年全球金融危机爆发时,文艺复兴公司的投资收益还是正的。西蒙斯因量化投资而致身家超2000亿。
所以,当你那个开着一辆路虎的小学肄业的同学问你读书有什么用时你可以跟他讲一下这个事迹。学道若能精用,则潜能极深,底蕴极厚极悠长。如果你硕博连读,考试天下无敌,可至今还孑然一身,你怀疑人生时,可能那是由于你还没精用。知行合一,是要行好久才能合于知的。
当然,有着相同聪明脑子的聪明人总是有着相同想法,同时在起步做量化交易的除了文艺复兴还有其他公司,比如,和文艺复兴一时瑜亮,竞争同一批投资人的,德邵。关于德邵,这又是另一个精彩的话题了。
往前,还有量化始祖——麻省理工的数学家,拉斯维加斯算牌高手,宽客之父爱德华索普。爱德华索普和凯利公式的发明者拉里凯利,信息论之父香农都互有交集互有启发。著名赌牌电影《决胜21点》原型——华裔赌神马凯文所做过的事,硬核数学家爱德华索普早就做过,他们通过数学计算牌面的概率和收益期望在赌场大杀四方。这又是另一个精彩的话题了。
但大家一致认同的在量化上做得最成功的数学是西蒙斯。
在我关注西蒙斯后不久的今年,西蒙斯与世长辞了。
接下来,就是你我的时代。
所以,还等什么,你和西蒙斯之间的距离,可能只剩下一门量化课程了。
好,接下来转入正题,说一下股票和期货的量化接入起手式。
下面发车,驾驶证要求:懂程序开发和基本的交易知识。
首先,就是股票了,这块门槛比较高,比如交易接口和行情接口都需要入金达到标准的,并且很高,比如,要20万。我用的是国盛通,由于有内部优惠,注册入金就可以直接开通量化权限(有需要可以加V15381125473,包括下面的期货量化接入到时也是可以一并咨询的)。开通权限后他们给你提供一个量化交易软件,比如国盛通掘金和国盛通PTrader,你联系客户经理填一个表格,收集IP和电脑的MAC地址之后就可以直接使用量化软件,在里面写代码调用他们数据和交易了。软件里还集成了一些开发好的策略可以供你参考,唯一的问题就是软件关闭后策略就停止了,所以你策略运行期间要保证电脑不断电不关机!
股票不是今天的重点,我已经写了一些量化策略在上面运行,目前效果还不太好,需要继续调优,唯一的优点就是我可以再也不用看盘安心的上班了。
接下来讲讲期货量化平台的全流程接入,我把我接入过程中的坑全部撸出来,顺口一提,西蒙斯当初刚开始做量化时也是从期货开始做的。在中国,期货可以T+0,既可以多也可以空,技术指标有效度较高,用来做量化也是比较合适的。
二、准备工作
期货我用的正信期货,量化接入无入金门槛。
首先第一步,你得开个正信期货的交易账号,然后加上客户经理,你跟他说你需要接入量化平台他就会帮你走流程的了,他会发一些文档给你填,主要的就是软件标识(APPID)这个,填写要求:client(固定)_软件名(英文,随便填)_(数字,随便填,我填的1.0),然后系统类型就填客户自研系统,其他的一些填写他会发一个模板给你直接照着填就好,不懂填的就直接问客户经理好了,填好转发给客户经理确认后然后打印出来拍照发给客户经理,拍完纸质文档记得留住,后面流程完成后还需要邮寄给客户经理的。
文档这一步骤过完后接下来他会邮箱发你一个文档压缩包然后把你拉进他们的技术对接群,邮件里面有一份文档填有你的测试系统仿真的交易和行情IP端口和账号密码以及APPID对应的AuthCode,还有上期所的API地址http://www.sfit.com.cn/5_2_DocumentDown_2.htm,broker id 用于标识你的交易商。对接测试系统时用来给券商那边收集你的IP和MAC地址等信息的,仿真系统用于对接看你的报单、撤单等代码功能能否成功流转到交易所那边的。账号密码可以直接登录行情端口,要登录交易端口的话需要先用APPID和AuthCode调用认证函数认证成功后再用登录函数登录。

首先,到上期所网站下载一份评测版的API,要注意是评测版的不是生产版本的!评测系统的账号密码认证码不能用来登录生产的版本的API,仿真系统的账号密码认证码才可以。

但是呢,他交易所提供的这个API是用C++写的,但是我们平时处理数据都是用python更好使,而且C++学起来用起来也比较难,所以接下来就要进入到第二步了:CTP的C++代码转编译为python可调用的代码。
三、CTP源码转化为Python
从上期所下载的api文件包文件内容长这样子:



由于Api是C++写的,所以我们需要转译成python能用的代码,首先我们下载一个跨语言调用工具swig,这里给出链接:链接:https://pan.baidu.com/s/1zKwKl79KXgW5eUOzW_sNyA?pwd=xjeq 提取码:xjeq 。解压缩之后添加安装包路径到环境变量即可使用swig命令,在cmd命令行敲下swig命令出现如下所示即表明安装成功。

安装python环境变量,这一步不多说,网上教程很多。
解压缩CTP的api压缩包,在文件夹里新建一个文件thosttraderapi.i,内容如下:
%module(directors="1") thosttraderapi
%{
#include "ThostFtdcTraderApi.h"
#include "iconv.h"
%}
%typemap(out) char[ANY], char[] {
if ($1) {
iconv_t cd = iconv_open("utf-8", "gb2312");
if (cd != reinterpret_cast<iconv_t>(-1)) {
char buf[4096] = {};
char **in = &$1;
char *out = buf;
size_t inlen = strlen($1), outlen = 4096;
if (iconv(cd, (const char **)in, &inlen, &out, &outlen) != static_cast<size_t>(-1))
{
size_t size = outlen;
while (size && (buf[size - 1] == '\0')) --size;
resultobj = SWIG_FromCharPtrAndSize(buf, size);
}
iconv_close(cd);
}
}
}
%feature("director") CThostFtdcTraderSpi;
%ignore THOST_FTDC_VTC_BankBankToFuture;
%ignore THOST_FTDC_VTC_BankFutureToBank;
%ignore THOST_FTDC_VTC_FutureBankToFuture;
%ignore THOST_FTDC_VTC_FutureFutureToBank;
%ignore THOST_FTDC_FTC_BankLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BrokerLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BankLaunchBrokerToBank;
%ignore THOST_FTDC_FTC_BrokerLaunchBrokerToBank;
%feature("director") CThostFtdcTraderSpi;
%include "ThostFtdcUserApiDataType.h"
%include "ThostFtdcUserApiStruct.h"
%include "ThostFtdcTraderApi.h"
以上代码是我参考其他博客大佬的,应该问题不大,其实CTP转python现成的源码其他博客已经附有,但是交易这么重要的事还是决定自己转一遍才感到安全放心。
cmd进入CTP的api解压缩文件夹路径里,执行命令:swig -threads -c++ -python thosttraderapi.i,看到文件夹里新增加了几个文件:

然后打开Visual Studio 2022,我这里是2022版的,贼难用,出了很多问题要自己一点点摸索去解决。
点新建项目,选控制台应用:


项目名称填CTP API解压缩后的文件夹名称,位置填文件夹所在的文件路径。

分别右键头文件和源文件——添加——现有项,选择CTP API文件夹里面的内容如上图所示,我看有的教程并不需要这一步,可能是因为项目路径已经选在解压缩后的文件夹,工程可以自动读到,但是我不添加进来的话后面打包出来的dll文件使用时会报:“找不到文件_thosttraderapi”的错,这一步让我琢磨老久,所以这里必须要这样引入一下。
下面进入配置项,右键工程选择属性进入界面:

配置选Release,平台填x64,常规那里的配置类型选动态库.dll,不这样选的话后面打包会报不是合法可用的dll文件或者文件过大需要用\bigobj编译这些奇奇怪怪的报错,而且这些报错在其他博客搜通常都没有正确答案。

在C/C++的附加包含目录这里填上你python所在目录的include文件夹,因为他打包编译你的文件需要用到python代码库,其他博客写是需要填这一步,但是不知道是不是因为我的VS编译器的问题,我这样设置并没有起作用,依然会报”找不到Python.h文件”这样的与python类型文件找不到相关的编译报错问题,需要到后面的步骤才能解决,但因为别的博客有这一步,我也姑且保留这一步吧。

链接器这里的输入,附加依赖项要把你的python环境的lib文件路径加上文件名填上,我的是C:\Users\lkwai\AppData\Local\Programs\Python\Python38\libs\python38.lib,然后后面加个分号填上你的thosttraderapi_se.lib的文件路径加文件名,这个文件是CTP API解压缩里面的一个文件,我怕VS读不到把他直接放到python38.lib同一个文件路径下了。这一步如果没有填对的话会报无法打开文件python.lib或者不是合法的win32文件或者不是合法的dll。而且这里要把从父级或项目默认设置继承这个取消勾选,不然他会把文件名自动加上.obj扩展然后报打不开xxx.obj文件,这个报错我琢磨了好久,后来才自己摸索解决掉,但按道理这个东西不需要搞,也许是因为我别的没配置对,你们按需进行设置吧。

上面如果大家不知道自己的python安装目录在哪的话,可以用cmd命令行,键入where python,就会出现好几个路径,通常是第一个路径,我的就是第一个。

接下来的这一步很重要了,也是参考别的博客的,在C/C++里填的附加包含目录不起效之后,我看有的博客说是要在VC++选项里把包含目录和外部包含目录填成自己的python所在的include目录,但是我在这里填了也起不到效果,依然报“打不开python.h”这一类的找不到python文件相关的错误的,后面我干脆直接把python include文件夹的文件引入到VS项目的头文件和源文件中倒是不报找不到python文件相关的错误了,但是可能因为引入的文件太多,导致报了文件太大无法编译需要用bigobj命令运行的错误。我在这个地方停了好久,盯着屏幕快把眼睛瞅瞎了才发现华点。在VC++目录的包含目录的选项里,点进编辑里,在填的值为空时,下面计算的值那里,显示的就是VS编译器默认读取包含文件的地方,我把python的include目录下的文件包括cpython文件夹全拷进那个默认目录里,然后,就能成功读取到python文件了。

这里最后还会报个“打不开puh.h文件”的错误,但是我在python的include文件夹里找了半天眼睛都找出屎来了可是都没有找到,我百思不得其姐,我不李姐。然后我新建个空的文件,命名为puh.h同样扔进默认的include文件夹就解决了,puh.h文件是编译默认会产生的文件,但是由于我的项目可能由于配置错误并没有自动产生所以才报的错,所以至此我能确认,我的VS的确大概是抽风了。
最后,把主页面的release和x64勾上,点击调试,忽略弹出来的不是有效的win32程序,能看到调试信息里的成功字样就是编译打包成功了。

上图所示就是生成成功了,还显示出了生成的文件所在的文件路径。
我们进入到该文件路径,把带有dll文件后缀的文件拷进之前CTP API的文件夹里,把文件名改成_thosttraderapi.pyd,然后用python编译器pycharm打开该文件夹。

自己在pycharm里写一个python文件,然后调用封装过的api,运行,没报错,只提示没有报单权限,那是因为用测试账号的登录的生产API是没法报单的。OK,大功告成,下面讲解下看穿式测试代码流程。

四、CTP PYTHON登录认证报单撤单代码流程
下面是代码总体结构:


下面一一来讲解这几块代码都是干啥的。
if __name__ == ‘__main__’这一块不多说了,main()函数也不多说了,就是调用各个API函数拼装成流程。
def main():
tradeapi = api.CThostFtdcTraderApi_CreateFtdcTraderApi()
tradespi = CTradeSpi(tradeapi)
tradeapi.RegisterSpi(tradespi)
tradeapi.RegisterFront(FrontAddr)
tradeapi.SubscribePrivateTopic(api.THOST_TERT_QUICK)
tradeapi.SubscribePublicTopic(api.THOST_TERT_QUICK)
tradeapi.Init()
tradeapi.Join()
print("good job")
在thosttraderapi.py末尾还需要加上以下两个函数,用于向外提供CThostFtdcTraderSpi的对象以及版本信息
def CThostFtdcTraderApi_CreateFtdcTraderApi(*args) -> "CThostFtdcTraderApi *":
return _thosttraderapi.CThostFtdcTraderApi_CreateFtdcTraderApi(*args)
def CThostFtdcTraderApi_GetApiVersion() -> "char const *":
return _thosttraderapi.CThostFtdcTraderApi_GetApiVersion()
ReqorderfieldInsert:在此填充报单时需要填充的参数,具体某个字段什么含义就不过多赘述了,百度都能查到,所赋值的参数值都是我在前面定义好的,具体代码如下:
def ReqorderfieldInsert(tradeapi):
print("ReqOrderInsert Start")
# 获取参数属性的类
orderfield = api.CThostFtdcInputOrderField()
# 交易商标识
orderfield.BrokerID = BROKERID
# 合约代码 买卖标的
orderfield.InstrumentID = INSTRUMENTID
# 用户ID
orderfield.UserID = USERID
orderfield.InvestorID = USERID
# 交易方向, 多空平今平昨
orderfield.Direction = DIRECTION
# 报单价格
orderfield.LimitPrice = PRICE
# 报单数量
orderfield.VolumeTotalOriginal = VOLUME
# 报价单类型, 限价单按指定价格交易, 市价单按当前市场价交易
orderfield.OrderPriceType = api.THOST_FTDC_OPT_LimitPrice
# 触发条件,等于当前市价触发或者等于卖一价触发或者立刻按当前价成交等
orderfield.ContingentCondition = api.THOST_FTDC_CC_Immediately
# 条件单有效期
orderfield.TimeCondition = api.THOST_FTDC_TC_GFD
# 成交量条件 就是你的单子不会全部成交你希望最大数量成交还是最小数量成交
orderfield.VolumeCondition = api.THOST_FTDC_VC_AV
# 投机套保标志, 1表示投机仓,与对冲风险的货商区别
orderfield.CombHedgeFlag = "1"
# 平今指令,下平仓指令和平昨指令等
orderfield.CombOffsetFlag = OFFSET
# GTD日期 当前交易日 未使用不知道有什么用
orderfield.GTDDate = ""
# 报单引用,必须是一个递增的数值,相当于报单编号,用于后续获取报单的成交情况的
orderfield.OrderRef = "1"
# 最小成交量 为0意味着不需要最小成交量
orderfield.MinVolume = 0
# 非强平
orderfield.ForceCloseReason = api.THOST_FTDC_FCC_NotForceClose
# 自动挂起标识,必填0
orderfield.IsAutoSuspend = 0
# 调用底层API的报单函数
tradeapi.ReqOrderInsert(orderfield, 0)
print("ReqOrderInsert End")
下面新建的CTradeSpi类是对C++的CThostFtdcTraderSpi虚类的继承与实现,CTP-API规定了对底层API的调用需要继承底层C++的虚类以及实现里面的函数。
实现了CThostFtdcTraderSpi类里面的函数就是实现了登录认证报单撤单等交易流程。
def OnFrontConnected(self) -> "void":
print("OnFrontConnected")
authfield = api.CThostFtdcReqAuthenticateField()
authfield.BrokerID = BROKERID
authfield.UserID = USERID
authfield.Password = PASSWORD
authfield.AppID = APPID
authfield.AuthCode = AUTHCODE
# loginfield.UserProductInfo = "python dll"
print("send auth ready")
self.tapi.ReqAuthenticate(authfield, 0)
print("send auth ok")
print("OnFrontConnected")
当客户端与交易后台建立起通信连接时(还未登录前),也就是刚和交易所的IP地址建立起一次会话连接成功时,该方法会响应式调用。也就是在main函数的tradeapi.RegisterFront(FrontAddr)调用成功时,该OnFrontConnected方法才会被执行。
一般在OnFrontConnected中,进行appid和authcode的认证,要先认证成功后登录,不然会报“该用户没有认证”的错误。
def OnRspAuthenticate(self, pRspAuthenticateField: 'CThostFtdcRspAuthenticateField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
rsp = api.CThostFtdcRspAuthenticateField()
print("OnRspAuthenticate")
rsp.UserID = USERID
rsp.AppID = APPID
rsp.BrokerID = BROKERID
print("auth result:", pRspInfo.ErrorMsg)
print("认证成功,APPID为:", APPID, ",认证码信息为:", AUTHCODE)
# self.tapi.ReqQrySettlementInfo(rsp, 0)
if not pRspInfo.ErrorID:
print("OnRspAuthenticate done")
loginfield = api.CThostFtdcReqUserLoginField()
loginfield.BrokerID = BROKERID
loginfield.UserID = USERID
loginfield.Password = PASSWORD
loginfield.UserProductInfo = "python dll"
self.tapi.ReqUserLogin(loginfield, 0)
print("send login ok")
上面是认证成功后交易所的回调函数,他会把是否认证成功,错误信息等返回给调用者,在这个函数里判断认证成功后再登录,之前一直在OnFrontConnected函数里进行登录,一直报“未认证”的错误。
def OnRspUserLogin(self, pRspUserLogin: 'CThostFtdcRspUserLoginField', pRspInfo: 'CThostFtdcRspInfoField',
nRequestID: 'int', bIsLast: 'bool') -> "void":
qryinfofield = api.CThostFtdcQrySettlementInfoField()
qryinfofield.BrokerID = BROKERID
qryinfofield.InvestorID = USERID
qryinfofield.TradingDay = pRspUserLogin.TradingDay
print("OnRspUserLogin")
print("TradingDay=", pRspUserLogin.TradingDay)
print("SessionID=", pRspUserLogin.SessionID)
print("ErrorID=", pRspInfo.ErrorID)
print("ErrorInfo3=", pRspInfo)
print("ErrorMsg=", pRspInfo.ErrorMsg)
print("登录成功,用户ID为:", USERID)
self.tapi.ReqQrySettlementInfo(qryinfofield, 0)
print("send ReqQrySettlementInfo ok")
上面是登录回调函数,可以在里面查看登录成功失败的信息,登录失败的错误码,然后登录成功后可以在里面查询投资者结算结果。就是相当于你打开期货APP时一般会收到的期货交易结算单,里面有交易信息还有手续费,盈亏等信息。
def OnRspQrySettlementInfo(self, pSettlementInfo: 'CThostFtdcSettlementInfoField',
pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
print("OnRspQrySettlementInfo")
if pSettlementInfo is not None:
print("content:", pSettlementInfo.Content)
else:
print("content null")
if bIsLast:
pSettlementInfoConfirm = api.CThostFtdcSettlementInfoConfirmField()
pSettlementInfoConfirm.BrokerID = BROKERID
pSettlementInfoConfirm.InvestorID = USERID
self.tapi.ReqSettlementInfoConfirm(pSettlementInfoConfirm, 0)
print("send ReqSettlementInfoConfirm ok")
上面是查询投资者结算结果响应函数,可以在里面查询成交信息。还有可以进行投资者结算结果确认。
def OnRspSettlementInfoConfirm(self, pSettlementInfoConfirm: 'CThostFtdcSettlementInfoConfirmField',
pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool') -> "void":
print("OnRspSettlementInfoConfirm")
print("ErrorID=", pRspInfo.ErrorID)
print("ErrorInfo1=", pRspInfo)
print("ErrorMsg=", pRspInfo.ErrorMsg)
ReqorderfieldInsert(self.tapi)
print("send ReqorderfieldInsert ok")
上面是投资者结算结果确认响应函数,在里面可以查询结算结果确认是否成功,然后在这一步调用ReqorderfieldInsert函数进行报单录入。
def OnRspOrderInsert(self, pInputOrder: 'CThostFtdcInputOrderField', pRspInfo: 'CThostFtdcRspInfoField',
nRequestID: 'int', bIsLast: 'bool') -> "void":
print("OnRspOrderInsert")
print("ErrorID=", pRspInfo.ErrorID)
print("ErrorInfo2=", pRspInfo)
print("ErrorMsg=", pRspInfo.ErrorMsg)
上面是报单录入响应函数,能让你知道是否把报单成功提交到交易所了。
def OnRtnOrder(self, pOrder: 'CThostFtdcOrderField') -> "void":
print("OnRtnOrder")
print("APPID为:", APPID, ",认证码信息为:", AUTHCODE)
print("OrderStatus=", pOrder.OrderStatus)
print("合约=", INSTRUMENTID)
print("StatusMsg=", pOrder.StatusMsg)
print("LimitPrice=", pOrder.LimitPrice)
# self.tapi.ReqorderfieldAction(pOrder.OrderSysID, pOrder.ExchangeID, pOrder.InstrumentID)
key = f"{pOrder.FrontID}_{pOrder.SessionID}_{pOrder.OrderRef}".replace(' ', '')
print(key)
## 如果未成交,5秒后主动撤单
if pOrder.OrderStatus is api.THOST_FTDC_OST_NoTradeQueueing:
print("撤单")
thread = threading.Thread(target=self.ReqorderfieldAction,
args=(pOrder.OrderSysID, pOrder.ExchangeID, pOrder.InstrumentID))
thread.start()
thread.join()
print("撤单是否成功:", pOrder.StatusMsg)
上面是报单通知响应函数,就是能查看,你的报单成功提交到交易所之后他的成交状况,在这里你可以进行撤单操作,每一个成功提交到交易所的报单或撤单操作都会有一次OnRtnOrder函数的被触发,所以这里要加一下多线程threading.Thread。
def ReqorderfieldAction(self, OrderSysID, ExchangeID, InstrumentID):
"""撤单操作(第一种方式OrderSysID)"""
print("ReqorderfieldAction")
orderfield = api.CThostFtdcInputOrderActionField()
orderfield.BrokerID = BROKERID
orderfield.UserID = USERID
orderfield.InvestorID = USERID
orderfield.OrderSysID = OrderSysID
orderfield.ExchangeID = ExchangeID
orderfield.InstrumentID = InstrumentID
orderfield.ActionFlag = api.THOST_FTDC_AF_Delete
self.tapi.ReqOrderAction(orderfield, 0)
print('send ReqOrderAction: ' + orderfield)
上面是撤单函数,根据前面说的报单索引编码对该报单进行撤单操作,撤单是否成功的信息在OnRtnOrder进行回调显示。
OK,以上代码调用流程完善,点击运行。

大功告成。
可以把控制台的运行结果截图提交给交易商的技术对接人,让他们给你走完量化接入流程了。注意截图要先包含评测系统的成功登录信息还有USERID、APPID和AUTHCODE,然后成功认证登录仿真系统(仿真账号用生产API,生产API也可以用来登实盘账户进行实盘交易)的登录信息还有报单成功交易信息和撤单成功信息。评测系统主要用来收集你的登录的
把文档(主要是评测报告那一份文档)填好,截图提交,下一个交易日他们就会发邮件给你,提供量化交易的IP端口和broker id经纪公司代码了,账号密码就是你原来刚开户的账号密码,APPID和AUTHCODE还是一开始那个,然后你还可以向你的客户经理申请仿真账号(和前面的仿真账号有区别)用来做数据回测策略验证的,不过仿真账号需要先下载登录他们的仿真系统修改密码才能使用。
有些代码运行时的报单返回错误信息要和交易商的技术客服交流过才知道问题在哪的,我就遇到过,比如,他们给了一个非仿真系统账号给我,导致一直报没有报单权限的错误,我百思不得其姐,后来他们检查过给了一个正确的账号就解决了。比如在非交易时段,他们仿真系统是没有夜盘功能的,这时运行会报“当前状态禁止此项操作”。比如他们的仿真系统运行的数据不是实盘数据,你填的报价单的价格会无法成交,或者你填的品种仿真系统没有,都需要技术客服提供的。
以上,以上,就是我接入量化过程中栽过的所有的坑了,已经记录得非常详细了,前人种树后人乘凉,留给后来者了。
五、最后聊聊
我的背景
我是一个干了5年开发的没有级的程序员,在数个外包公司蹉跎了岁月。不是因为公司太不当人人不够还不招人把剩下的人当牛马我把公司噶了,就是公司为了裁猿广进把我噶了。
目前在一家不卷也不倦的外包干活,业务时间学量化,AI,区块链,Rust,Go,架构,爬虫,鸿蒙这些。
想想看我报了很多的课,能算得上是程序员里的韭菜战斗机了。其实学来主要不是为了升职加薪,纯纯是因为我从小求知欲特别旺盛,当学习是一种纯个人的兴趣爱好了。但是碰到不良的割菜培训机构,有时候还是很心痛的。下面罗列一下我报过的课,不算打广告,有些还是有点坑的,注意甄别。
1、马士兵MCA架构&大数据双料架构师课,这课还顺带开了个马士兵黑金级永久会员,即使课一直没学完(2020年报的),可是和客服老师们聊天还挺开心,然后2023年又报了个AIOT课,这个倒是在辞职的三个月里学完了,但是工作没得找到,缺项目,目前在复习中。
2、学车,深圳白石龙银通驾校的。
3、拉勾教育的大数据,2020年报的,裸辞出来才学了两个月两个模块,然后因为第一裸辞经验不足,听说社保断交几个月会怎样怎样被吓倒了,赶紧面试了几个周拿到个工作上班去也,至今学习进度再也没进展了。现在拉勾教育好像噶了,连客户老师小姐姐都不发广告给我了。
4、新芯设计,2023年和马士兵的AIOT同期报的,因为忙着学AIOT就再也没进展了,只看过两节课。
5、卷子牙老师的硬核自制操作系统开发课,也是2023年和AIOT同期学的,所以,也没得进展。
6、风变编程的量化交易,2023年那会裸辞,想着我躺平学习了没收入咋办,于是把开户多年的期货捡起来,做起了交易,但是当时天天盯盘又导致我没得心思和时间去学习了,于是想着自己学的AIOT里既然已经有数据分析了,还有python,于是打算把数据分析和自动化交易结合起来,那样自己就不用看盘了,于是又去报了个量化,目前正在学当中,进展尚可,但是学了发现对于我这个程序员没啥大用处
7、八斗的AI大模型,因为学完马士兵的AIOT后发现里面没有最近出的大模型,刚好那会我做期货赚了点钱,于是我又去找大模型的课,刚好那会很多镰刀公众号都在推这个机构的课,于是我不慎中招,进度嘛,NLP那一块是快完课了。CV还没开始。至于效果嘛,说多了都是泪啊。
8、指南针投顾的199投资课,2023年做期货的同时报的,学完了,记忆最深刻的是里面的教你怎么看基本面的课。
9、儒猿的电商项目架构课,2023年学完马士兵的AIOT的课后找了两周多没找到AI相关的工作,当时急需一份工作好到年底回家过年时没人吱歪我以及有收入支撑我的投资,于是还是打算重新入坑Java,在面试高级开发中被毒打了,然后报的这个,目前进展,看了五个课时的课吧。
10、极客时间:大模型课,也是2023年报了AIOT发现没有大模型时报的,目前看了三个课时。大模型微调课,大模型都报了大模型微调不得也搞一个?于是报了,没进展。Go语言课,2023年找Java工作时感觉自己实在不喜欢Java这门语言,在找出路时想想研究下Go吧,所以报了,只看了开头。鸿蒙课,2024年报的,报这个因为比较时新,而且当时炒白银赚了一波,所以报了,目前正在跟直播中。
11、路飞城的爬虫课,也是2023年当时报的,就是当时觉得没收入了,想多个收入来源,他们说他们有爬虫接单平台,但是因为我现在还没有开始学,所以不知道是不是真的。
12、知乎的写作课,当时是因为觉得便宜,好像还送个精品文章免费看的会员特权,然后就报了,没学过。
13、正信期货首席咨询师张恒老师的期货学习课程,因为当时自己感觉对期货了解还不深,所以报了,学完后感觉自己对期货了解还是不深。这个是学完了,老师主要讲的是各种操作技术。但是个人感觉对期货的了解,都是在实践中遇到的各种疑惑,然后自己去搜索查询求问感悟慢慢补充获得的。
我把这些报过的课程罗列出来,不是为了告诉大家我有多韭菜,我是为了告诉所有人,我花了钱买的课,我含着泪跪着都要学完。
我求知欲还是挺旺盛的,不仅买课,还买了一大堆书,还买了微信读书的会员,下载了一堆电子书。




至于说这样子做对不对,见仁见智吧,每个人都有每个人追求的生活方式,这是我的人生兴趣,人生兴趣是无法用结果论作用论功利角度去看的。
后面计划做的事
做这个量化接入,加上写总结,前前后后大概花了我三周多的时间,期间夹杂着找工作面试,新公司入职做需求,每天一下班回到宿舍就吭哧吭哧地搞,搞到深夜1点左右,终于收尾了。好开心。
目前核心重中之重在做的事就是学鸿蒙、AI、学车还有量化和爬虫,目前这份工作还好,感觉不卷,这边附件有个公园,风景挺好的,可以安下心来工作学习了。但是我骨子里还是不喜欢上班这种规条化的生活的,所以量化自动交易和爬虫这两个目前一定会啃下的,是为了以后可以不上班打基础。那样我就能有更多的时间去学习看书,跑步,哈哈。突然发现过去两三年跑了500多公里。

愿男人至死依然是奔跑着的如风的少年。哈哈。
打什么工啊,打工就是浪费生命。
以后若有可能脱离职场,我可能还会尝试轻创业,我常和朋友说,哪天我开公司了,心情不好了,精神不振了,把公司们一关就可以回家睡觉去,多自由,让我的员工也跟着放一下随机假。
打工就是浪费生命啊,和资本家扣扣搜搜发的每个月窝囊费相比,投资做得好的时候最高一天能赚一万多,大盘好的时候都是一天一千多往上的,我还打什么工啊(当然,肯定有亏的时候,不然我早就不打工了躺平了)。不过目前我还需要原始积累,只能先苟着。初期起步时,还没验证自己的真正实力,不敢说稳赚,不想向身边的人借钱融资,也有人想向我注资的,我拒绝了,只能靠自己了啊,我也只想靠自己。感觉自己的资金用到了极限了,可是架不住还有认识的人想向我借钱的,也有想让我参与他们的项目的,不知道怎么拒绝。
打什么工啊,打工就是浪费生命。
希望能做成功吧。
后面主要想做的事如下。
现在的情况是,量化接口接入了,要做的就是再搞个数据进行行情数据落库,技术指标还有基本面指标落库,交易记录交易盈亏交易理由落库以备后面总结。然后数据分析,AI模型也是要上的,数据维度我都想好了,就是技术面和基本面,之前还想过去爬通达信还有各种网站上的新闻热词,用NLP技术做成词云,然后和票库里的票进行向量化关联,这样能迅速抓取到热点,打一把短线,主打快进快出,比一般人快即可。数据分析主要用来找出一个票值不值得做,然后就是上策略了,策略我主要想的肯定就是大名鼎鼎的凯利公式啦,凯利公式的变种应用其实就是现在大部分券商软件里都有的网格条件单,但是用过的都知道网格条件单有个问题就是单边下跌时的煎熬(这个可以通过前面的判断一个票是否值得投的内在价值的数据分析来解决),还有就是单边上涨时网格太小的惋惜,或者冲高回调了网格太大的痛苦,就像你织一张渔网去网鱼,网孔太大,大鱼不一定捞得到小鱼一定会漏,网孔太小,网到小鱼了,但是网可能不够用了。对于这个问题我的解法是,谁说网孔一定要是恒定大小的,我要设定一个动态的变量因子去决定网孔大小以及是否收网(清仓)。而且,我感觉,网格交易并没有掌握凯利公式的精髓。关于动态因子,我目前写的几个量化策略回测时在2024年大跌中效果都不大好,还没做到市场中性(西蒙斯追求的就是要做到市场中性,手动狗头)。所以我设想一个当前市场氛围值的动态因子,关联于一系列关于大盘情况的参数,在参数值低的时候少投或者不投或者只投红利的保险的稳定的票。
关于因子,我对量化了解得还不是很深,好像有个叫阿尔法因子还有个叫贝塔因子的量化术语,不知道是什么。
除了数据落库还有数据分析,后续还有做个前端界面方便操作,最好有个一键下单,一键确认条件策略执行什么的,前端我是没学过,搭建一个VUE框架应该不是啥难事。这个不急。
还有要开个云服务器,把策略部署到云上,这样避免关机而导致策略无法运行。这个也不是很急。
还有就是要做个短信通知或者发邮件通知捕捉到买卖点了,点击可一键确认操作,这样就可以工作忙没空摸鱼看盘时一键确认下单。
你看,做程序员就是有这种好处,只要有接口,有数据,不需要局限于软件服务提供商提供的服务,可以自己定制开发自己需要的功能。
以上功能都不是什么太难的事,问题在于,我时间和资金都不是很够。30了,家里催结婚,一旦结了婚,时间和资金可能都不足以支撑我做这些事了。以上功能都不是什么太难的事,问题在于,我时间和资金都不是很够。30了,家里催结婚,一旦结了婚,时间和资金可能都不足以支撑我做这些事了。还有一个问题就是我的身体状态从小都不大好,一不舒服就会躺平一两周才能恢复,这也就是我报了这么多课却没有学完的原因之一,典型的人菜瘾大了。这也是我前面练长跑的原因之一,练长跑真的很锻炼人的精力,还有就是我在自学中医,试图通过中医来调理身体,中医在有些虚证的问题上有时还是很好使的,比西医好使。
先装个数据库进行数据落库,试试水再说。
还想到一点的是,交易时人在不同时候是会想到不同逻辑的,然后积累了大量经验,但是在某一时刻需要人作出理性决策时,由于资本市场天然的造成人的生理情绪波动,人的大脑瞬时算力有限,在该时刻人是无法即时通过大量逻辑归整出一个没有矛盾和逻辑缺陷的观点和行为的,这时往往会导致人的思考具有偏向性,从而导致决策错误,过后才会突然想起,这在我交易决策过程中屡见不鲜了,我的做法是修习道学,盘中不看盘不做决策不看新闻,练心态,但这不能解决根本的问题,我总不能永远不看盘的。所以,这个时候代码和机器的优势就体验出来了,他们永远能逻辑自洽的,永远拥有执行力,永远无情绪,永远计算力恒定,永远能执行策略永远能优化调校,永远能执行止盈止损等风控,永远冷静,永远没有赌徒心理。
最后,问一下有会开发也会量化的友友吗,志同道合的,一起加个V:15381125473,无商务无广告,纯粹搭伴子学习交流技术,我建有一系列的谈笑有鸿儒的微信群,主要的有做量化的,做AI的,私以为,做投资,学技术,找工作,创业这种事,都是集思广益,众人拾柴火焰高,越交流越能碰撞出思维的火花,灵感越多创意越多的。什么都可以付费,唯知识不可付费,像我一样愿意被割除外。

感觉凡是做投资的,做AI的,群里的人才还是很多的。
不找搭子的话自己一个人摸索,感觉还是挺寂寞,信息差挺多,弯路挺多的。
这个动手级别的技术分享系列会持续更新的,敬请期待。
因为据说,据说哈,就是网上传的,学习效率最高的模式,就是费曼学习法,就是把自己学到的东西整理一遍然后再教出去,也就是输出倒逼输入,于是我就想到了写文章这个方式,写自媒体这件事好久以前干的啦,那还是大学时的事,现在又捡起来了。
老子花了钱买的课一定要把它吃透了掌握起来。
狗头保命:以上全是个人经验总结,不涉及任何广告营销和投资建议。客官们请慎重。
以上以上,顿首顿首,敬拜敬拜,慎之慎之。