Code Monkey home page Code Monkey logo

wondertrader's Introduction

WonderTrader2.png

WonderTrader是什么

  • WonderTrader是一个基于C++核心模块的,适应全市场全品种交易的,高效率高可用的量化交易开发框架。

    • 面向于专业机构的整体架构
    • 数十亿级的实盘管理规模
    • 从数据落地清洗、到回测分析、再到实盘交易、运营调度,量化交易所有环节全覆盖
  • WonderTrader依托于高速的C++核心框架,高效易用的应用层框架(wtpy),致力于打造一个从研发、交易、到运营、调度,全部环节全自动一站式的量化研发交易场景。

  • WonderTrader0.9开启了一个新的UFT引擎,针对超低延时交易的需求进行实现,经过一系列的优化以后,系统延迟在175纳秒之内。

  • WonderTrader的实盘运行架构 WonderTrader实盘运行架构.png

WonderTrader的优势

  • 丰富的交易引擎

    • CTA引擎,也叫同步策略引擎,一般适用于标的较少,计算逻辑较快的策略,事件+时间驱动。典型的应用场景包括单标的择时、中频以下的套利等。Demo中提供的DualThrust策略,单次重算平均耗时,Python实现版本约70多微秒,C++实现版本约4.5微秒。 CTA.jpg
    • SEL引擎,也叫异步策略引擎,一般适用于标的较多,计算逻辑耗时较长的策略,时间驱动。典型应用场景包括多因子选股策略、截面多空策略等。
    • HFT引擎,也叫高频策略引擎,主要针对高频或者低延时策略,事件驱动,系统延迟在1-2微秒之间
    • UFT引擎,也叫极速策略引擎,主要针对超高频或者超低延时策略,事件驱动,系统延迟在200纳秒之内 CTA.jpg
  • 完善的开发接口

    • 高效易用的数据接口:每个策略都会有独立的上下文模块,上下文会自动缓存策略所需要的数据,策略直接调用即可。
    • 简洁的信号接口:策略只需要设置目标仓位,后台自动执行。
    • 上下文无关的策略逻辑:策略不需要自己记录任何数据,每次只需要向接口查询即可,数据全部缓存在内存中,访问效率有保障。
  • 专业的策略管理

    • 策略组合统一管理:采用策略组合的方式,主要为了配合专业机构的产品管理。一个组合盘,对应若干个策略的若干个标的,再设置一个基本的单位资金量,这就是产品管理的基本组合盘,方便扩展。
    • 目标仓位合并执行:目标仓位合并以后,避免了自成交的风险,同时降低了保证金占用和佣金开销。
    • 理论部位独立存储:策略的理论部位是独立存储的,组合盘的整体绩效也是独立核算的,轻松胜任内部管理。
    • 多账户并发执行:组合的目标头寸确定以后,就通过多个交易通道同步执行,可以有效的保障不同的账户的绩效的一致性。
  • 全类型的回测支持

    • 语言支持全:不论是C++开发的策略还是wtpy下开发的python策略,或者其他语言子框架下开发的策略,都在统一的回测引擎中统一回测。
    • 回测效率高:回测引擎采用C++开发,回测效率高,速度快。不管是C++策略还是Python策略,都能快速验证。
    • 策略支持完备:除了CTA策略SEL策略可以回测,HFT策略UFT策略执行单元也能回测 backtest.jpg
  • 高效的数据伺服

    • 本地数据伺服WonderTrader内置的存储引擎采用本地存储,在本地建立数据伺服,通过udp端口广播实时行情,实现1+N的服务结构,可以同时向多个组合盘提供无差别数据服务。专业数据供应商级别的架构,支持搭建多级分发体系,轻松应对各种需求场景。
    • 缓存历史数据:交易过程中,历史数据全部缓存到内存中,同时采用内存直接引用内存数据切片的机制,从根本上避免数据拷贝,提高访问效率。
    • 高效存储引擎:实时数据采用mmap文件,读写高速并且不会丢失数据。同时支持mysql数据库存储历史数据,更方便在此基础上搭建自有的投研数据库。
  • 灵活的风险控制

    • 组合盘资金风控:组合盘有预设的资金规模,可以针对组合盘的虚拟资金,进行组合盘的资金风控。最大的优点是,如果组合盘处于下行阶段,触发风控以后,即使资金账户没有打到风控线,也不会再继续下行了。
    • 通道流量风控:主要针对合规风险,控制的是总撤单笔数、短时间内下单次数和撤单次数等指标。
    • 账户资金风控:和一般意义上的资金风控一致,主要控制账户资金的回撤等。
    • 紧急人工介入:提供一个紧急的人工介入的入口,通过上传一个配置文件,达到控制的目的。主要适用于单品种出现风险,如果全市场风险,人工停止系统即可。
    • 离合器机制:离合器机制依托于信号和执行分离的机制的,主要是如果策略或组合发生风险,通过离合器机制,直接断开信号执行。优点是不影响策略的逻辑,只断开信号的执行,可以继续观察策略在特定行情阶段的表现,和理论研究相互印证。 risk.jpg
  • 强大的控制台wtpy的监控服务)

    • 组合盘运行监控:可以查看实时运行日志、策略理论数据、交易通道数据等,并提供手动启停的入口。 monitor.jpg
    • 自动调度服务:全自动调度定时任务(启动、停止、重启),支持按周设置任务重复,支持进程守护。 schedule.jpg
    • 实时事件通知:监控服务接收组合盘推送的事件,然后转发给监控端,提示给用户。
    • 回测查看器:使用WtBtSnooper模块,可以进行回测数据的查看分析。 bt_summary.jpg bt_details.jpg bt_signals.jpg
    • 全自动远程部署(在建):全自动在线远程部署,提供回测环境、实盘环境等多种应用场景的自动化部署服务。

常见应用场景

  • 团队内控 策略组合管理的方式,给团队内部管理提供了完美的解决方案。

    • 一方面,不同投研人员,不同的策略可以组合成一个组合运行,而且每个策略都有自己的理论部位,即使交易相同标的也不会互相干扰;
    • 另一方面,C++级别的代码可以提供最大的策略保密性,投研人员不用担心策略的泄露;
    • 策略的绩效是独立核算的,团队内部的考核指标可以很容易实现。
  • 多账户交易多产品配置) 对于不同行情周期下的策略组合,一般团队都会有一个当下最适应的策略组合。但是同一时期,团队可能会同时管理很多个账户,而其实这些账户用到的策略组合都是相同的。这个时候WonderTrader平台提供的M+1+N执行架构就能够完美的满足这个需求。 WonderTrader基本架构.jpg

    • 首先,策略组合有自己的单位资金容量和对应的风险参数,以及各个策略的单位交易数量;
    • 其次,不同的账户有不同的资金规模和风险偏好,这个时候只需要根据这些要求配置不同的手数倍率即可;

      假如某组合盘P基本资金规模为500w,预期收益30%,最大回撤10%,收益风险比3:1;A账户使用该组合盘P交易,A账户的资金量为1000w,可以接受的最大回撤也是10%;B账户也使用该组合盘P交易,资金量也是1000w,但是可以接受的最大回撤为20%;这个时候因为A账户风险参数和基本盘一致,所以A账户的手数放大倍数为资金规模/基本盘的资金规模=1000w/500w=2倍;B账户因为可以忍受最大回撤20%,所以手数比例还要再放大一倍,即B账户可以配置4倍。

    • 第三,不同的账户可以配置独立的风控逻辑,账户之间不会互相影响。
  • 多标的跟踪 一些用解释型语言(如Python)开发核心模块的量化交易平台,在标的数不多的情况下,能够胜任各种不同的应用场景。但是当需要跟踪的标的数达到100个以上,甚至是50个以上时,就无法满足需求了。一方面资源占用大,利用multiprocess等机制,虽然各个标的独立运行,但是上百个标的就要新建上百个进程,内存和CPU开销都非常大;另一方面策略效率低,资源争强严重的情况下,策略反应也会变慢。 WonderTrader核心采用C++开发,数据伺服更是一开始就设计成向多个组合同时提供服务的架构,同时策略和执行剥离,信号执行和策略计算完全在两个不同的线程中独立运行。在这样的架构下,就能够很好的满足多标的跟踪的需求。

  • 大计算量策略 一些策略计算量会非常惊人,比较典型的就是选股策略,不管是用多因子也好,还是基本面也好,都会从数千只股票中,逐步筛选,从而得到最后的目标股池。另外,一些多标的的多因子框架也具有较大的计算量。这样的策略,计算量非常庞大,耗时也长。 WonderTraderSEL引擎就是为了满足这方面的需求而定制的。SEL引擎采用异步时间驱动的模式,通过向引擎注册重算时间调度(支持日内,每日、每周、每月的等多种周期),定时触发重算,然后调整多标的的目标仓位,从而输出信号。

  • 极速交易 WonderTrader使用C++作为底层核心开发语言,一个最重要的目的就是追求极致性能,所以WonderTrader的使用场景中高频交易或者极速交易有一个非常大的占比。WonderTraderv0.9版本开设了一个新的UFTEngine,专门针对极速交易的场景。 和原来的HFTEngine不同,HFTEngine针对的是一般高频,侧重于向应用层提供高性能的底层组件,会考虑更多的兼容性问题以及应用层对接的问题,系统延迟在1-2微秒之间。而UFTEngine则完全从WtCore项目剥离,不向应用层提供接口,全部在C++进行开发实现,系统延迟在200ns以内

  • 算法交易 WonderTrader有一个独立的执行器入口模块WtExecMon,用户可以在此基础上实现算法交易。WonderTraderM+1+N执行架构中,1+N执行部分剥离出来,就可以作为一个独立算法交易执行器来使用。用户在使用的时候,通过设置指定标的的目标头寸,算法执行单元就可以按照预设的算法进行交易下单。 用户可以通过实现自己的WtExecFact模块,来添加更多的算法执行单元。高效的C++底层,可以给算法执行单元的执行效果提供有力的保障。

支持的交易接口

  • 期货
    • CTP
    • CTPMini
    • 飞马Femas
    • 艾克朗科(仅组播行情)
    • 易达
  • 期权
    • CTPOpt
    • 金证期权maOpt
    • QWIN二开
  • 股票
    • 中泰XTP
    • 中泰XTPXAlgo
    • 华鑫奇点
    • 华锐ATP
    • 宽睿OES

wtpy简介

  • wtpy是构建在WonderTrader核心模块之上的,使用Python3开发的WonderTraderPython3子框架
  • Python作为量化领域最流行的语言,在时序数据处理上有许多非常受欢迎的强大的第三方库
  • Python作为一种解释型语言,代码编写和调试都非常方便,不需要编译就可以直接运行
  • Python的跨平台属性也使Python可以应用到更多的场景中
  • wtpy主要功能是作为WonderTraderPython语言的外延
  • 同时wtpy还内置了一个强大的监控服务组件WtMonSvr。该组件提供了远程的webui的监控界面,可以实时监控策略组合的运行情况,还提供全天24×7的自动调度服务,为你的交易保驾护航。

WonderTrader怎么获取

WonderTrader延伸项目

写在最后


wondertrader's People

Contributors

a819721810 avatar delusionpig avatar dogfood1 avatar hyperdreamer avatar jacksu avatar mrrdrr avatar qiuwei avatar rafikor avatar twilightsight avatar wondertrader avatar yagerfgcs avatar zhaoyvke avatar zzzzhej avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wondertrader's Issues

wtpy下的dthelper类的read_dsb_ticks与dump_ticks无法正常使用

dthelper的read_dsb_ticks无法正常读取dsb数据,但在cpp下可以读取,回测也能够使用。
dump_ticks返回错误

OSError: [WinError -529697949] Windows Error 0xe06d7363

read_dsb_ticks返回错误

AttributeError: 'TickList' object has no attribute 'on_data_count'

XTP entrustid对不上,无法兑回localid

uint32_t TraderAdapter::doEntrust(WTSEntrust* entrust)
{
	_trader_api->makeEntrustID(entrust->getEntrustID(), 64);

这里用的是自增的 order ref,会不断加大数字

int TraderXTP::orderInsert(WTSEntrust* entrust)
{
	…….
	
	req.order_client_id = _client;

这里是固定数字

当XTP的order响应回来,回调函数中会根据 order_client_id 生成对应的 entrust id,用于兑回到 local id

WTSEntrust* TraderXTP::makeEntrust(XTPOrderInfo* order_info)
{
	…….
	
	pRet->setEntrustID(genEntrustID(order_info->order_client_id).c_str());      // 这里始终是一个固定值,也就是上面的_client

	std::string usertag = _ini.readString(ENTRUST_SECTION, pRet->getEntrustID());   // 这里会导致读INI文件,没有这个entrust id,所以usertag始终为空
	if (!usertag.empty())
		pRet->setUserTag(usertag.c_str());

app discard signal 28

尊敬的开发者,您好!
我在debug模式下编译并运行WtRunner的时候 app discard signal 28 以及 app discard signal 17这样的问题。
还有sh: 1: dmidecode: not found这个问题。
所以想请教一下,这个地方 app discard signal 代表的意思是什么?以及dmidecode: not found是什么原因?

[06.15 01:49:04 - info ] Commodities configuration file ./common/commodities.json loaded
[06.15 01:49:04 - info ] Contracts configuration file ./common/contracts.json loaded, 5 exchanges
[06.15 01:49:04 - info ] Trading enviroment initialzied with engine: CTA
[06.15 01:49:04 - info ] Platform running mode: Production
[06.15 01:49:04 - info ] 36 fee templates loaded
[06.15 01:49:04 - debug] 0 position info of portfolio loaded
[06.15 01:49:04 - debug] Storage initialized @ ../FUT_Data/
[06.15 01:49:04 - info ] No adjusting factor file configured, loading skipped
[06.15 01:49:04 - info ] Data manager initialized
[06.15 01:49:04 - info ] Reading parser config from tdparsers.yaml...
[06.15 01:49:04 - info ] [parser1] Parser module /home/achang/wondertrader/src/build_debug/build_x64/Debug/bin/WtRunner/parsers/libParserUDP.so loaded
[06.15 01:49:04 - info ] 1 parsers loaded
[06.15 01:49:04 - info ] Reading trader config from tdtraders.yaml...
[06.15 01:49:04 - info ] [simnow] Risk control rule default of trading channel loaded
[06.15 01:49:04 - info ] [simnow] Trader module /home/achang/wondertrader/src/build_debug/build_x64/Debug/bin/WtRunner/traders/libTraderCTP.so loaded
[06.15 01:49:04 - info ] 1 traders loaded
[06.15 01:49:04 - info ] Reading executer config from executers.yaml...
[06.15 01:49:04 - info ] Executer factory WtExeFact loaded
[06.15 01:49:04 - info ] 1 executers loaded
[06.15 01:49:04 - info ] CTA strategy factory[WtCtaStraFact] loaded
[06.15 01:49:04 - info ] 1 CTA strategy factories in directory[/home/achang/wondertrader/src/build_debug/build_x64/Debug/bin/WtRunner/cta/] loaded
[06.15 01:49:04 - info ] [ParserUDP] Ticks subscribing sent
[06.15 01:49:04 - info ] 1 parsers started
[06.15 01:49:04 - info ] 1 trading channels started
[06.15 01:49:04 - info ] CtaTicker will drive engine with session TRADING
[06.15 01:49:04 - debug] Main KBars confirmed��CFFEX.rb.HOT#m1
[06.15 01:49:04 - info ] Trading day 20220615 begun
sh: 1: dmidecode: not found
[06.15 01:49:04 - error] app discard signal 17
sh: 1: dmidecode: not found
[06.15 01:49:04 - error] app discard signal 17
[06.15 01:49:04 - info ] [TraderCTP][9999-197011] Login succeed, AppID: simnow_client_test, Sessionid: 983643650, login time: 09:49:20...
[06.15 01:49:04 - info ] [TraderCTP][9999-197011] Login succeed, trading date: 20220615...
[06.15 01:49:04 - info ] [TraderCTP][9999-197011] Querying confirming state of settlement data...
[06.15 01:49:05 - info ] [TraderCTP][9999-197011] Trading channel initialized...
[06.15 01:49:05 - info ] [simnow] Trader login succeed, trading date: 20220615
[06.15 01:49:06 - info ] [simnow] Position data updated
[06.15 01:49:09 - info ] [simnow] Trading channel ready
[06.15 02:02:17 - error] app discard signal 28
[06.15 02:02:18 - error] app discard signal 28
[06.15 02:02:19 - error] app discard signal 28
[06.15 02:02:27 - error] app discard signal 28
[06.15 02:02:29 - error] app discard signal 28
[06.15 02:02:31 - error] app discard signal 28

XTP的三个问题

1、XTP的cancel order返回非0值才代表正常,TraderXTP::orderAction里面写的是要求为0.
2、XTP有一个部分撤单的状态,需要映射到WT里面的完全撤单,否则WOS_PartTraded_NotQueuing这种状态无法触发on_order回调
3、XTP的lib没有自动重连,需要在OnDisconnect里面自己调用Login重新连接。

  • ParserXTP里面,需要用DoLogin重新登录,以及行情也需要重新订阅(XTP QA)
  • TraderXTP里面生成entrustid的逻辑,需要跟session_id解耦

10.问:api会自动重连么?
答:api不会自动帮用户重连。用户可以在收到断线通知OnDisconnect()后选择不销毁api,不登出,继续登录login(),此时交易服务器会在用户重新登录后,从断点消息处续传。注意:行情服务器在断线后不会重新推送行情,除非用户重新订阅。

orderInsert函数里面,生成entrustid,用到了_sessionid
然后断线,重连,会受到断点续传的报单回调
OnOrderEvent函数里面,根据order_info->order_client_id重新生成entrustid,这时候_sessionid变了,会导致entrustid不一致

[bug] 在使用换月合约进行交易的情况下,可能会在换月当日出现问题

假定当前时间为20日夜盘,此时发生了换月,主力合约由A-》B,但是可能会出现在当天夜盘交易的主力合约仍然是A,但是在第二天21日的白盘,主力切换到了B,导致出现了重复开仓的问题。目前猜测可能和交易日和日历日的获取有关,交易日最初是以日历日赋值,随后等第一个tick到达后,在重新设置成交易日。这个逻辑可能存在bug

多个执行器如何配置

在查看官方和半官方的配置文件相关的教程时,和代码文件对比一看,发现有些差异,一时不知道怎么配置多个执行器好。请大佬帮忙解答,谢谢!!!

python接口中的stra_get_ticks无法调用

python接口中的stra_get_ticks无法调用,调用时会直接卡死,cpp中可以正常调用。通过调试,发现已经执行了WtBtPorter下的cta_get_ticks中的回调函数调用,所以问题应该是处在python那边的处理上

tick回放问题

tick是按天回放的
当回放完一天后,就会释放当天的所有tick.
然后在第二天的第一个tick触发的on_tick下调用get_last_tick就会报out_of_range

cmake报错

SRC目录下的CMakeLists.txt最后面加的一段代码会导致WIN下Cmake配置错误,重复添加了子目录

# Only used on win
IF(MSVC)
ADD_SUBDIRECTORY(TestTrader)
ENDIF()

wondertrader无法通过编译,提示/usr/include/c++/7/ext/new_allocator.h:136:4: error: no matching function for call to ‘spdlog::logger::logger(const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink> >&)’

你好,我对你的项目非常感兴趣,编译的时候会报错。我的系统详细信息如下:

No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.5 LTS
Release:	18.04
Codename:	bionic

我的spdlog是编译的源码:
https://github.com/gabime/spdlog/

具体的错误信息为:

-- Operation System is UNIX-like OS's
-- Configuring done
CMake Error: Unable to open check cache file for write. /home/wubin/tmp/wondertrader/src/CMakeFiles/cmake.check_cache
[ 21%] Built target WTSUtils
[ 21%] Building CXX object WTSTools/CMakeFiles/WTSTools.dir/WTSLogger.cpp.o
In file included from /home/wubin/tmp/wondertrader/src/WTSTools/../Share/JsonToVariant.hpp:12:0,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:15:
/home/wubin/tmp/wondertrader/src/WTSTools/../Share/../Includes/WTSVariant.hpp: In static member function ‘static otp::WTSVariant* otp::WTSVariant::create(int64_t)’:
/home/wubin/tmp/wondertrader/src/WTSTools/../Share/../Includes/WTSVariant.hpp:89:28: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘int64_t {aka long int}’ [-Wformat=]
   sprintf(s, INT64_FMT, i64);
                            ^
/home/wubin/tmp/wondertrader/src/WTSTools/../Share/../Includes/WTSVariant.hpp: In static member function ‘static otp::WTSVariant* otp::WTSVariant::create(uint64_t)’:
/home/wubin/tmp/wondertrader/src/WTSTools/../Share/../Includes/WTSVariant.hpp:100:29: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
   sprintf(s, UINT64_FMT, u64);
                             ^
In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
                 from /usr/include/c++/7/bits/allocator.h:46,
                 from /usr/include/c++/7/string:41,
                 from /usr/include/c++/7/bits/locale_classes.h:40,
                 from /usr/include/c++/7/bits/ios_base.h:41,
                 from /usr/include/c++/7/ios:42,
                 from /usr/include/c++/7/ostream:38,
                 from /usr/include/c++/7/iostream:39,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:11:
/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = spdlog::logger; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}; _Tp = spdlog::logger]’:
/usr/include/c++/7/bits/alloc_traits.h:475:4:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = spdlog::logger; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}; _Tp = spdlog::logger; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<spdlog::logger>]’
/usr/include/c++/7/bits/shared_ptr_base.h:526:39:   required from ‘std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...) [with _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}; _Tp = spdlog::logger; _Alloc = std::allocator<spdlog::logger>; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]’
/usr/include/c++/7/bits/shared_ptr_base.h:637:4:   required from ‘std::__shared_count<_Lp>::__shared_count(std::_Sp_make_shared_tag, _Tp*, const _Alloc&, _Args&& ...) [with _Tp = spdlog::logger; _Alloc = std::allocator<spdlog::logger>; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]’
/usr/include/c++/7/bits/shared_ptr_base.h:1295:35:   required from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<spdlog::logger>; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}; _Tp = spdlog::logger; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]’
/usr/include/c++/7/bits/shared_ptr.h:344:64:   required from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<spdlog::logger>; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}; _Tp = spdlog::logger]’
/usr/include/c++/7/bits/shared_ptr.h:690:14:   required from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = spdlog::logger; _Alloc = std::allocator<spdlog::logger>; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}]’
/usr/include/c++/7/bits/shared_ptr.h:706:39:   required from ‘std::shared_ptr<_Tp> std::make_shared(_Args&& ...) [with _Tp = spdlog::logger; _Args = {const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink>, std::allocator<std::shared_ptr<spdlog::sinks::sink> > >&}]’
/home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:137:64:   required from here
/usr/include/c++/7/ext/new_allocator.h:136:4: error: no matching function for call to ‘spdlog::logger::logger(const char*&, std::vector<std::shared_ptr<spdlog::sinks::sink> >&)’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/spdlog/logger.h:366:0,
                 from /usr/local/include/spdlog/details/registry-inl.h:12,
                 from /usr/local/include/spdlog/details/registry.h:114,
                 from /usr/local/include/spdlog/spdlog.h:13,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.h:18,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:13:
/usr/local/include/spdlog/logger-inl.h:28:15: note: candidate: spdlog::logger::logger(spdlog::logger&&)
 SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : name_(std::move(other.name_)),
               ^~~~~~
/usr/local/include/spdlog/logger-inl.h:28:15: note:   candidate expects 1 argument, 2 provided
/usr/local/include/spdlog/logger-inl.h:19:15: note: candidate: spdlog::logger::logger(const spdlog::logger&)
 SPDLOG_INLINE logger::logger(const logger &other)
               ^~~~~~
/usr/local/include/spdlog/logger-inl.h:19:15: note:   candidate expects 1 argument, 2 provided
In file included from /usr/local/include/spdlog/details/registry-inl.h:12:0,
                 from /usr/local/include/spdlog/details/registry.h:114,
                 from /usr/local/include/spdlog/spdlog.h:13,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.h:18,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:13:
/usr/local/include/spdlog/logger.h:65:5: note: candidate: spdlog::logger::logger(std::__cxx11::string, spdlog::sinks_init_list)
     logger(std::string name, sinks_init_list sinks)
     ^~~~~~
/usr/local/include/spdlog/logger.h:65:5: note:   no known conversion for argument 2 from ‘std::vector<std::shared_ptr<spdlog::sinks::sink> >’ to ‘spdlog::sinks_init_list {aka std::initializer_list<std::shared_ptr<spdlog::sinks::sink> >}’
/usr/local/include/spdlog/logger.h:60:5: note: candidate: spdlog::logger::logger(std::__cxx11::string, spdlog::sink_ptr)
     logger(std::string name, sink_ptr single_sink)
     ^~~~~~
/usr/local/include/spdlog/logger.h:60:5: note:   no known conversion for argument 2 from ‘std::vector<std::shared_ptr<spdlog::sinks::sink> >’ to ‘spdlog::sink_ptr {aka std::shared_ptr<spdlog::sinks::sink>}’
/usr/local/include/spdlog/logger.h:54:5: note: candidate: template<class It> spdlog::logger::logger(std::__cxx11::string, It, It)
     logger(std::string name, It begin, It end)
     ^~~~~~
/usr/local/include/spdlog/logger.h:54:5: note:   template argument deduction/substitution failed:
In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
                 from /usr/include/c++/7/bits/allocator.h:46,
                 from /usr/include/c++/7/string:41,
                 from /usr/include/c++/7/bits/locale_classes.h:40,
                 from /usr/include/c++/7/bits/ios_base.h:41,
                 from /usr/include/c++/7/ios:42,
                 from /usr/include/c++/7/ostream:38,
                 from /usr/include/c++/7/iostream:39,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:11:
/usr/include/c++/7/ext/new_allocator.h:136:4: note:   candidate expects 3 arguments, 2 provided
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/spdlog/details/registry-inl.h:12:0,
                 from /usr/local/include/spdlog/details/registry.h:114,
                 from /usr/local/include/spdlog/spdlog.h:13,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.h:18,
                 from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:13:
/usr/local/include/spdlog/logger.h:47:14: note: candidate: spdlog::logger::logger(std::__cxx11::string)
     explicit logger(std::string name)
              ^~~~~~
/usr/local/include/spdlog/logger.h:47:14: note:   candidate expects 1 argument, 2 provided
In file included from /home/wubin/tmp/wondertrader/src/WTSTools/WTSLogger.cpp:16:0:
/home/wubin/tmp/wondertrader/src/WTSTools/../Share/StdUtils.hpp: In static member function ‘static uint64_t StdFile::read_file_content(const char*, std::__cxx11::string&)’:
/home/wubin/tmp/wondertrader/src/WTSTools/../Share/StdUtils.hpp:68:8: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result [-Wunused-result]
   fread((void*)content.data(), sizeof(char), length, f);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WTSTools/CMakeFiles/WTSTools.dir/build.make:158: recipe for target 'WTSTools/CMakeFiles/WTSTools.dir/WTSLogger.cpp.o' failed
make[2]: *** [WTSTools/CMakeFiles/WTSTools.dir/WTSLogger.cpp.o] Error 1
CMakeFiles/Makefile2:140: recipe for target 'WTSTools/CMakeFiles/WTSTools.dir/all' failed
make[1]: *** [WTSTools/CMakeFiles/WTSTools.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

WTSToolsLib编译出错

用最新的spdlog编译出错

WTSLogger.cpp 里面,
auto logger = std::make_sharedspdlog::logger(catName, sinks);
sinks这个参数不能这么直接用?

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C2664 “spdlog::logger::logger(spdlog::logger &&) noexcept”: 无法将参数 2 从“std::vector<spdlog::sink_ptr,std::allocator<_Ty>>”转换为“spdlog::sink_ptr” WTSToolsLib c:\program files (x86)\microsoft visual studio\2019\enterprise\vc\tools\msvc\14.16.27023\include\memory 1801

在Hft引擎做A股股票做回测时,如果使用日线和tick,且有11:31至13:00休盘期间的tick时,13:00后的tick不会回放。

在Hft引擎做回测时,HisDataReplayer中有这个调用过程 run_by_bars —>replayHftDatas —>getNextTickTime—>isInTradingTime。
isInTradingTime 判断中午休盘期间的tick不在交易时段,一路调用返回,导致退出了replayHftDatas 的执行,而日线驱动的回测,当天就不会再进入replayHftDatas 了,从而导致下午的tick没有机会回放。
下面两行代码是关键:
replayHftDatas函数中的:

_uint64_t nextTime = std::min(UINT64_MAX, getNextTickTime(_cur_tdate));
if (nextTime == UINT64_MAX)
   return false;_

getNextTickTime函数中的:

_//By Wesley @ 2022.03.06
//检查一下时间戳,如果不是交易时间的,就不回放了
if(!sInfo->isInTradingTime(nextTick.action_time/100000, false))_

CentOS 编译项目报错

求助下各位C++大佬

编译一个项目的时候提示:
/lib/libboost_filesystem.so: undefined reference to `std::__cxx11::basic_string<char, std::char_traits, std::allocator >::find_first_not_of(char const*, unsigned long, unsigned long) const@GLIBCXX_3.4.21'

导致编译失败,找到一个类似的错误
https://stackoverflow.com/questions/33394934/converting-std-cxx11string-to-stdstring

说是因为用了不同版本的GCC编译导致C++11的ABI接口不兼容,有什么办法解决吗,尝试使用cmake的编译项-D_GLIBCXX_USE_CXX11_ABI 无效

版本信息:
centos 7.9
gcc 7.5
cmake 3.19
boost 1.72

试WtHftStraFact这个demo的时候发现在存在跳转错误的问题,导致无法订阅合约。

您好,我在调试WtHftStraFact这个demo的时候发现在存在跳转错误的问题,导致无法订阅合约。
image
在WtHftStrDemo.cpp这个源码中void WtHftStraDemo::on_init(IHftStraCtx* ctx) 这个方法里面ctx->stra_sub_ticks(_code.c_str())跳转进去后是如下代码
image

double HftStraBaseCtx::stra_get_price(const char* stdCode)
{
return _engine->get_cur_price(stdCode);
}
为什么不是跳转到如下:
void HftStraBaseCtx::stra_sub_ticks(const char* stdCode)
{
_engine->sub_tick(id(), stdCode);
stra_log_info("Market Data subscribed: %s", stdCode);
}

函数名写错

WtRunner/WtRunner.cpp, 222行, initTraders, 应该是 initExecuters

ParserCTP.cpp文件中配置判断逻辑是否有误?

ParserAdapter.cpp文件中ParserAdapter::init要求配置中必须有"module", 因此ParserCTP.cpp文件中ParserCTP::init

	std::string module = config->getCString("ctpmodule");
	if (module.empty())
		module = "thostmduserapi_se";

这段代码判断逻辑是否多余?

image

image

使用日线回测时,如果股票上市时间比回测开始时间晚,会漏掉第一根bar。

在HisDataReplayer::get_kline_slice(...) 函数中,取得Bar后,会定位Bar列表的_cursor。
由于股票上市日期晚于回测开始日期,计算出bar list的游标的初始值为1,从而漏掉下标为0的第一根。
节选代码如下:

... ...
if (kBlkPair->_cursor == UINT_MAX)
{
	WTSBarStruct bar;
	bar.date = _cur_tdate;
	if (kp != KP_DAY)
		bar.time = (_cur_date - 19900000) * 10000 + _cur_time;
	auto it = std::lower_bound(kBlkPair->_bars.begin(), kBlkPair->_bars.end(), bar, [isDay, isClosed](const WTSBarStruct& a, const WTSBarStruct& b) {
	if (isDay)
		if (!isClosed)
			return a.date < b.date;
		else
			return a.date <= b.date;
	else
		return a.time < b.time;
	});


//@@ *****************************
问题分析step1: 由于 第一根bar的时间比当前时间_cur_tdate晚,所以这时候 eIdx = 0 
//@@ *****************************

	std::size_t eIdx = it - kBlkPair->_bars.begin();


	if (it != kBlkPair->_bars.end())
	{
		WTSBarStruct& curBar = *it;
		if (isDay)
		{

//@@ *****************************
// 问题分析step2:第一根bar的时间大于_cur_tdate,条件满足,进入这个分支
			if (curBar.date >= _cur_tdate && !isClosed)  
			{
//@@ *****************************
// 问题分析step3:这时候 eIdx =0 ,不满足条件,eIdx不会减1。
				if (eIdx > 0)   
				{
					it--;
					eIdx--;
				}
			}
			else if (curBar.date > _cur_tdate && isClosed)
			{
				if (eIdx > 0)
				{
					it--;
					eIdx--;
				}
			}
		}
		else
		{
			if (curBar.time > bar.time)
			{
				if (eIdx > 0)
				{
					it--;
					eIdx--;
				}
			}
		}

//@@ *****************************
// 问题分析step4:到这里,eIdx为0,从而kBlkPair->_cursor等于1,由此导致回放Bar时,从1开始了。
		kBlkPair->_cursor = eIdx + 1;  

	}
	else
... ... 

我的修改方法:在开始先判断第一根bar的时间是否比当前时间晚,如果晚就直接把_cursor设置为0.
if (kBlkPair->_bars.begin()->date >= _cur_tdate)
kBlkPair->_cursor = 0;
else
... ...

[BUG] TWAP算法发现以下错误

在执行器中的TWAP执行单元下发现以下问题:

撤单日志缺少参数

if (_cancel_cnt > 0)
_cancel_cnt--;
_ctx->writeLog(fmt::format("Order {} updated cancelcnt -> {}", _cancel_cnt).c_str());
}

第83行日志输出的format缺少一个参数

参数表述与实际存在差异

uint32_t _total_secs; //执行总时间,单位s
uint32_t _total_times; //总执行次数
uint32_t _tail_secs; //执行尾部时间
uint32_t _ord_sticky; //挂单时限,单位s
uint32_t _price_mode; //价格模式: 0-最新价,1-最优价,2-对手价
uint32_t _price_offset; //挂单价格偏移,相对于几乎价格偏移,买+卖-

_total_secs和_tail_secs在备注中单位是秒,但在实际计算中,由于now的单位是毫秒,因此存在问题

if (!hasCancel && (now - _last_fire_time >= _fire_span))
{
do_calc();
}

now时间不更新

uint64_t now = _ctx->getCurTime();

now时间没有更新,始终指向当日的8:00

on_condition_triggered触发异常

问题复现:

使用当前版本中demo时,在on_tick中设置limitprice和stopprice为0的直接触发单,也仍然会触发on_condition_triggered。但在on_schedule中,这样的直接触发单,则不会触发on_condition_triggered

原因分析

在on_tick中设置直接委托单时,_is_in_schedule为false,因此sInfo._triggered会被设置为true,导致后续在判断是否作为条件单触发回调时,出现非预期的回调情况。

找不到libcurl-mdd.lib

#pragma comment(lib, "libcurl-mdd.lib")
libcurl.lib
libcurld.lib都好说,这libcurl-mdd.lib是curl的哪个版本的?

HFT直连需要过滤噪声数据

HFT直连CTP情况下需要过滤噪声数据。

uint32_t uDate = curTick->actiondate();
uint32_t uTime = curTick->actiontime();
if (_date != 0 && (uDate < _date || (uDate == _date && uTime < _time)))
{
//WTSLogger::info("行情时间%u小于本地时间%u", uTime, _time);

在该处增加判断

 uint32_t uDate = curTick->actiondate(); 
 uint32_t uTime = curTick->actiontime(); 

 if (!_s_info->isInTradingTime(uTime/100000))
      return;

 if (_date != 0 && (uDate < _date || (uDate == _date && uTime < _time))) 
 { 
 	//WTSLogger::info("行情时间%u小于本地时间%u", uTime, _time); 

bar数据settle,money复权处理

  1. 策略内读取复权后的bar数据,开高低收已复权,但是settle和money没有做复权处理
  2. tick数据中也是一样,pre_close,pre_settle等也没有复权
  3. tick数据里面的ask和bid,用于计算仓位手数,应该是不要复权比较好

[bug] 关于HftMocker模块中procOrder 方法内调用on_order、on_trade的传参问题

image
遇到的问题:高频回测模块中,策略在on_trade中调用ctx->stra_sell()会报错,当调用完ctx->stra_sell()后on_trade接收的指针参数stdCode指向了非法内存。
可能的原因:HftMocker中_orders在插入新订单发生扩容的时候,ordInfo会被复制到新地址,原有的ordInfo会被释放掉,此时作为参数传递的ordInfo._code就变成了野指针。

配置文件有错

dist/WtRunnerCta/config.yaml

按照源码WtRunner.cpp配置加载顺序

filters: filters.yaml       #过滤器配置文件,这个主要是用于盘中不停机干预的
fees: ../common/fees.json   #佣金配置文件

这两个配置字段应该放在 env 字段内, 否则无法加载

配置文件写错

/dist/WtRunnerCta/executers.yaml, policy 下配置内容出现了逗号

检查时间戳时,存在死循环

//检查一下时间戳,如果不是交易时间的,就不回放了
uint32_t idx = 0;
while(true)
{
uint32_t tickMin = tickList._items[idx].action_time / 100000;
if (sInfo->isInTradingTime(tickMin))
{
tickList._cursor = idx + 1;
break;
}
}

该处代码存在死循环,可以修改为:

tickList._cursor = 1;
while(true)
{
	if (tickList._cursor>tickList._count)
                break;
        uint32_t tickMin = tickList._items[tickList._cursor-1].action_time / 100000;
	if (sInfo->isInTradingTime(tickMin))
                break;
        tickList._cursor++
}

【HFT】在on_order或者on_trade中下单会触发指针悬空或边界溢出的问题

问题描述

在HFT引擎的回测中,撮合是在on_tick下的procOrder函数中执行的。

bool HftMocker::procOrder(uint32_t localid)
{
auto it = _orders.find(localid);
if (it == _orders.end())
return false;

每次撮合时,会从_orders中获取对应的order对象,并触发on_order与on_order。如果此时在on_order与on_order的回调函数中,再次调用下单函数,会添加新的order对象到_orders中,添加的代码是异步执行的。

postTask([this, localid]() {
const OrderInfo& ordInfo = _orders[localid];
on_entrust(localid, ordInfo._code, true, "下单成功", ordInfo._usertag);
});

在触发procOrder后,如果有成交,便会根据成交订单对应的localid,将订单从_orders中erase掉。

for(uint32_t localid : ids)
{
auto it = _orders.find(localid);
_orders.erase(it);
}

上述过程有一定概率触发如下几个问题:

  1. _orders中会存在本该被释放掉的localid键,而值则是一个空的order对象
  2. 会在其他地方操作_orders时,触发越界错误

需要被修复的理由

尽管可以通过避免在on_order或者on_trade中下单来避开这个问题,但是在实际的策略设计中,可能会出现比较多需要在前一个订单成交后,立刻发出新订单的情况,如套利中的主被动腿订单。而且这个问题在实盘中实际是不会触发的,这是由于wt的撮合机制导致的。为了避免限制WT的下单限制,保证回测与实盘代码一致,因此需要修复该问题。

修复建议

采用一个额外的单独订单map来保存下单中创建的订单对象,并在每轮on_tick执行前,将该订单map合并到_orders中。

其他

触发错误的订单,总是在on_trade中交易的
image

SEL引擎回测股票时,stra_get_time 返回都是 2359

分支版本:dev-0.93
ExtDataLoader 获取数据用的postgresql数据库中准备好的数据,并且是能正常加载数据的。
image

策略模板是用的 demos/sel_fut_bt/Strategies/DualThrust_Sel.py 这个模板,结果回测时,isInTradingTime(curTime) 一直返回False,因为curTime = 2359,导致回测无法执行,而且当注释这个交易时间的判断后,context.stra_get_bars 返回数据为空
image

是不是我哪里的配置有问题呢 ?

另外请教下 extDataLoader能否增加一个自定义的dict参数,用于传入一些自定义参数,来限制每次获取数据的条数,因为现在看到每次查询查询标的时,都是查询该标的所有的数据,比如我只想回测 2020年-2021年时间段内的数据,但是因为在extDataLoader中获取不到回测区间参数,每次默认查询该标的 1991年到2022年时间段内的数据,这样对查询性能比较低。

Originally posted by @RickyLoveFreedom in #57

WT控制台

(1) WT控制台通道管理没有任何数据
(2) WT控制台在多账户的情况下,只显示一个账户的持仓,其余的均不显示

请问上诉功能是不是还未开发?

撮合触发的事件逻辑有问题

如果_left没有变,比如curQty为0,仍然会触发on_trader和on_order

	for(uint32_t curQty : vols)
	{
		on_trade(ordInfo._localid, ordInfo._code, ordInfo._isBuy, curQty, curPx, ordInfo._usertag);

		ordInfo._left -= curQty;
		on_order(localid, ordInfo._code, ordInfo._isBuy, ordInfo._total, ordInfo._left, ordInfo._price, false, ordInfo._usertag);

		double curPos = stra_get_position(ordInfo._code);

		_sig_logs << _replayer->get_date() << "." << _replayer->get_raw_time() << "." << _replayer->get_secs() << ","
			<< (ordInfo._isBuy ? "+" : "-") << curQty << "," << curPos << "," << curPx << std::endl;
	}

TraderXTP的direction判断有问题

XTP头文件里面写了这么一段,会导致direction相关判断,if始终进入else分支

///开平标志,期权用户关注字段,其余用户填0即可
XTP_POSITION_EFFECT_TYPE position_effect;

TradeXTP.CPP
inline WTSDirectionType wrapDirectionType(XTP_SIDE_TYPE side, XTP_POSITION_EFFECT_TYPE pe)
{
if (XTP_SIDE_BUY == side)
if (pe == XTP_POSITION_EFFECT_OPEN)
return WDT_LONG;
else
return WDT_SHORT; // 始终进入else
else
if (pe == XTP_POSITION_EFFECT_OPEN)
return WDT_SHORT;
else
return WDT_LONG; // 始终进入else
}

WT中HFT模式下是否支持多周期的策略

首先非常感谢您开源这么好的项目。我想咨询下,WT中HFT模式下是否支持多周期的策略,比如在我的策略中,需要几个周期进行共振的,比如1分钟,5分钟15分钟之类的,这样该如何订阅呢,我看HFTDEMO中有on_bar这个回调,但是如何订阅不同分钟数据,来触发这个回调函数呢?WT这个是否支持呢,如果支持,麻烦您指点下我该如何订阅多周期,我找了好久都没有找到。非常感谢。

回测中异步的撤单有时无法触发on_order回报

使用hft引擎进行tick级别回测时,撤单有时无法触发on_order,但实盘没有这种问题

bool HftMocker::stra_cancel(uint32_t localid)
{
	postTask([this, localid](){
		auto it = _orders.find(localid);
		if (it == _orders.end())
			return;

		StdLocker<StdRecurMutex> lock(_mtx_ords);
		OrderInfo& ordInfo = (OrderInfo&)it->second;
		ordInfo._left = 0;

		on_order(localid, ordInfo._code, ordInfo._isBuy, ordInfo._total, ordInfo._left, ordInfo._price, true, ordInfo._usertag);
		_orders.erase(it);
	});

	return true;
}

游标问题

以下部分应将判断改为大于,而不是大于等于

if (itemList._cursor >= itemList._count)

if (itemList._cursor >= itemList._count)

if (itemList._cursor >= itemList._count)

if (itemList._cursor >= itemList._count)

以下部分应该增加对游标的判断

if (itemList._items.empty())

if(tickList._items.empty())

if (itemList._items.empty())

replayHftDatasByDay中,tick回测强制要求所有数据存在

使用HFT引擎进行tick级别的回测,在replayHftDatasByDay函数下的如下代码中,没有对tick数据是否存在进行判断,

auto& tickList = _ticks_cache[stdCode];

该步骤没有判断stdCode对应的数据是否存在,即便没有加载对应的dsb数据,也会进行读取,然后会在第二步跑出索引错误。

WTSTickStruct& nextTick = tickList._items[tickList._cursor - 1];
//3、第三步再回放tick数据
for (auto& v : _tick_sub_map)
{
	//std::string stdCode = v.first;
	const char* stdCode = v.first.c_str();
	auto& tickList = _ticks_cache[stdCode];
	WTSTickStruct& nextTick = tickList._items[tickList._cursor - 1];
	uint64_t lastTime = (uint64_t)nextTick.action_date * 1000000000 + nextTick.action_time;
	if (lastTime <= nextTime)
	{
		update_price(stdCode, nextTick.price);
		WTSTickData* newTick = WTSTickData::create(nextTick);
		newTick->setCode(stdCode);
		_listener->handle_tick(stdCode, newTick);
		newTick->release();

		tickList._cursor++;
		total_ticks++;
	}
}

回测中,条件单跨日导致成交异常。

在实盘中,每个交易开始于结束前,会对程序进行重启,会清空当前的条件单设置。
但是在回测中,可以在交易日的最后时刻设置条件单,并跨日。即便设置了tick撮合,在跨节假日时,由于前一天没有tick,撮合模式会自动转为模拟tick,当出现跳空时,条件单会成交在跳空间。从而导致绩效异常。
@Y)FFVBS)$84I)XT0__739C
建议在回测中,每个交易日结束时,清空已有的条件单列表。

回测时,只有一个股票,且使用日线和tick时,不能自动判断出_main_key来

下面的HisDataReplayer::run 有个bug,只有一个股票,且使用日线和tick时,不能自动判断出_main_key来,从而进入了run_by_ticks回测。
因为这时候只有一个股票,且使用日线,下面代码中的 barsList->_period =KP_DAY, barsList->_times = 1。
会进入else if(barsList->_period == minPeriod) 分支,但是 if(barsList->_times < minTimes) 条件不满足,导致判断不出_main_key,因为barsList->_times 和 minTimes 都是1,不满足小于判断。

void HisDataReplayer::run(bool bNeedDump/* = false*/)
{
	if(_task == NULL)
	{
		//如果没有时间调度任务,则采用主K线回放的模式

		//如果没有确定主K线,则确定一个周期最短的主K线
		if (_main_key.empty() && !_bars_cache.empty())
		{
			WTSKlinePeriod minPeriod = KP_DAY;
			uint32_t minTimes = 1;       
			for(auto& m : _bars_cache)
			{
				const BarsListPtr& barsList = m.second;
				if (barsList->_period < minPeriod)
				{
					minPeriod = barsList->_period;
					minTimes = barsList->_times;
					_main_key = m.first;
				}
				else if(barsList->_period == minPeriod)
				{
					if(barsList->_times < minTimes)
					{
						_main_key = m.first;
						minTimes = barsList->_times;
					}
				}
			}

			WTSLogger::info("Main K bars automatic determined: {}", _main_key.c_str());
		}

解决方法:定义 minTimes 时,改成大于1的数字就行了
uint32_t minTimes = 2; 把这里改成2就可以了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.