wonder trader cta仿真以及对接行情交易接口

这篇具有很好参考价值的文章主要介绍了wonder trader cta仿真以及对接行情交易接口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

WonderTrader是一个基于C++核心模块的,适应全市场全品种交易的,高效率、高可用的开源量化交易开发框架。
    面向于专业机构的整体架构
    数十亿级的实盘管理规模
    从数据落地清洗、到回测分析、再到实盘交易、运营调度,量化交易所有环节全覆盖。

  本文简单介绍在windows操作系统下使用vs作为开发工具使用wtrunner进行仿真交易以及着重讲解如何对接行情交易接口。

  拉取到wondertrader代码完成编译后,在主目录的dist文件夹,找到QuoteFactory,将里面的yaml配置文件全部复制,放在src文件夹里面的QuoteFactory文件夹中,在QuoteFactory中,会有一个parsers文件夹用来放置行情库(如thostmduserapi_se)和行情解析库(如ParserCTP)。

  同时,在目录下会有WtDataStorage.dll和WtDataStorageAD.dll,以上这些库可以在src目录下的Win32目录(外部接口库如hostmduserapi_se在src下的API中)找到,替换之。之后,将主目录的dist文件夹中的common复制到src目录下,为了方便同时wtrunner和QuoteFactory使用它。并且确保在src中有一个storage目录用来存放数据落地后存储的数据。

  现在,你的目录应该和下面差不多

wonder trader cta仿真以及对接行情交易接口,c++,github

    之后我们以au2308合约为例,首先在common中的contracts.json找到au一类,随便找个过期的合约用au2308替换掉。

wonder trader cta仿真以及对接行情交易接口,c++,github

   然后来到QuoteFactory目录下,检查dtcfg,确定它读取的基本配置文件目录没错。因为我们是放在了上一级目录的。或者复制即可。

basefiles:
    commodity: ../common/commodities.json
    contract: ../common/contracts.json
    holiday: ../common/holidays.json
    session: ../common/sessions.json
    utf-8: true
broadcaster:                    
    active: true
    bport: 3997                 
    broadcast:                 
    -   host: 255.255.255.255   
        port: 9001             
        type: 2
allday: true                 
parsers: mdparsers.yaml
statemonitor: statemonitor.yaml
writer:
    async: true         
    groupsize: 20      
    path: ../storage  
    savelog: true  

然后在mdparsers中修改你的账户和密码,前置和品种。

wonder trader cta仿真以及对接行情交易接口,c++,github

  这样,在vs中运行QuoteFactory,看到类似这样的界面就说明数据落地成功了(wt文档里面找的图,与本文并不完全一致)。

wonder trader cta仿真以及对接行情交易接口,c++,github

  成功后,我们开始配置wtrunner,同理,将dist目录中的WtRunerCta中的所有配置文件全部放入src中的WtRunner。

wonder trader cta仿真以及对接行情交易接口,c++,github

 我建议最好在src的Win32目录下自己把这个目录中的库再替换下。cta目录放的是Cta策略工厂,我们的策略就用它生成,executer中放的是执行器工厂,parsers和traders里面有行情/交易接口,以及wondertrader用于对接该行情/交易的接口。为了看到的效果更加明显,我们对wondertrader提供的demo策略进行修改。在vs中找到WtStraDualThrust.cpp。wonder trader cta仿真以及对接行情交易接口,c++,github

 直接复制即可。

#include "WtStraDualThrust.h"

#include "../Includes/ICtaStraCtx.h"

#include "../Includes/WTSContractInfo.hpp"
#include "../Includes/WTSVariant.hpp"
#include "../Includes/WTSDataDef.hpp"
#include "../Share/decimal.h"

extern const char* FACT_NAME;

//By Wesley @ 2022.01.05
#include "../Share/fmtlib.h"

WtStraDualThrust::WtStraDualThrust(const char* id)
	: CtaStrategy(id)
{
}


WtStraDualThrust::~WtStraDualThrust()
{
}

const char* WtStraDualThrust::getFactName()
{
	return FACT_NAME;
}

const char* WtStraDualThrust::getName()
{
	return "DualThrust";
}

bool WtStraDualThrust::init(WTSVariant* cfg)
{
	if (cfg == NULL)
		return false;

	_days = cfg->getUInt32("days");
	_k1 = cfg->getDouble("k1");
	_k2 = cfg->getDouble("k2");

	_period = cfg->getCString("period");
	_count = cfg->getUInt32("count");
	_code = cfg->getCString("code");

	_isstk = cfg->getBoolean("stock");

	return true;
}

void WtStraDualThrust::on_session_begin(ICtaStraCtx* ctx, uint32_t uTDate)
{
	ctx->stra_log_info("on_session_begin");
	std::string newMonCode = ctx->stra_get_rawcode(_code.c_str());
	if (newMonCode != _moncode)
	{
		if (!_moncode.empty())
		{
			double curPos = ctx->stra_get_position(_moncode.c_str());
			if (!decimal::eq(curPos, 0))
			{
				ctx->stra_log_info(fmt::format("主力换月,  老主力{}[{}]将会被清理", _moncode, curPos).c_str());
				ctx->stra_set_position(_moncode.c_str(), 0, "switchout");
				ctx->stra_set_position(newMonCode.c_str(), curPos, "switchin");
			}
		}

		_moncode = newMonCode;
	}
}

void WtStraDualThrust::on_schedule(ICtaStraCtx* ctx, uint32_t curDate, uint32_t curTime)
{
	ctx->stra_log_info("on_schedule");
	ctx->stra_log_info(fmt::format("策略回调on_schedule, {}", ctx->stra_get_time()).c_str());

	std::string code = _code;
	if (_isstk)
		code += "-";
	WTSKlineSlice *kline = ctx->stra_get_bars(code.c_str(), _period.c_str(), _count, true);
	if (kline == NULL)
	{
		//这里可以输出一些日志
		return;
	}

	if (kline->size() == 0)
	{
		kline->release();
		return;
	}

	//这个释放一定要做
	kline->release();

	// 每笔交易手数
	uint32_t trdUnit = 1;
	if (_isstk)
		trdUnit = 100;

	double curPos = ctx->stra_get_position(_code.c_str()) / trdUnit;
	if (decimal::eq(curPos, 0))
	{
		ctx->stra_enter_long(_code.c_str(), 2 * trdUnit, "DT_EnterLong");
		//向上突破
		ctx->stra_log_info(fmt::format("多仓进场").c_str());

	}
	else if (decimal::gt(curPos, 1))
	{

		//多仓出场
		ctx->stra_exit_long(_code.c_str(), 2 * trdUnit, "DT_ExitLong");
		ctx->stra_log_info(fmt::format("多单离场").c_str());

		ctx->stra_save_user_data("test", "waht");
	}
}

void WtStraDualThrust::on_init(ICtaStraCtx* ctx)
{
	ctx->stra_log_info("on_init");
	std::string code = _code;
	ctx->stra_sub_ticks(_code.c_str());
	WTSKlineSlice *kline = ctx->stra_get_bars(code.c_str(), _period.c_str(), _count, true);
	if (kline == NULL)
	{
		//这里可以输出一些日志
		return;
	}

	kline->release();

	//注册指标和图表K线
	ctx->set_chart_kline(_code.c_str(), _period.c_str());

	//注册指标
	ctx->register_index("DualThrust", 0);

	//注册指标线
	ctx->register_index_line("DualThrust", "upper_bound", 0);
	ctx->register_index_line("DualThrust", "lower_bound", 0);
}

void WtStraDualThrust::on_tick(ICtaStraCtx* ctx, const char* stdCode, WTSTickData* newTick)
{
	ctx->stra_log_info("on_tick");
}

然后重新生成WtCtaStraFact。在Win32目录中将重新生成的dll文件放入cta目录中。

接下来修改配置。也是直接复制即可

首先是config.yaml

basefiles:
    commodity: ../common/commodities.json   
    contract: ../common/contracts.json      
    holiday: ../common/holidays.json        
    hot: ../common/hots.json                
    session: ../common/sessions.json       
#数据存储
data:
    store:
        path: ../storage/      

#环境配置
env:
    name: cta                       
    product:
        session: FN0230   
    riskmon:                
        active: false          
        module: WtRiskMonFact   
        name: SimpleRiskMon     
      
        base_amount: 5000000    
        basic_ratio: 101      
        calc_span: 5            
        inner_day_active: true  
        inner_day_fd: 20.0      
        multi_day_active: false 
        multi_day_fd: 60.0     
        risk_scale: 0.3         
        risk_span: 30          

strategies:
    cta:
    -   active: true       # 模块名,linux下为xxxx.so
        id: dt_if          # 策略ID,自定义的
        name: WtCtaStraFact.DualThrust   # 策略名,要和factory中的匹配
        params:                         # 策略初始化参数,这个根据策略的需要提供
            code: SHFE.au.2308
            count: 1
            days: 30
            k1: 0.6
            k2: 0.6
            period: m1
            stock: false
            

executers: executers.yaml   #执行器配置文件
parsers: tdparsers.yaml     #行情通达配置文件
traders: tdtraders.yaml     #交易通道配置文件
bspolicy: actpolicy.yaml    #开平策略配置文件
fees: ../common/fees.json 
filters: filters.yaml

tdtraders.yaml复制后修改用户名这些的。

traders:
-   active: false
    id: simnow         
    module: TraderCTP  
    savedata: true      
    riskmon:            
        active: false    
        policy:         
            default:    
                cancel_stat_timespan: 10    
                cancel_times_boundary: 20   
                cancel_total_limits: 470    
                order_stat_timespan: 10     
                order_times_boundary: 20    
    # 以上是TraderAdapter读取的配置
    # 以下是TraderXXX读取的配置
    front: tcp://180.168.146.187:10201
    broker: "9999"                      
    appid: simnow_client_test
    authcode: "0000000000000000"    
    user: your user
    pass: your password
    quick: true                       
    # ctpmodule: thosttraderapi_se    
    # flowdir: CTPTDFlow  

executes.yaml

executers:
-   active: true    	#是否启用
    id: exec        	#执行器id,不可重复
    trader: simnow	    #执行器绑定的交易通道id,如果不存在,无法执行
    scale: 1        	#数量放大倍数,即该执行器的目标仓位,是组合理论目标仓位的多少倍,可以为小数 

    policy:         #执行单元分配策略,系统根据该策略创建对一个的执行单元
        default:    #默认策略,根据品种ID设置,如SHFE.rb,如果没有针对品种设置,则使用默认策略
            name: WtExeFact.WtMinImpactExeUnit #执行单元名称
            offset: 0,      #委托价偏移跳数
            expire: 5,      #订单超时没秒数
            pricemode: 1,   #基础价格模式,-1-己方最优,0-最新价,1-对手价
            span: 500,      #下单时间间隔(tick驱动的)
            byrate: false,  #是否按对手盘挂单量的比例挂单,配合rate使用
            lots: 1,        #固定数量
            rate: 0         #挂单比例,配合byrate使用

    clear:                  #过期主力自动清理配置
        active: false       #是否启用
        excludes:           #排除列表
        includes:           #包含列表

其他暂时不用管。

接下来在vs中,启动以上两个项目。

wonder trader cta仿真以及对接行情交易接口,c++,github

 启动后,看到类似如下界面说明配置成功(wt文档里面找的图,与本文并不完全一致),一定要看到on_schedule,自己最好也在快期提供的仿真平台上看到下单的回报。如果有这样就成功了。

wonder trader cta仿真以及对接行情交易接口,c++,github

 接下来我们来讲解如何对接外部的行情交易接口。

 wonder trader行情/交易对接项目分别在如下目录中。

wonder trader cta仿真以及对接行情交易接口,c++,github

  我们来到Parsers中,这里面已经对接了很多接口,如CTP,CTPmini,艾科朗克,飞马。以CTP为例,因为它比较经典通用,在对接自己的接口,会用易盛的启明星V9来举例。

  如此多的行情接口,我们需要一个通用的类来管理使用它们,在wonder trader中担任这个角色的是ParserAdapter,它继承自一个IParserSpi。

  ParserCTP,即提供对接CTP行情的类,一方面继承了IParserApi,用于给IParserSpi提供服务,这个部分继承下来的函数多是连接行情,初始化API,注册SPI,这些被ParserAdapter主动调用的函数。之后它一定会继承行情接口为我们提供的SPI类,在CTP中,它是CThostFtdcMdSpi,在这部分继承下来的函数毫无疑问的是CThostFtdcMdSpi中的回调函数。如返回登录状态,返回订阅合约的数据等。

  如果我们要自己对接行情接口,那就一定要注意一个Parser是如何在ParserAdapter被使用的。

  直接来到ParserAdapter的cpp文件中,以关键词_parser_api搜索,看看它是如何连接贯通的。

  先来到init函数中,这里_parser_api被pFuncCreateParser创建出来,如果创建成功,它接下来会注册SPI,并且利用配置文件进行初始化,这个配置文件,通常是我们前面配置文件中的mdparsers.yaml。

wonder trader cta仿真以及对接行情交易接口,c++,github

  随后,在经过一系列判断后将欲订阅的合约传入contractSet并且调用_parser_api的subscribe。

  在init中,它的任务以及完成了,总结,创建parser,给parser注册spi(就是这个ParserAdapter),初始化,订阅合约(主要就是把合约放进去,登录没成功是不能直接订阅的)。

  那么,在之后ParserAdapter的Run函数中,会调用_parser_api->connect() 这也就预示着,我们的parser要登录正式开始工作了。

  了解完毕后来到我们想准备的行情接口,首先肯定是把头文件,库文件这些加入到wonder trader的目录中,模仿其他parser即可,之后模仿其他parser设置好项目属性后,我们可以开始parser的编写了,首先是parser的init函数,在这个函数中,parser利用提供的配置文件初始化,其他地方别无二致,要注意读库文件的地址,修改为自己的库文件名。

wonder trader cta仿真以及对接行情交易接口,c++,github

  之后,我们会利用DLLHelper的get_symbol函数提取出创建行情API实例的函数,这里要注意好creatorName,如果它是C++式编译的,如CTP,我们要利用工具导出它在不同位数,不同操作系统的导出符号名,如果是用extern “C” 修饰的,如易盛的启明星V9,我们直接使用这个函数名即可,如下两图。

wonder trader cta仿真以及对接行情交易接口,c++,github

wonder trader cta仿真以及对接行情交易接口,c++,github​ 

  之后,注册SPI,注册前置地址。

  来到parser的connect函数,这个函数中ParserCTP是调用了Init,在调用init函数后,会触发回调OnFrontConnected,然后在这里调用ReqUserLogin使用登录。而易盛中则没有init的需要,我们直接调用ReqUserLogin登录即可,然后我们会触发登录的回调,在这里,CTP是直接处理了交易日期之后,触发ParserAdapter的handleEvent让其处理登录事件(不过这个好像没有函数实现),

  最后调用函数来订阅合约。但是启明星不同,启明星的登录成功回调返回成功,说明用户登录成功。但是不代表API准备完毕。需要等到OnAPIReady才能进行查询与订阅请求。所以我们在这里只是打个日志,并且触发一个handleEvent。那等到OnAPIReady回调成功后,我们使用DoSubscribeMD()来订阅合约,在订阅合约中我们要注意的是,CTP是可以一次订阅多组合约的,而启明星一次只能订阅一个,我们需要在一次循环中来处理订阅。

wonder trader cta仿真以及对接行情交易接口,c++,github

wonder trader cta仿真以及对接行情交易接口,c++,github​   在订阅合约后,我们会不断地收到行情数据回调,在这里,也就是一个个处理一个个转换好就行了。

  讲完行情接口的对接后,我们简要地概述交易接口,与行情一致,会有TraderAdapter来处理不同的trader,TraderAdapter是一个ITraderSpi。我们的trader是继承了一个ITraderApi和交易接口提供的SPI类,在易盛启明星V9中,它是ITapTradeAPINotify。ITraderApi的部分中继承了直接被TraderAdapter主动调用的函数,如登录,连接,下单,撤单,查询资金用户等。而在ITapTradeAPINotify部分中,我们理所应当地继承了不同的回调函数如OnRspLogin,OnRtnFill这些来将回调的结果给予TraderAdapter处理。同时,因为交易的函数更多,结构体更多,我们也需要更多一批函数来帮助我们使用交易接口。wonder trader cta仿真以及对接行情交易接口,c++,github

   wrap系列函数负责帮助转换枚举变量消除wonder trader与不同接口枚举值的隔阂。make系列函数用于将回调产生的报单结构,交易结构等等转化为wonder trader内部数据结构便于TraderAdapter处理。而与EntrustID相关的函数,则是与报单引用相关。

  在交易中,相当重要就是本地管理的报单号,返回的报单id,返回的交易id之间的管理了,笔者功力浅薄,自己写的trader尚有点小问题,先介绍一下TraderCTP中的处理吧。

  先看到与Trader最亲近的类:TraderAdapter中,在TraderAdapter中负责开平多空的open(close)Long(Short)函数中,会先创建一个WTSEntrust类entrust,这里只会简单地设置交易合约,设置市价或者限价,开平方向,多空方向,之后传入entrust调用doEntrust。
在doEntrust中,会调用TraderCTP的makeEntrustID生成一个独一的委托ID(这里利用了原子变量m_orderRef)。
  那之后,还会调用makeLocalOrderID生成一个本地ID(localid),设置entrust的usertag为 _order_pattern(有一部分配置文件中的id) + localid之后调用orderInsert执行这笔委托,在执行委托之后如果成功,那么在_order_time_cache下单时间缓存中记录当前时间。来到TraderCTP中的orderInsert:除了其他赋值行为,如果entrust中的usertag为空,将m_orderRef作为报单引用
放入CThostFtdcInputOrderField中;不为空,将EntrustID中的报单引CThostFtdcInputOrderField中。
  之后调用ReqOrderInsert正式发送报单录入请求。如果报单内容填写无误成功发出,会收到OnRtnOrder回调。进入到这个回调中,它会利用makeOrderInfo函数生成一个WTSOrderInfo在makeOrderInfo中,将OnRtnOrder的参数CThostFtdcOrderField转化为一个WTSOrderInfo中,有比较重要的几点,先是将CThostFtdcOrderField中的FrontID SessionID OrderRef(和之前填的报单引用是对应的)放入WTSOrderInfo中的m_strEntrustID,其次就是将CThostFtdcOrderField
的OrderSysID报单编号放入m_strOrderID中,最后,由TraderAdapter的onPushOrder函数
来处理这个WTSOrderInfo。在成交的返回中,也会有OrderSysID与之前的报单编号对应,同时也要记录下TradeID,整理好数据后就会交给TraderAdapter的onRspTrades来处理。

笔者能力有限,如有谬误请不吝指出。

最后贴下wonder trader地址

WonderTrader
            github地址:https://github.com/wondertrader/wondertrader
            gitee地址:https://gitee.com/wondertrader/wondertrader

    wtpy
            github地址:https://github.com/wondertrader/wtpy
            gitee地址:https://gitee.com/wondertrader/wtpy

    wtpy获取地址:https://pypi.org/project/wtpy/ wtpy可以直接在python3.8以上的版本安装
    pip install wtpy --upgrade文章来源地址https://www.toymoban.com/news/detail-737450.html

到了这里,关于wonder trader cta仿真以及对接行情交易接口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 适用各种行情,使用网格交易策略实现自动高效套利

    网格交易是量化交易的一种,在指定的区间内,将资金分成N份,先用一部分资金初始建仓,每下跌一定比例买入1份,每上涨一定比例卖出1份,反复低吸高抛,赚取差价。 网格交易策略对于不能实时盯盘的交易者来说,是一个非常理想的自动交易工具!它的优点非常明显,无

    2024年02月04日
    浏览(44)
  • 8.9黄金最新行情走势分析及短线交易策略

    近期有哪些消息面影响黄金走势?黄金多空该如何研判? ​黄金消息面解析:周三(8月9日)现货黄金维持震荡,目前交投于1930美元附近,隔日现货黄金盘中震荡下行,失守1930关口并在美盘时段跌至1922.83美元的日内低点,美元指数全线攀升,获得避险买盘,欧洲风险敏感货

    2024年02月13日
    浏览(44)
  • 5.8晚间黄金行情走势分析及短线交易策略

    ====近期有哪些消息面影响黄金走势?本周黄金多空该如何研判?==== ​黄金消息面解析:周一亚洲时段, 现货黄金 小幅反弹,目前交投于2024.3 美元 /盎司附近,一方面是金价上周五守住了 2000 整数关口,逢低买盘涌入支撑金价,另一方,市场对 美国 债务违约危机的担忧情绪

    2024年02月03日
    浏览(51)
  • 外汇天眼:在交易中有多少属于你的行情?

    期货、股票、外汇不同的市场有着不同的特性,就一个市场而言,也不会是每一段行情都适合你。 刚刚进入期货、股票、外汇市场的朋友都会被其巨大的财富效应所震慑:还有这样赚钱的? 而且机会比比皆是,一夜暴富不是神话呀。 他们依靠自己的欣喜、陶醉、冲动进行着

    2024年02月04日
    浏览(48)
  • 对接华泰极速行情丨DolphinDB INSIGHT 插件使用教程

    INSIGHT 是华泰证券依托大数据存储、实时分析等领域的技术积累,整合接入国内多家交易所高频行情数据,为投资者提供集行情接入、推送、回测、计算及分析等功能于一体的行情数据服务解决方案。 基于 INSIGHT 官方提供的行情数据服务 C++ SDK(TCP 版本),DolphinDB 开发了能

    2024年03月24日
    浏览(55)
  • 程序化交易(二)level2行情数据源接入

    行情在线测试 websocket行情接口 交易在线测试 在线交易接口 官方文档地址 行情交易接口用户文档 注意: 每次分配的服务器地址会发生变化,连接服务前,请务必调用该接口获取最新的服务器地址。 获取服务器: Copy 接口参数: # 参数名 类型 描述 1 market string 市场标志,沪深

    2024年02月05日
    浏览(52)
  • 5.13下周黄金最新行情走势分析及多空交易策略

    ====近期有哪些消息面影响黄金走势?下周黄金多空该如何研判?==== ​黄金消息面解析:周五(5月12日)美市尾盘, 现货黄金 收报2010.23 美元 /盎司,下跌4.57美元或0.23%,日内最高触及2022.59美元/盎司,最低触及2000.85美元/盎司。本周,现货黄金下跌6.22美元或0.31%。劳工部周四公

    2024年02月05日
    浏览(48)
  • 如何在PHP中对接openAI接口,PHP创建AI会话思路以及代码讲解

    https://platform.openai.com/account/api-keys 在这个地址进行注册,但是需要翻墙,可自己查找国内的试用地址。就不多赘述… php端代码: 思路:前端通过一个图标入口,点击后 发送请求,创建一个会话(也就是聊天室),并且把创建的这个会话 入库。并且后端返回一个入库生成的

    2024年01月18日
    浏览(51)
  • 通达信l1l2行情接口-十档行情有哪些优势?

    据提供系统或用户编制的条件选股公式进行选股选定一个条件选股公式或多个组合条件后,计算机自动帮您选出当时或历史上某一段时间内满足条件的所有股票十档行情 英文,列在行情下载显示窗口,同时可保留成板块。 那通达信l1l2行情接口-十档行情有哪些优势? 1、主要

    2024年01月16日
    浏览(38)
  • 通达信l2行情接口怎么用?

    通达信L2行情接口, 包括了普通行情接口所有功能,并新增了十档行情,逐笔成交,买卖队列和深圳逐笔委托(上海证券交易所不对外提供逐笔委托数据)这四个新功能。 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace TdxH

    2023年04月10日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包