From 9b0d6fd0a05ee6b6e751b014b6a0ecfbe6964652 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Fri, 6 Apr 2018 20:56:19 -0400 Subject: [PATCH 01/15] v --- UML/dataRecord.puml | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 UML/dataRecord.puml diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml new file mode 100644 index 00000000..57a825d0 --- /dev/null +++ b/UML/dataRecord.puml @@ -0,0 +1,86 @@ +@startuml +participant runDataRecord as run +participant mongoDB as db +participant MainEngine as me +participant DrEngine as dr +participant Queue as drq +participant eventEngine as ee +participant Queue as eeq +participant ibGateway as gw + +activate db +activate run +'create ee +run->ee: new evnetEngine() +activate ee + +ee->ee: __init__() +activate ee +create eeq +ee->eeq: Create Queue +activate eeq +ee->ee: Create Child Thread +deactivate ee + +create me +run->me: new mainEngine(ee) +activate me +me->ee: ee.start() +note right +启动ee的子线程 +end note +me->me:创建DataEngine() + + +run->me: addGateway(ibGateway) +run->me: addApp() +run->ee: regiser() 注册日志处理事件 +run->me: 连接IB网关 +create dr +me->dr: new DrEngine(me,ee) + +activate dr + +dr->dr:loadSetting() +note right +从配置文件中加载 +订阅设置到字典对象 +end note +create drq +dr->drq:Create Queue +activate drq +dr->ee:register(TICK, handler) +deactivate ee +gw-->eeq: queue.put(tick/bar) +activate ee #red +loop +ee->eeq:queue.get() +eeq-->ee: Message +ee->ee: process(mesage) +end +ee->dr:call procecssTickEvent() +deactivate ee +activate dr #blue +dr->dr:OnTick() +activate dr +dr->drq: queue.put(tick) +deactivate dr +dr->dr:OnBar() +activate dr +dr->drq: queue.put(bar) +deactivate dr +deactivate dr +deactivate dr + +dr->dr:run() +activate dr #blue +loop +dr->drq:queue.get() +drq-->dr:data +dr->me:insertDB(data) +end +deactivate dr + +me->db: 写入mongoDB + +@enduml From 244cfb0f7f78fc68539e1159c3cf92becce76eaa Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Sat, 7 Apr 2018 05:45:17 -0400 Subject: [PATCH 02/15] v --- UML/dataRecord.puml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index 57a825d0..29dcce2f 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -14,6 +14,7 @@ activate run run->ee: new evnetEngine() activate ee + ee->ee: __init__() activate ee create eeq @@ -22,6 +23,7 @@ activate eeq ee->ee: Create Child Thread deactivate ee + create me run->me: new mainEngine(ee) activate me From adf1cc6ff2a5530ab3f8eb9b3dfe1a4eb9e9b497 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Sun, 8 Apr 2018 10:31:33 -0400 Subject: [PATCH 03/15] v --- UML/dataRecord.puml | 177 ++++++++++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 73 deletions(-) diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index 29dcce2f..53ec1870 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -1,88 +1,119 @@ @startuml +database mongoDB as db participant runDataRecord as run -participant mongoDB as db participant MainEngine as me +participant DataEngine as dt +participant LogEngine as le participant DrEngine as dr participant Queue as drq +participant Thread as drt participant eventEngine as ee +participant Thread as eet participant Queue as eeq participant ibGateway as gw -activate db + activate run -'create ee -run->ee: new evnetEngine() -activate ee + run->ee ** :create evnetEngine object + activate ee + ee->ee ++ : init() + ee->eeq ** : Create Queue + ee->eet ** : Create Child Thread + return + return object +||| +||| + run->me ** : new mainEngine(ee) + activate me + me->me ++ : init() + me->ee ++ : ee.start() + note right: 启动ee的子线程 + ee->eet ++ #red : thread.start() + ee-->me--: return + me->dt ** :创建DataEngine() + activate dt + dt->dt ++ : init() + return + return object + me->le ** :创建LogEngine() + activate le + le->le ++ : init() + return + return + me-->me--:return + me-->run--:return object +||| +||| + run->me: addGateway(ibGateway) + activate me + return +||| +||| + run->me: addApp() + activate me + return +||| +||| + run->ee: ee.regiser() 注册日志处理事件 + activate ee + return +||| +||| + run->me++: me.Connect(IB) + note right: 连接IB网关 + me->dr**: new DrEngine(me,ee) + activate dr + dr->dr++:init() + dr->drq **:Create Queue + dr->drt **:Create Thread + activate drt #blue + dr->dr:loadSetting() + note right + 从配置文件中加载 + 订阅设置到字典对象 + end note + dr->ee++:register(TICK, handler) + return + dr-->dr -- : return + 'return object + dr-->me--: object + run<--me--:return + +||| +||| + eet->ee--: ee.run() + activate ee #red + loop + ee->eeq:queue.get() + gw->eeq ++: queue.put(tick/bar) + return + eeq-->ee: event + ee->ee ++ : __process(event) + ee->dr ++ #red :call procecssTickEvent() + dr->dr ++ :OnTick() + dr->drq ++: queue.put(tick) + return + return + + dr->dr ++ :OnBar() + dr->drq ++: queue.put(bar) + return + return + return + return + end loop + deactivate ee -ee->ee: __init__() -activate ee -create eeq -ee->eeq: Create Queue -activate eeq -ee->ee: Create Child Thread -deactivate ee + drt->dr -- :run() + activate dr #blue + loop + dr->drq ++ :queue.get() + drq-->dr --:data + dr->me:insertDB(data) + end loop + deactivate dr - -create me -run->me: new mainEngine(ee) -activate me -me->ee: ee.start() -note right -启动ee的子线程 -end note -me->me:创建DataEngine() - - -run->me: addGateway(ibGateway) -run->me: addApp() -run->ee: regiser() 注册日志处理事件 -run->me: 连接IB网关 -create dr -me->dr: new DrEngine(me,ee) - -activate dr - -dr->dr:loadSetting() -note right -从配置文件中加载 -订阅设置到字典对象 -end note -create drq -dr->drq:Create Queue -activate drq -dr->ee:register(TICK, handler) -deactivate ee -gw-->eeq: queue.put(tick/bar) -activate ee #red -loop -ee->eeq:queue.get() -eeq-->ee: Message -ee->ee: process(mesage) -end -ee->dr:call procecssTickEvent() -deactivate ee -activate dr #blue -dr->dr:OnTick() -activate dr -dr->drq: queue.put(tick) -deactivate dr -dr->dr:OnBar() -activate dr -dr->drq: queue.put(bar) -deactivate dr -deactivate dr -deactivate dr - -dr->dr:run() -activate dr #blue -loop -dr->drq:queue.get() -drq-->dr:data -dr->me:insertDB(data) -end -deactivate dr - -me->db: 写入mongoDB + me->db: 写入mongoDB @enduml From 932143d2ddd08711db74d934e615e8b0446cfb05 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Mon, 9 Apr 2018 04:44:04 -0400 Subject: [PATCH 04/15] v --- UML/dataRecord.puml | 209 +++++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 81 deletions(-) diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index 53ec1870..97b129db 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -1,119 +1,166 @@ @startuml database mongoDB as db -participant runDataRecord as run +participant runDataRecord as rundr +participant Process as run participant MainEngine as me +participant LogEngine as runle participant DataEngine as dt participant LogEngine as le participant DrEngine as dr participant Queue as drq participant Thread as drt participant eventEngine as ee -participant Thread as eet +participant EventProcessThread as eet participant Queue as eeq +participant TimerThread as eetm participant ibGateway as gw -activate run - run->ee ** :create evnetEngine object - activate ee - ee->ee ++ : init() - ee->eeq ** : Create Queue - ee->eet ** : Create Child Thread - return - return object +activate rundr + loop + rundr->rundr: 检查是否处于时间段 + rundr->rundr: 监控子进程是否存在 + rundr->run ** : create process + activate run + rundr->rundr: sleep(5) + end loop + deactivate rundr + +run->runle ** : create runle ||| ||| - run->me ** : new mainEngine(ee) - activate me - me->me ++ : init() - me->ee ++ : ee.start() - note right: 启动ee的子线程 - ee->eet ++ #red : thread.start() - ee-->me--: return - me->dt ** :创建DataEngine() - activate dt - dt->dt ++ : init() - return - return object - me->le ** :创建LogEngine() - activate le - le->le ++ : init() - return - return - me-->me--:return - me-->run--:return object -||| -||| - run->me: addGateway(ibGateway) - activate me +run->ee ** :create evnetEngine object + activate ee + ee->ee ++ : init() + ee->eeq ** : Create Queue + ee->eet ** : Create event process thread + note right: 事件处理子线程 + ee->eetm ** : Create timer thread + note right: 定时器子线程 return + return object ||| ||| - run->me: addApp() +run->me ** : new mainEngine(ee) + activate me + me->me ++ : init() + me->ee ++ : ee.start() + note right: 启动ee的子线程 + ee->eet ++ #red : thread.start() + ee->eetm ++ #green : timer.start() + ee-->me--: return + me->dt ** :创建DataEngine() + activate dt + dt->dt ++ : init() + return + return object + me->le ** :创建LogEngine() + activate le + le->le ++ : init() + return + return + me-->me--:return + me-->run--: object +||| +||| +run->me: addGateway(ibGateway) activate me return ||| ||| - run->ee: ee.regiser() 注册日志处理事件 +run->me: addApp() + activate me + return +||| +||| +run->ee: ee.regiser() 注册日志处理事件 activate ee return ||| ||| - run->me++: me.Connect(IB) - note right: 连接IB网关 - me->dr**: new DrEngine(me,ee) - activate dr - dr->dr++:init() - dr->drq **:Create Queue - dr->drt **:Create Thread - activate drt #blue - dr->dr:loadSetting() - note right - 从配置文件中加载 - 订阅设置到字典对象 - end note - dr->ee++:register(TICK, handler) - return - dr-->dr -- : return - 'return object - dr-->me--: object - run<--me--:return +run->me++: me.Connect(IB) + note right: 连接IB网关 + me->dr**: new DrEngine(me,ee) + activate dr + dr->dr++:init() + dr->drq **:Create Queue + dr->drt **:Create Thread + activate drt #blue + dr->dr:loadSetting() + note right + 从配置文件中加载 + 订阅设置到字典对象 + end note + dr->ee++:register(TICK, handler) + return + dr-->dr -- : return + 'return object + dr-->me--: object + run<--me--:return ||| ||| - eet->ee--: ee.run() - activate ee #red - loop - ee->eeq:queue.get() - gw->eeq ++: queue.put(tick/bar) - return - eeq-->ee: event - ee->ee ++ : __process(event) - ee->dr ++ #red :call procecssTickEvent() - dr->dr ++ :OnTick() - dr->drq ++: queue.put(tick) - return - return +run->ee ++ : ee.register(EVENT_LOG, le.processLogEvent) + return - dr->dr ++ :OnBar() - dr->drq ++: queue.put(bar) - return +||| +||| +run->ee ++ : ee.register(EVENT_ERROR, le.processErrorEvent) + return + +||| +||| +loop + run->run: sleep(1) +end loop +deactivate run +||| +||| +gw->eeq ++: queue.put(tick/bar) + return +||| +||| +eetm->ee -- : ee.__runTimer() + activate ee #green + loop + ee->eeq ++ : queue.put(定时器事件) + return + ee->ee : 休眠1秒 + end loop + deactivate ee +||| +||| +eet->ee--: ee.run() + activate ee #red + loop + ee->eeq ++ :queue.get() + return event + ee->ee ++ : __process(event) + ee->dr ++ #red :call procecssTickEvent() + dr->dr ++ :OnTick() + dr->drq ++: queue.put(tick) + return + return + + dr->dr ++ :OnBar() + dr->drq ++: queue.put(bar) return return return - end loop - deactivate ee + return + end loop + deactivate ee - drt->dr -- :run() - activate dr #blue - loop - dr->drq ++ :queue.get() - drq-->dr --:data - dr->me:insertDB(data) - end loop - deactivate dr +drt->dr -- :run() + activate dr #blue + loop + dr->drq ++ :queue.get() + drq-->dr --:data + dr->me:insertDB(data) + end loop + deactivate dr - me->db: 写入mongoDB +me->db: 写入mongoDB @enduml From a0575aa7bf99f80a4b127fbf31234d3b73315bc1 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Mon, 9 Apr 2018 05:33:16 -0400 Subject: [PATCH 05/15] =?UTF-8?q?=E6=96=B0=E5=A2=9EREADME.md=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UML/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 UML/README.md diff --git a/UML/README.md b/UML/README.md new file mode 100644 index 00000000..d99161ea --- /dev/null +++ b/UML/README.md @@ -0,0 +1,9 @@ +#vnpy的部分场景的UML时序图 + +本UML资料使用plantUML作成。 +下载地址 http://plantuml.com + +NO | 场景 | vnpy入口源代码文件 | UML文件名 +---|---------------|------------------|----------- + 1| 实时市场数据采集 | example/DataRecording/runDataRecording.py| dataRecord.puml + \ No newline at end of file From 4aaf77a4233c240fa81fc08cfd4cc679cc9e0c1a Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Mon, 9 Apr 2018 20:18:24 +0800 Subject: [PATCH 06/15] =?UTF-8?q?=E6=96=B0=E5=A2=9EDataEngine=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UML/dataRecord.puml | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index 97b129db..df16137e 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -4,7 +4,7 @@ participant runDataRecord as rundr participant Process as run participant MainEngine as me participant LogEngine as runle -participant DataEngine as dt +participant DataEngine as dte participant LogEngine as le participant DrEngine as dr participant Queue as drq @@ -49,9 +49,24 @@ run->me ** : new mainEngine(ee) ee->eet ++ #red : thread.start() ee->eetm ++ #green : timer.start() ee-->me--: return - me->dt ** :创建DataEngine() - activate dt - dt->dt ++ : init() + me->dte ** :创建DataEngine() + activate dte + dte->dte ++ : init() + dte->dte ++ : registerEvent() + dte->ee ++ : ee.register(EVENT_CONTRACT, self.processContractEvent) + return + dte->ee ++ : ee.register(EVENT_ORDER, self.processOrderEvent) + return + dte->ee ++ : ee.register(EVENT_TRADE, self.processTradeEvent) + return + dte->ee ++ : ee.register(EVENT_POSITION, self.processPositionEvent) + return + dte->ee ++ : ee.register(EVENT_ACCOUNT, self.processAccountEvent) + return + dte->ee ++ : ee.register(EVENT_LOG, self.processLogEvent) + return + dte->ee ++ : ee.register(EVENT_ERROR, self.processErrorEvent) + return return return object me->le ** :创建LogEngine() From f5d87ba8af7da16fedc5329376933e1302d01eb4 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Tue, 10 Apr 2018 02:41:45 -0400 Subject: [PATCH 07/15] v --- UML/dataRecord.puml | 107 ++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index df16137e..a8a781a3 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -13,14 +13,18 @@ participant eventEngine as ee participant EventProcessThread as eet participant Queue as eeq participant TimerThread as eetm -participant ibGateway as gw +participant "ibGateway:vtGateway" as gw +participant "IbWrapper:EWrapper" as wrap + + + activate rundr loop - rundr->rundr: 检查是否处于时间段 - rundr->rundr: 监控子进程是否存在 - rundr->run ** : create process + rundr->rundr: 检查是否处于交易时间段\n非交易时间段不起动子进程 + rundr->rundr: 若处于非交易时间段 && 有子进程存在,\n就终止子进程运行 + rundr->run ** : 若处于交易时间段 && 不存在子进程\ncreate process activate run rundr->rundr: sleep(5) end loop @@ -52,21 +56,24 @@ run->me ** : new mainEngine(ee) me->dte ** :创建DataEngine() activate dte dte->dte ++ : init() + dte->dte ++ : loadContract() + return + ||| dte->dte ++ : registerEvent() - dte->ee ++ : ee.register(EVENT_CONTRACT, self.processContractEvent) - return - dte->ee ++ : ee.register(EVENT_ORDER, self.processOrderEvent) - return - dte->ee ++ : ee.register(EVENT_TRADE, self.processTradeEvent) - return - dte->ee ++ : ee.register(EVENT_POSITION, self.processPositionEvent) - return - dte->ee ++ : ee.register(EVENT_ACCOUNT, self.processAccountEvent) - return - dte->ee ++ : ee.register(EVENT_LOG, self.processLogEvent) - return - dte->ee ++ : ee.register(EVENT_ERROR, self.processErrorEvent) + dte->ee ++ : ee.register(交易类事件, 对应的事件处理句柄) + note right + **以下事件处理句柄都在DataEngine中定义** + + (EVENT_CONTRACT, processContractEvent) 合约 + (EVENT_ORDER, processOrderEvent) 订单 + (EVENT_TRADE, processTradeEvent) 交易 + (EVENT_POSITION, processPositionEvent) 头寸 + (EVENT_ACCOUNT, processAccountEvent) 帐号 + (EVENT_LOG, processLogEvent) LOG + (EVENT_ERROR, processErrorEvent) ERROR + end note return + return return return object me->le ** :创建LogEngine() @@ -78,23 +85,31 @@ run->me ** : new mainEngine(ee) me-->run--: object ||| ||| -run->me: addGateway(ibGateway) - activate me +run->me ++ : addGateway(ibGateway) + me->gw ** : Create IbGateway(ee, "IB") + activate gw + gw->gw ++ : init() + note right + ** 将ee保存到私有变量 + ** 内部变量初始化为空 + ** 获取连接IB G/W的信息 + end note + gw->wrap ** : Create IbWrap(self) + note right + EWrapper类是C++实现, 存在于IB提供的源代码中。 + 通过boost.python机制, + Python的IbWrapper类从EWrapper派生 + end note + activate wrap + wrap->wrap ++ : 构造函数() + return object + return object + return + return object return ||| ||| -run->me: addApp() - activate me - return -||| -||| -run->ee: ee.regiser() 注册日志处理事件 - activate ee - return -||| -||| -run->me++: me.Connect(IB) - note right: 连接IB网关 +run->me ++ : addApp() me->dr**: new DrEngine(me,ee) activate dr dr->dr++:init() @@ -108,9 +123,35 @@ run->me++: me.Connect(IB) end note dr->ee++:register(TICK, handler) return - dr-->dr -- : return - 'return object + dr-->dr -- : dr-->me--: object + ||| + me->me ++ : 初始化其他内部变量 + return + + run<--me -- : return +||| +||| +run->ee: ee.regiser() 注册日志处理事件 + activate ee + note right + 登记EVENT_LOG事件处理句柄 + 登记EVENT_ERROR事件处理句柄 + end note + return +||| +||| +run->me++: me.Connect(IB) + note right: 连接IB网关 + me->gw ++ : gw.connect() + gw-> wrap : wrap.eConnect(host, port, clientId, false) + return + me->me ++ : dbConnect() + me->db ++ : MongoClient() + return dbClinet + me->ee ++ : ee.register(EVENT_LOG, self.dbLogging) + return + return run<--me--:return ||| From e8059cfc4b13b193760046b264dc2db6ee729176 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Tue, 10 Apr 2018 05:36:43 -0400 Subject: [PATCH 08/15] v --- UML/IbApi.puml | 59 +++++++++++++++++++++++++++++++++++++++++++++ UML/dataRecord.puml | 15 ++++++++---- 2 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 UML/IbApi.puml diff --git a/UML/IbApi.puml b/UML/IbApi.puml new file mode 100644 index 00000000..f01aa8c7 --- /dev/null +++ b/UML/IbApi.puml @@ -0,0 +1,59 @@ +@startuml + +abstract class EWrapper +class IbWrapper +class VnIbApi +class IbApiWrap +class IbApi + + +EWrapper <|-- IbWrapper +IbWrapper *-- VnIbApi +IbWrapper --* VnIbApi +VnIbApi <|-- IbApiWrap : Boost.python封装 +note right +实际上是结构体struct。 +按照Boost.python的规范封装 +end note + +IbApiWrap <|-- IbApi : Boost.python封装 +note right +按照Boost.python的规范封装 +Python的程序对接使用此类型。 +end note + + + + +abstract class EWrapper { +} +note right +提供IB网关返回响应数据后,会调用回调函数。 +此类定义了回调函数的接口。 +end note + +class IbWrapper { + - VnIbApi *api; +} +note right +此类用于实现回调函数的接口。 +end note + +class VnIbApi { + - IbWrapper *wrapper; + - EReaderOSSignal signal; + - EReader *reader; + + EClientSocket *client; +} +note right +**VnIbApi中包含EClientSocket和IbWrapper成员** + +EClientSocket:提供应用程序发起请求到IB网关的API函数 +IbWrapper: 提供IB网关返回响应数据后的回调函数 +end note + + + + + +@enduml \ No newline at end of file diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index a8a781a3..f894fb58 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -14,7 +14,7 @@ participant EventProcessThread as eet participant Queue as eeq participant TimerThread as eetm participant "ibGateway:vtGateway" as gw -participant "IbWrapper:EWrapper" as wrap +participant "IbWrapper:IbApi" as wrap @@ -96,9 +96,13 @@ run->me ++ : addGateway(ibGateway) end note gw->wrap ** : Create IbWrap(self) note right - EWrapper类是C++实现, 存在于IB提供的源代码中。 - 通过boost.python机制, - Python的IbWrapper类从EWrapper派生 + IbApi是基于Boost.python的封装。 + 用C++实现,但是可以提供给Python程序使用。 + IbApi使用IB提供的C++接口源代码, + 来和IB网关进行数据交互 + IbApi提供两类函数功能: + 主动请求IB网关的功能 + 接收IB网关异步返回数据的功能 end note activate wrap wrap->wrap ++ : 构造函数() @@ -144,7 +148,8 @@ run->ee: ee.regiser() 注册日志处理事件 run->me++: me.Connect(IB) note right: 连接IB网关 me->gw ++ : gw.connect() - gw-> wrap : wrap.eConnect(host, port, clientId, false) + gw-> wrap ++ : wrap.eConnect(host, port, clientId, false) + return return me->me ++ : dbConnect() me->db ++ : MongoClient() From 12b1e10c51ae31fa1a0520fca555ef6426a4f051 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Thu, 12 Apr 2018 05:51:29 -0400 Subject: [PATCH 09/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UML/IbApi.puml | 16 +++++++++++++++ UML/README.md | 2 +- UML/dataRecord.puml | 47 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/UML/IbApi.puml b/UML/IbApi.puml index f01aa8c7..81324f51 100644 --- a/UML/IbApi.puml +++ b/UML/IbApi.puml @@ -1,14 +1,18 @@ @startuml +class EClient +class EClientSocket abstract class EWrapper class IbWrapper class VnIbApi class IbApiWrap class IbApi +EClient <|-- EClientSocket EWrapper <|-- IbWrapper IbWrapper *-- VnIbApi +EClientSocket *-- VnIbApi IbWrapper --* VnIbApi VnIbApi <|-- IbApiWrap : Boost.python封装 note right @@ -23,7 +27,19 @@ Python的程序对接使用此类型。 end note +class EClient { +} +note right +IB提供的C++源代码。 +此类定义了应用程序向IB网关发起请求的主动函数。 +end note +class EClientSocket { +} +note right +IB提供的C++源代码。 +此类定义了应用程序向IB网关发起请求的主动函数。 +end note abstract class EWrapper { } diff --git a/UML/README.md b/UML/README.md index d99161ea..77fe7dfe 100644 --- a/UML/README.md +++ b/UML/README.md @@ -6,4 +6,4 @@ NO | 场景 | vnpy入口源代码文件 | UML文件名 ---|---------------|------------------|----------- 1| 实时市场数据采集 | example/DataRecording/runDataRecording.py| dataRecord.puml - \ No newline at end of file + 2|IB API封装方法 | vnpy/api/ib/vnib/vnib/vnib.cpp .h/ |IbApi.puml \ No newline at end of file diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index f894fb58..461f2262 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -15,6 +15,7 @@ participant Queue as eeq participant TimerThread as eetm participant "ibGateway:vtGateway" as gw participant "IbWrapper:IbApi" as wrap +participant "IB Gateway/IB TWS" as ib @@ -94,7 +95,7 @@ run->me ++ : addGateway(ibGateway) ** 内部变量初始化为空 ** 获取连接IB G/W的信息 end note - gw->wrap ** : Create IbWrap(self) + gw->wrap ** : Create IbWrapper(self) note right IbApi是基于Boost.python的封装。 用C++实现,但是可以提供给Python程序使用。 @@ -126,6 +127,7 @@ run->me ++ : addApp() 订阅设置到字典对象 end note dr->ee++:register(TICK, handler) + note right: 登记EVENT_TICK事件 return dr-->dr -- : dr-->me--: object @@ -148,9 +150,50 @@ run->ee: ee.regiser() 注册日志处理事件 run->me++: me.Connect(IB) note right: 连接IB网关 me->gw ++ : gw.connect() - gw-> wrap ++ : wrap.eConnect(host, port, clientId, false) + gw-> wrap ++ : ibwrapper.eConnect(host, port, clientId, false) + wrap-\ib ++ : 调用IB的C++代码,发送连接请求数据包到IB网关 + return + return + + + gw->wrap ++ : ibwrapper.reqCurrentTime() + wrap->ib ++: 调用IB的C++代码,发送服务器时间查询数据包到IB网关 + return + return + + return + + ib-/ wrap ++ : connectAck()\nIB网关发回响应数据包到IB的C++代码,该代码回调函数 + return + + ib->wrap ++ : currentTime()\nIB网关发回响应数据包到IB的C++代码,该代码回调函数 + wrap->gw ++ : 修改连接状态\ngateway.conntected=true + return + + wrap->gw ++ : 订阅市场行情\nsubscribe(subscribeReq) + gw->wrap ++ : 请求合约详细\nreqContractDetails(self.tickerId, contract) + return + gw->wrap ++ : 请求市场数据\nreqMktData(self.tickerId, contract, '', False, TagValueList()) + return + ||| + return + ||| + return + + ib->wrap ++ : contractDetails(reqId, contractDetails)\nIB网关响应的合约信息通过回调函数传入 + wrap -> gw ++ : OnContract(contract)\n推送事件 + gw->ee ++ : ee.put(event(EVENT_CONTRACT, contract)) + return return return + + ib->wrap ++ : tickPrice(tickerId, field, price, canAutoExecute)\nIB网关响应的合约信息通过回调函数传入 + wrap -> gw ++ : OnTick(tick)\n推送事件 + gw->ee ++ : ee.put(event(EVENT_TICK, tick)) + return + return + return + me->me ++ : dbConnect() me->db ++ : MongoClient() return dbClinet From 727ea4bae2d6f7aa1bb2eb3dd72321a197a63262 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Thu, 12 Apr 2018 23:56:30 -0400 Subject: [PATCH 10/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UML/dataRecord.puml | 28 ++++------------------------ UML/version.puml | 3 +++ 2 files changed, 7 insertions(+), 24 deletions(-) create mode 100644 UML/version.puml diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index 461f2262..feb44325 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -1,4 +1,7 @@ @startuml + +title Data Recording + database mongoDB as db participant runDataRecord as rundr participant Process as run @@ -33,7 +36,6 @@ activate rundr run->runle ** : create runle ||| -||| run->ee ** :create evnetEngine object activate ee ee->ee ++ : init() @@ -45,7 +47,6 @@ run->ee ** :create evnetEngine object return return object ||| -||| run->me ** : new mainEngine(ee) activate me me->me ++ : init() @@ -85,7 +86,6 @@ run->me ** : new mainEngine(ee) me-->me--:return me-->run--: object ||| -||| run->me ++ : addGateway(ibGateway) me->gw ** : Create IbGateway(ee, "IB") activate gw @@ -96,15 +96,7 @@ run->me ++ : addGateway(ibGateway) ** 获取连接IB G/W的信息 end note gw->wrap ** : Create IbWrapper(self) - note right - IbApi是基于Boost.python的封装。 - 用C++实现,但是可以提供给Python程序使用。 - IbApi使用IB提供的C++接口源代码, - 来和IB网关进行数据交互 - IbApi提供两类函数功能: - 主动请求IB网关的功能 - 接收IB网关异步返回数据的功能 - end note + note right: IbApi是基于Boost.python的封装。\n用C++实现,但是可以提供给Python程序使用。 activate wrap wrap->wrap ++ : 构造函数() return object @@ -113,7 +105,6 @@ run->me ++ : addGateway(ibGateway) return object return ||| -||| run->me ++ : addApp() me->dr**: new DrEngine(me,ee) activate dr @@ -137,7 +128,6 @@ run->me ++ : addApp() run<--me -- : return ||| -||| run->ee: ee.regiser() 注册日志处理事件 activate ee note right @@ -146,7 +136,6 @@ run->ee: ee.regiser() 注册日志处理事件 end note return ||| -||| run->me++: me.Connect(IB) note right: 连接IB网关 me->gw ++ : gw.connect() @@ -201,29 +190,21 @@ run->me++: me.Connect(IB) return return run<--me--:return - -||| ||| run->ee ++ : ee.register(EVENT_LOG, le.processLogEvent) return - -||| ||| run->ee ++ : ee.register(EVENT_ERROR, le.processErrorEvent) return - -||| ||| loop run->run: sleep(1) end loop deactivate run ||| -||| gw->eeq ++: queue.put(tick/bar) return ||| -||| eetm->ee -- : ee.__runTimer() activate ee #green loop @@ -233,7 +214,6 @@ eetm->ee -- : ee.__runTimer() end loop deactivate ee ||| -||| eet->ee--: ee.run() activate ee #red loop diff --git a/UML/version.puml b/UML/version.puml new file mode 100644 index 00000000..f03b2d89 --- /dev/null +++ b/UML/version.puml @@ -0,0 +1,3 @@ +@startuml +version +@enduml \ No newline at end of file From c36a58d5e35a5f3cc1b69234cbb0715ddb96cbf2 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Thu, 12 Apr 2018 23:57:02 -0400 Subject: [PATCH 11/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/HistDataCollector/HD_setting.json | 15 +++ .../HistDataCollector/runHistDataCollector.py | 105 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 examples/HistDataCollector/HD_setting.json create mode 100644 examples/HistDataCollector/runHistDataCollector.py diff --git a/examples/HistDataCollector/HD_setting.json b/examples/HistDataCollector/HD_setting.json new file mode 100644 index 00000000..3294e417 --- /dev/null +++ b/examples/HistDataCollector/HD_setting.json @@ -0,0 +1,15 @@ +{ + "working": true, + + "tick": + [ + ["700", "IB", "SEHK", "HKD", "股票"], + ["USD.JPY", "IB", "IDEALPRO", "JPY", "外汇"] + ], + + "bar": + [ + ["700", "IB", "SEHK", "HKD", "股票"], + ["USD.JPY", "IB", "IDEALPRO", "JPY", "外汇"] + ] +} \ No newline at end of file diff --git a/examples/HistDataCollector/runHistDataCollector.py b/examples/HistDataCollector/runHistDataCollector.py new file mode 100644 index 00000000..604e20a9 --- /dev/null +++ b/examples/HistDataCollector/runHistDataCollector.py @@ -0,0 +1,105 @@ +# encoding: UTF-8 + +import multiprocessing +from time import sleep +from datetime import datetime, time + +from vnpy.event import EventEngine2 +from vnpy.trader.vtEvent import EVENT_LOG, EVENT_ERROR +from vnpy.trader.vtEngine import MainEngine, LogEngine +from vnpy.trader.gateway import ibGateway +from vnpy.trader.app import dataRecorder + + +#---------------------------------------------------------------------- +def processErrorEvent(event): + """ + 处理错误事件 + 错误信息在每次登陆后,会将当日所有已产生的均推送一遍,所以不适合写入日志 + """ + error = event.dict_['data'] + print u'错误代码:%s,错误信息:%s' %(error.errorID, error.errorMsg) + +#---------------------------------------------------------------------- +def runChildProcess(): + """子进程运行函数""" + print '-'*20 + + # 创建日志引擎 + le = LogEngine() + le.setLogLevel(le.LEVEL_DEBUG) + le.addConsoleHandler() + le.info(u'启动行情记录运行子进程') + + ee = EventEngine2() + le.info(u'事件引擎创建成功') + + me = MainEngine(ee) + me.addGateway(ibGateway) + me.addApp(histDataCollector) + le.info(u'主引擎创建成功') + + ee.register(EVENT_LOG, le.processLogEvent) + ee.register(EVENT_ERROR, processErrorEvent) + le.info(u'注册日志事件监听') + + me.connect('IB') + le.info(u'连接IB接口') + + while True: + sleep(1) + +#---------------------------------------------------------------------- +def runParentProcess(): + """父进程运行函数""" + # 创建日志引擎 + le = LogEngine() + le.setLogLevel(le.LEVEL_INFO) + le.addConsoleHandler() + le.info(u'启动HistData守护父进程') + + DAY_START = time(8, 57) # 日盘启动和停止时间 + DAY_END = time(15, 18) + NIGHT_START = time(20, 57) # 夜盘启动和停止时间 + NIGHT_END = time(2, 33) + + p = None # 子进程句柄 + + while True: + currentTime = datetime.now().time() + recording = False + + # 判断当前处于的时间段 + if ((currentTime >= DAY_START and currentTime <= DAY_END) or + (currentTime >= NIGHT_START) or + (currentTime <= NIGHT_END)): + recording = True + + # 过滤周末时间段:周六全天,周五夜盘,周日日盘 + if ((datetime.today().weekday() == 6) or + (datetime.today().weekday() == 5 and currentTime > NIGHT_END) or + (datetime.today().weekday() == 0 and currentTime < DAY_START)): + recording = False + + recording = True + # 记录时间则需要启动子进程 + if recording and p is None: + le.info(u'启动子进程') + p = multiprocessing.Process(target=runChildProcess) + p.start() + le.info(u'子进程启动成功') + + # 非记录时间则退出子进程 + if not recording and p is not None: + le.info(u'关闭子进程') + p.terminate() + p.join() + p = None + le.info(u'子进程关闭成功') + + sleep(5) + + +if __name__ == '__main__': + #runChildProcess() + runParentProcess() From 29dd68e88304fcc223cf73f00542c23dc3dcbaca Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Thu, 12 Apr 2018 23:57:33 -0400 Subject: [PATCH 12/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy/trader/app/histDataCollector/__init__.py | 8 + vnpy/trader/app/histDataCollector/hdcBase.py | 19 ++ .../trader/app/histDataCollector/hdcEngine.py | 274 ++++++++++++++++++ .../histDataCollector/language/__init__.py | 13 + .../language/chinese/__init__.py | 0 .../language/chinese/text.py | 16 + .../language/english/__init__.py | 0 .../language/english/text.py | 15 + 8 files changed, 345 insertions(+) create mode 100644 vnpy/trader/app/histDataCollector/__init__.py create mode 100644 vnpy/trader/app/histDataCollector/hdcBase.py create mode 100644 vnpy/trader/app/histDataCollector/hdcEngine.py create mode 100644 vnpy/trader/app/histDataCollector/language/__init__.py create mode 100644 vnpy/trader/app/histDataCollector/language/chinese/__init__.py create mode 100644 vnpy/trader/app/histDataCollector/language/chinese/text.py create mode 100644 vnpy/trader/app/histDataCollector/language/english/__init__.py create mode 100644 vnpy/trader/app/histDataCollector/language/english/text.py diff --git a/vnpy/trader/app/histDataCollector/__init__.py b/vnpy/trader/app/histDataCollector/__init__.py new file mode 100644 index 00000000..c177142d --- /dev/null +++ b/vnpy/trader/app/histDataCollector/__init__.py @@ -0,0 +1,8 @@ +# encoding: UTF-8 + +from hdcEngine import HdcEngine + + +appName = 'HistDataCollector' +appDisplayName = u'HistData记录' +appEngine = HdcEngine diff --git a/vnpy/trader/app/histDataCollector/hdcBase.py b/vnpy/trader/app/histDataCollector/hdcBase.py new file mode 100644 index 00000000..c7249443 --- /dev/null +++ b/vnpy/trader/app/histDataCollector/hdcBase.py @@ -0,0 +1,19 @@ +# encoding: UTF-8 + +''' +本文件中包含的数据格式和CTA模块通用,用户有必要可以自行添加格式。 +''' + +from __future__ import division + +# 数据库名称 +SETTING_DB_NAME = 'VnTrader_Setting_Db' +TICK_DB_NAME = 'VnTrader_Tick_Db' +DAILY_DB_NAME = 'VnTrader_Daily_Db' +MINUTE_DB_NAME = 'VnTrader_1Min_Db' + +# 行情记录模块事件 +EVENT_DATARECORDER_LOG = 'eHistDataCollectorLog' # 行情记录日志更新事件 + +# CTA引擎中涉及的数据类定义 +from vnpy.trader.vtConstant import EMPTY_UNICODE, EMPTY_STRING, EMPTY_FLOAT, EMPTY_INT diff --git a/vnpy/trader/app/histDataCollector/hdcEngine.py b/vnpy/trader/app/histDataCollector/hdcEngine.py new file mode 100644 index 00000000..703059af --- /dev/null +++ b/vnpy/trader/app/histDataCollector/hdcEngine.py @@ -0,0 +1,274 @@ +# encoding: UTF-8 + +''' +本文件中实现了行情数据记录引擎,用于汇总TICK数据,并生成K线插入数据库。 + +使用DR_setting.json来配置需要收集的合约,以及主力合约代码。 +''' + +import json +import csv +import os +import copy +import traceback +from collections import OrderedDict +from datetime import datetime, timedelta +from Queue import Queue, Empty +from threading import Thread +from pymongo.errors import DuplicateKeyError + +from vnpy.event import Event +from vnpy.trader.vtEvent import * +from vnpy.trader.vtFunction import todayDate, getJsonPath +from vnpy.trader.vtObject import VtSubscribeReq, VtLogData, VtBarData, VtTickData +from vnpy.trader.app.ctaStrategy.ctaTemplate import BarGenerator + +from .hdcBase import * +from .language import text + + +######################################################################## +class HdcEngine(object): + """数据记录引擎""" + + settingFileName = 'HD_setting.json' + settingFilePath = getJsonPath(settingFileName, __file__) + + #---------------------------------------------------------------------- + def __init__(self, mainEngine, eventEngine): + """Constructor""" + self.mainEngine = mainEngine + self.eventEngine = eventEngine + + # 当前日期 + self.today = todayDate() + + # 主力合约代码映射字典,key为具体的合约代码(如IF1604),value为主力合约代码(如IF0000) + self.activeSymbolDict = {} + + # Tick对象字典 + self.tickSymbolSet = set() + + # K线合成器字典 + self.bgDict = {} + + # 配置字典 + self.settingDict = OrderedDict() + + # 负责执行数据库插入的单独线程相关 + self.active = False # 工作状态 + self.queue = Queue() # 队列 + self.thread = Thread(target=self.run) # 线程 + + # 载入设置,订阅行情 + self.loadSetting() + + # 启动数据插入线程 + self.start() + + # 注册事件监听 + self.registerEvent() + + #---------------------------------------------------------------------- + def loadSetting(self): + """加载配置""" + with open(self.settingFilePath) as f: + drSetting = json.load(f) + + # 如果working设为False则不启动行情记录功能 + working = drSetting['working'] + if not working: + return + + # Tick记录配置 + if 'tick' in drSetting: + l = drSetting['tick'] + + for setting in l: + symbol = setting[0] + gateway = setting[1] + vtSymbol = symbol + + req = VtSubscribeReq() + req.symbol = setting[0] + + # 针对LTS和IB接口,订阅行情需要交易所代码 + if len(setting)>=3: + req.exchange = setting[2] + vtSymbol = '.'.join([symbol, req.exchange]) + + # 针对IB接口,订阅行情需要货币和产品类型 + if len(setting)>=5: + req.currency = setting[3] + req.productClass = setting[4] + + self.mainEngine.subscribe(req, gateway) + + #tick = VtTickData() # 该tick实例可以用于缓存部分数据(目前未使用) + #self.tickDict[vtSymbol] = tick + self.tickSymbolSet.add(vtSymbol) + + # 保存到配置字典中 + if vtSymbol not in self.settingDict: + d = { + 'symbol': symbol, + 'gateway': gateway, + 'tick': True + } + self.settingDict[vtSymbol] = d + else: + d = self.settingDict[vtSymbol] + d['tick'] = True + + # 分钟线记录配置 + if 'bar' in drSetting: + l = drSetting['bar'] + + for setting in l: + symbol = setting[0] + gateway = setting[1] + vtSymbol = symbol + + req = VtSubscribeReq() + req.symbol = symbol + + if len(setting)>=3: + req.exchange = setting[2] + vtSymbol = '.'.join([symbol, req.exchange]) + + if len(setting)>=5: + req.currency = setting[3] + req.productClass = setting[4] + + self.mainEngine.subscribe(req, gateway) + + # 保存到配置字典中 + if vtSymbol not in self.settingDict: + d = { + 'symbol': symbol, + 'gateway': gateway, + 'bar': True + } + self.settingDict[vtSymbol] = d + else: + d = self.settingDict[vtSymbol] + d['bar'] = True + + # 创建BarManager对象 + self.bgDict[vtSymbol] = BarGenerator(self.onBar) + + # 主力合约记录配置 + if 'active' in drSetting: + d = drSetting['active'] + self.activeSymbolDict = {vtSymbol:activeSymbol for activeSymbol, vtSymbol in d.items()} + + #---------------------------------------------------------------------- + def getSetting(self): + """获取配置""" + return self.settingDict, self.activeSymbolDict + + #---------------------------------------------------------------------- + def procecssTickEvent(self, event): + """处理行情事件""" + tick = event.dict_['data'] + vtSymbol = tick.vtSymbol + + # 生成datetime对象 + if not tick.datetime: + tick.datetime = datetime.strptime(' '.join([tick.date, tick.time]), '%Y%m%d %H:%M:%S.%f') + + self.onTick(tick) + + bm = self.bgDict.get(vtSymbol, None) + if bm: + bm.updateTick(tick) + + #---------------------------------------------------------------------- + def onTick(self, tick): + """Tick更新""" + vtSymbol = tick.vtSymbol + + if vtSymbol in self.tickSymbolSet: + self.insertData(TICK_DB_NAME, vtSymbol, tick) + + if vtSymbol in self.activeSymbolDict: + activeSymbol = self.activeSymbolDict[vtSymbol] + self.insertData(TICK_DB_NAME, activeSymbol, tick) + + + self.writeDrLog(text.TICK_LOGGING_MESSAGE.format(symbol=tick.vtSymbol, + time=tick.time, + last=tick.lastPrice, + bid=tick.bidPrice1, + ask=tick.askPrice1)) + + #---------------------------------------------------------------------- + def onBar(self, bar): + """分钟线更新""" + vtSymbol = bar.vtSymbol + + self.insertData(MINUTE_DB_NAME, vtSymbol, bar) + + if vtSymbol in self.activeSymbolDict: + activeSymbol = self.activeSymbolDict[vtSymbol] + self.insertData(MINUTE_DB_NAME, activeSymbol, bar) + + self.writeDrLog(text.BAR_LOGGING_MESSAGE.format(symbol=bar.vtSymbol, + time=bar.time, + open=bar.open, + high=bar.high, + low=bar.low, + close=bar.close)) + + #---------------------------------------------------------------------- + def registerEvent(self): + """注册事件监听""" + self.eventEngine.register(EVENT_TICK, self.procecssTickEvent) + + #---------------------------------------------------------------------- + def insertData(self, dbName, collectionName, data): + """插入数据到数据库(这里的data可以是VtTickData或者VtBarData)""" + self.queue.put((dbName, collectionName, data.__dict__)) + + #---------------------------------------------------------------------- + def run(self): + """运行插入线程""" + while self.active: + try: + dbName, collectionName, d = self.queue.get(block=True, timeout=1) + + # 这里采用MongoDB的update模式更新数据,在记录tick数据时会由于查询 + # 过于频繁,导致CPU占用和硬盘读写过高后系统卡死,因此不建议使用 + #flt = {'datetime': d['datetime']} + #self.mainEngine.dbUpdate(dbName, collectionName, d, flt, True) + + # 使用insert模式更新数据,可能存在时间戳重复的情况,需要用户自行清洗 + try: + self.mainEngine.dbInsert(dbName, collectionName, d) + except DuplicateKeyError: + self.writeDrLog(u'键值重复插入失败,报错信息:' %traceback.format_exc()) + except Empty: + pass + + #---------------------------------------------------------------------- + def start(self): + """启动""" + self.active = True + self.thread.start() + + #---------------------------------------------------------------------- + def stop(self): + """退出""" + if self.active: + self.active = False + self.thread.join() + + #---------------------------------------------------------------------- + def writeDrLog(self, content): + """快速发出日志事件""" + log = VtLogData() + log.logContent = content + event = Event(type_=EVENT_DATARECORDER_LOG) + event.dict_['data'] = log + self.eventEngine.put(event) + \ No newline at end of file diff --git a/vnpy/trader/app/histDataCollector/language/__init__.py b/vnpy/trader/app/histDataCollector/language/__init__.py new file mode 100644 index 00000000..ecf72358 --- /dev/null +++ b/vnpy/trader/app/histDataCollector/language/__init__.py @@ -0,0 +1,13 @@ +# encoding: UTF-8 + +import json +import os +import traceback + +# 默认设置 +from chinese import text + +# 是否要使用英文 +from vnpy.trader.vtGlobal import globalSetting +if globalSetting['language'] == 'english': + from english import text \ No newline at end of file diff --git a/vnpy/trader/app/histDataCollector/language/chinese/__init__.py b/vnpy/trader/app/histDataCollector/language/chinese/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/vnpy/trader/app/histDataCollector/language/chinese/text.py b/vnpy/trader/app/histDataCollector/language/chinese/text.py new file mode 100644 index 00000000..fdb2179f --- /dev/null +++ b/vnpy/trader/app/histDataCollector/language/chinese/text.py @@ -0,0 +1,16 @@ +# encoding: UTF-8 + +DATA_RECORDER = u'行情记录' + +TICK_RECORD = u'Tick记录' +BAR_RECORD = u'Bar记录' +TICK_RECORD = u'Tick记录' + +CONTRACT_SYMBOL = u'合约代码' +GATEWAY = u'接口' + +DOMINANT_CONTRACT = u'主力合约' +DOMINANT_SYMBOL = u'主力代码' + +TICK_LOGGING_MESSAGE = u'记录Tick数据{symbol},时间:{time}, last:{last}, bid:{bid}, ask:{ask}' +BAR_LOGGING_MESSAGE = u'记录分钟线数据{symbol},时间:{time}, O:{open}, H:{high}, L:{low}, C:{close}' \ No newline at end of file diff --git a/vnpy/trader/app/histDataCollector/language/english/__init__.py b/vnpy/trader/app/histDataCollector/language/english/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/vnpy/trader/app/histDataCollector/language/english/text.py b/vnpy/trader/app/histDataCollector/language/english/text.py new file mode 100644 index 00000000..2230e6ca --- /dev/null +++ b/vnpy/trader/app/histDataCollector/language/english/text.py @@ -0,0 +1,15 @@ +# encoding: UTF-8 + +DATA_RECORDER = u'Data Recorder' + +TICK_RECORD = u'Tick Record' +BAR_RECORD = u'Bar Record' + +CONTRACT_SYMBOL = u'Contract Symbol' +GATEWAY = u'Gateway' + +DOMINANT_CONTRACT = u'Dominant Contract' +DOMINANT_SYMBOL = u'Dominant Symbol' + +TICK_LOGGING_MESSAGE = u'Record Tick Data {symbol}, Time:{time}, last:{last}, bid:{bid}, ask:{ask}' +BAR_LOGGING_MESSAGE = u'Record Bar Data {symbol}, Time:{time}, O:{open}, H:{high}, L:{low}, C:{close}' \ No newline at end of file From 91b3b8b1c58b0c59ffa9cf3391583d3cd94d180e Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Tue, 24 Apr 2018 00:43:08 -0400 Subject: [PATCH 13/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UML/dataRecord.puml | 47 ++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/UML/dataRecord.puml b/UML/dataRecord.puml index feb44325..b9b911ff 100644 --- a/UML/dataRecord.puml +++ b/UML/dataRecord.puml @@ -27,8 +27,8 @@ participant "IB Gateway/IB TWS" as ib activate rundr loop rundr->rundr: 检查是否处于交易时间段\n非交易时间段不起动子进程 - rundr->rundr: 若处于非交易时间段 && 有子进程存在,\n就终止子进程运行 - rundr->run ** : 若处于交易时间段 && 不存在子进程\ncreate process + rundr->rundr: 若处于非交易时间段\n并且有子进程存在,\n就终止子进程运行 + rundr->run ** : 若处于交易时间段\n并且不存在子进程,\ncreate process activate run rundr->rundr: sleep(5) end loop @@ -96,7 +96,12 @@ run->me ++ : addGateway(ibGateway) ** 获取连接IB G/W的信息 end note gw->wrap ** : Create IbWrapper(self) - note right: IbApi是基于Boost.python的封装。\n用C++实现,但是可以提供给Python程序使用。 + note right + IbApi是基于Boost.python的封装, + 用C++实现,但是可以提供给Python程序使用。 + IbApid的功能上面,主要提供了主动函数 + 和回调函数。 + end note activate wrap wrap->wrap ++ : 构造函数() return object @@ -112,11 +117,20 @@ run->me ++ : addApp() dr->drq **:Create Queue dr->drt **:Create Thread activate drt #blue - dr->dr:loadSetting() + dr->dr ++ : loadSetting() note right 从配置文件中加载 订阅设置到字典对象 end note + dr->me ++ : me.subscribe(req, gateway) + note left + 根据配置文件,订阅TICK数据和BAR数据。 + end note + me->gw ++ : 订阅市场行情\ngw.subscribe(req) + gw->gw : 如果网关没有连接,就先缓存req; + return + return + return dr->ee++:register(TICK, handler) note right: 登记EVENT_TICK事件 return @@ -139,30 +153,27 @@ run->ee: ee.regiser() 注册日志处理事件 run->me++: me.Connect(IB) note right: 连接IB网关 me->gw ++ : gw.connect() - gw-> wrap ++ : ibwrapper.eConnect(host, port, clientId, false) - wrap-\ib ++ : 调用IB的C++代码,发送连接请求数据包到IB网关 + gw-> wrap ++ : ibwrapper.eConnect(host, port, \nclientId, false) + wrap-\ib ++ : 调用IB的C++代码,\n发送连接请求数据包到IB网关 return return gw->wrap ++ : ibwrapper.reqCurrentTime() - wrap->ib ++: 调用IB的C++代码,发送服务器时间查询数据包到IB网关 + wrap->ib ++: 调用IB的C++代码,\n发送服务器时间查询数据包到IB网关 return return return - ib-/ wrap ++ : connectAck()\nIB网关发回响应数据包到IB的C++代码,该代码回调函数 + ib-/ wrap ++ : connectAck()\nIB网关发回响应数据包到IB的C++代码,\n该代码回调函数 return - ib->wrap ++ : currentTime()\nIB网关发回响应数据包到IB的C++代码,该代码回调函数 - wrap->gw ++ : 修改连接状态\ngateway.conntected=true - return - - wrap->gw ++ : 订阅市场行情\nsubscribe(subscribeReq) - gw->wrap ++ : 请求合约详细\nreqContractDetails(self.tickerId, contract) + ib->wrap ++ : currentTime()\nIB网关发回响应数据包到IB的C++代码,\n该代码回调函数 + wrap->gw ++ : 将缓存的req取出,进行实际订阅\nsubscribe(subscribeReq) + gw->wrap ++ : 请求合约详细\nreqContractDetails(tickerId, contract) return - gw->wrap ++ : 请求市场数据\nreqMktData(self.tickerId, contract, '', False, TagValueList()) + gw->wrap ++ : 请求市场数据\nreqMktData(tickerId, contract, '',\nFalse, TagValueList()) return ||| return @@ -219,14 +230,14 @@ eet->ee--: ee.run() loop ee->eeq ++ :queue.get() return event - ee->ee ++ : __process(event) + ee->ee ++ #red : __process(event) ee->dr ++ #red :call procecssTickEvent() - dr->dr ++ :OnTick() + dr->dr ++ #red :OnTick() dr->drq ++: queue.put(tick) return return - dr->dr ++ :OnBar() + dr->dr ++ #red :OnBar() dr->drq ++: queue.put(bar) return return From 737a72cc698278615ad6e03f87f50c87e24bb6f1 Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Tue, 24 Apr 2018 23:20:23 -0400 Subject: [PATCH 14/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/HistDataCollector/HD_setting.json | 15 --- .../HistDataCollector/runHistDataCollector.py | 105 ------------------ 2 files changed, 120 deletions(-) delete mode 100644 examples/HistDataCollector/HD_setting.json delete mode 100644 examples/HistDataCollector/runHistDataCollector.py diff --git a/examples/HistDataCollector/HD_setting.json b/examples/HistDataCollector/HD_setting.json deleted file mode 100644 index 3294e417..00000000 --- a/examples/HistDataCollector/HD_setting.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "working": true, - - "tick": - [ - ["700", "IB", "SEHK", "HKD", "股票"], - ["USD.JPY", "IB", "IDEALPRO", "JPY", "外汇"] - ], - - "bar": - [ - ["700", "IB", "SEHK", "HKD", "股票"], - ["USD.JPY", "IB", "IDEALPRO", "JPY", "外汇"] - ] -} \ No newline at end of file diff --git a/examples/HistDataCollector/runHistDataCollector.py b/examples/HistDataCollector/runHistDataCollector.py deleted file mode 100644 index 604e20a9..00000000 --- a/examples/HistDataCollector/runHistDataCollector.py +++ /dev/null @@ -1,105 +0,0 @@ -# encoding: UTF-8 - -import multiprocessing -from time import sleep -from datetime import datetime, time - -from vnpy.event import EventEngine2 -from vnpy.trader.vtEvent import EVENT_LOG, EVENT_ERROR -from vnpy.trader.vtEngine import MainEngine, LogEngine -from vnpy.trader.gateway import ibGateway -from vnpy.trader.app import dataRecorder - - -#---------------------------------------------------------------------- -def processErrorEvent(event): - """ - 处理错误事件 - 错误信息在每次登陆后,会将当日所有已产生的均推送一遍,所以不适合写入日志 - """ - error = event.dict_['data'] - print u'错误代码:%s,错误信息:%s' %(error.errorID, error.errorMsg) - -#---------------------------------------------------------------------- -def runChildProcess(): - """子进程运行函数""" - print '-'*20 - - # 创建日志引擎 - le = LogEngine() - le.setLogLevel(le.LEVEL_DEBUG) - le.addConsoleHandler() - le.info(u'启动行情记录运行子进程') - - ee = EventEngine2() - le.info(u'事件引擎创建成功') - - me = MainEngine(ee) - me.addGateway(ibGateway) - me.addApp(histDataCollector) - le.info(u'主引擎创建成功') - - ee.register(EVENT_LOG, le.processLogEvent) - ee.register(EVENT_ERROR, processErrorEvent) - le.info(u'注册日志事件监听') - - me.connect('IB') - le.info(u'连接IB接口') - - while True: - sleep(1) - -#---------------------------------------------------------------------- -def runParentProcess(): - """父进程运行函数""" - # 创建日志引擎 - le = LogEngine() - le.setLogLevel(le.LEVEL_INFO) - le.addConsoleHandler() - le.info(u'启动HistData守护父进程') - - DAY_START = time(8, 57) # 日盘启动和停止时间 - DAY_END = time(15, 18) - NIGHT_START = time(20, 57) # 夜盘启动和停止时间 - NIGHT_END = time(2, 33) - - p = None # 子进程句柄 - - while True: - currentTime = datetime.now().time() - recording = False - - # 判断当前处于的时间段 - if ((currentTime >= DAY_START and currentTime <= DAY_END) or - (currentTime >= NIGHT_START) or - (currentTime <= NIGHT_END)): - recording = True - - # 过滤周末时间段:周六全天,周五夜盘,周日日盘 - if ((datetime.today().weekday() == 6) or - (datetime.today().weekday() == 5 and currentTime > NIGHT_END) or - (datetime.today().weekday() == 0 and currentTime < DAY_START)): - recording = False - - recording = True - # 记录时间则需要启动子进程 - if recording and p is None: - le.info(u'启动子进程') - p = multiprocessing.Process(target=runChildProcess) - p.start() - le.info(u'子进程启动成功') - - # 非记录时间则退出子进程 - if not recording and p is not None: - le.info(u'关闭子进程') - p.terminate() - p.join() - p = None - le.info(u'子进程关闭成功') - - sleep(5) - - -if __name__ == '__main__': - #runChildProcess() - runParentProcess() From dbe58595f7edf70376b2077a7ebcf76e2129246e Mon Sep 17 00:00:00 2001 From: zhu4ling3 Date: Tue, 24 Apr 2018 23:23:21 -0400 Subject: [PATCH 15/15] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90dataR?= =?UTF-8?q?ecord=E7=9A=84=E5=85=A8=E8=BF=87=E7=A8=8B=E6=97=B6=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy/trader/app/histDataCollector/__init__.py | 8 - vnpy/trader/app/histDataCollector/hdcBase.py | 19 -- .../trader/app/histDataCollector/hdcEngine.py | 274 ------------------ .../histDataCollector/language/__init__.py | 13 - .../language/chinese/__init__.py | 0 .../language/chinese/text.py | 16 - .../language/english/__init__.py | 0 .../language/english/text.py | 15 - 8 files changed, 345 deletions(-) delete mode 100644 vnpy/trader/app/histDataCollector/__init__.py delete mode 100644 vnpy/trader/app/histDataCollector/hdcBase.py delete mode 100644 vnpy/trader/app/histDataCollector/hdcEngine.py delete mode 100644 vnpy/trader/app/histDataCollector/language/__init__.py delete mode 100644 vnpy/trader/app/histDataCollector/language/chinese/__init__.py delete mode 100644 vnpy/trader/app/histDataCollector/language/chinese/text.py delete mode 100644 vnpy/trader/app/histDataCollector/language/english/__init__.py delete mode 100644 vnpy/trader/app/histDataCollector/language/english/text.py diff --git a/vnpy/trader/app/histDataCollector/__init__.py b/vnpy/trader/app/histDataCollector/__init__.py deleted file mode 100644 index c177142d..00000000 --- a/vnpy/trader/app/histDataCollector/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# encoding: UTF-8 - -from hdcEngine import HdcEngine - - -appName = 'HistDataCollector' -appDisplayName = u'HistData记录' -appEngine = HdcEngine diff --git a/vnpy/trader/app/histDataCollector/hdcBase.py b/vnpy/trader/app/histDataCollector/hdcBase.py deleted file mode 100644 index c7249443..00000000 --- a/vnpy/trader/app/histDataCollector/hdcBase.py +++ /dev/null @@ -1,19 +0,0 @@ -# encoding: UTF-8 - -''' -本文件中包含的数据格式和CTA模块通用,用户有必要可以自行添加格式。 -''' - -from __future__ import division - -# 数据库名称 -SETTING_DB_NAME = 'VnTrader_Setting_Db' -TICK_DB_NAME = 'VnTrader_Tick_Db' -DAILY_DB_NAME = 'VnTrader_Daily_Db' -MINUTE_DB_NAME = 'VnTrader_1Min_Db' - -# 行情记录模块事件 -EVENT_DATARECORDER_LOG = 'eHistDataCollectorLog' # 行情记录日志更新事件 - -# CTA引擎中涉及的数据类定义 -from vnpy.trader.vtConstant import EMPTY_UNICODE, EMPTY_STRING, EMPTY_FLOAT, EMPTY_INT diff --git a/vnpy/trader/app/histDataCollector/hdcEngine.py b/vnpy/trader/app/histDataCollector/hdcEngine.py deleted file mode 100644 index 703059af..00000000 --- a/vnpy/trader/app/histDataCollector/hdcEngine.py +++ /dev/null @@ -1,274 +0,0 @@ -# encoding: UTF-8 - -''' -本文件中实现了行情数据记录引擎,用于汇总TICK数据,并生成K线插入数据库。 - -使用DR_setting.json来配置需要收集的合约,以及主力合约代码。 -''' - -import json -import csv -import os -import copy -import traceback -from collections import OrderedDict -from datetime import datetime, timedelta -from Queue import Queue, Empty -from threading import Thread -from pymongo.errors import DuplicateKeyError - -from vnpy.event import Event -from vnpy.trader.vtEvent import * -from vnpy.trader.vtFunction import todayDate, getJsonPath -from vnpy.trader.vtObject import VtSubscribeReq, VtLogData, VtBarData, VtTickData -from vnpy.trader.app.ctaStrategy.ctaTemplate import BarGenerator - -from .hdcBase import * -from .language import text - - -######################################################################## -class HdcEngine(object): - """数据记录引擎""" - - settingFileName = 'HD_setting.json' - settingFilePath = getJsonPath(settingFileName, __file__) - - #---------------------------------------------------------------------- - def __init__(self, mainEngine, eventEngine): - """Constructor""" - self.mainEngine = mainEngine - self.eventEngine = eventEngine - - # 当前日期 - self.today = todayDate() - - # 主力合约代码映射字典,key为具体的合约代码(如IF1604),value为主力合约代码(如IF0000) - self.activeSymbolDict = {} - - # Tick对象字典 - self.tickSymbolSet = set() - - # K线合成器字典 - self.bgDict = {} - - # 配置字典 - self.settingDict = OrderedDict() - - # 负责执行数据库插入的单独线程相关 - self.active = False # 工作状态 - self.queue = Queue() # 队列 - self.thread = Thread(target=self.run) # 线程 - - # 载入设置,订阅行情 - self.loadSetting() - - # 启动数据插入线程 - self.start() - - # 注册事件监听 - self.registerEvent() - - #---------------------------------------------------------------------- - def loadSetting(self): - """加载配置""" - with open(self.settingFilePath) as f: - drSetting = json.load(f) - - # 如果working设为False则不启动行情记录功能 - working = drSetting['working'] - if not working: - return - - # Tick记录配置 - if 'tick' in drSetting: - l = drSetting['tick'] - - for setting in l: - symbol = setting[0] - gateway = setting[1] - vtSymbol = symbol - - req = VtSubscribeReq() - req.symbol = setting[0] - - # 针对LTS和IB接口,订阅行情需要交易所代码 - if len(setting)>=3: - req.exchange = setting[2] - vtSymbol = '.'.join([symbol, req.exchange]) - - # 针对IB接口,订阅行情需要货币和产品类型 - if len(setting)>=5: - req.currency = setting[3] - req.productClass = setting[4] - - self.mainEngine.subscribe(req, gateway) - - #tick = VtTickData() # 该tick实例可以用于缓存部分数据(目前未使用) - #self.tickDict[vtSymbol] = tick - self.tickSymbolSet.add(vtSymbol) - - # 保存到配置字典中 - if vtSymbol not in self.settingDict: - d = { - 'symbol': symbol, - 'gateway': gateway, - 'tick': True - } - self.settingDict[vtSymbol] = d - else: - d = self.settingDict[vtSymbol] - d['tick'] = True - - # 分钟线记录配置 - if 'bar' in drSetting: - l = drSetting['bar'] - - for setting in l: - symbol = setting[0] - gateway = setting[1] - vtSymbol = symbol - - req = VtSubscribeReq() - req.symbol = symbol - - if len(setting)>=3: - req.exchange = setting[2] - vtSymbol = '.'.join([symbol, req.exchange]) - - if len(setting)>=5: - req.currency = setting[3] - req.productClass = setting[4] - - self.mainEngine.subscribe(req, gateway) - - # 保存到配置字典中 - if vtSymbol not in self.settingDict: - d = { - 'symbol': symbol, - 'gateway': gateway, - 'bar': True - } - self.settingDict[vtSymbol] = d - else: - d = self.settingDict[vtSymbol] - d['bar'] = True - - # 创建BarManager对象 - self.bgDict[vtSymbol] = BarGenerator(self.onBar) - - # 主力合约记录配置 - if 'active' in drSetting: - d = drSetting['active'] - self.activeSymbolDict = {vtSymbol:activeSymbol for activeSymbol, vtSymbol in d.items()} - - #---------------------------------------------------------------------- - def getSetting(self): - """获取配置""" - return self.settingDict, self.activeSymbolDict - - #---------------------------------------------------------------------- - def procecssTickEvent(self, event): - """处理行情事件""" - tick = event.dict_['data'] - vtSymbol = tick.vtSymbol - - # 生成datetime对象 - if not tick.datetime: - tick.datetime = datetime.strptime(' '.join([tick.date, tick.time]), '%Y%m%d %H:%M:%S.%f') - - self.onTick(tick) - - bm = self.bgDict.get(vtSymbol, None) - if bm: - bm.updateTick(tick) - - #---------------------------------------------------------------------- - def onTick(self, tick): - """Tick更新""" - vtSymbol = tick.vtSymbol - - if vtSymbol in self.tickSymbolSet: - self.insertData(TICK_DB_NAME, vtSymbol, tick) - - if vtSymbol in self.activeSymbolDict: - activeSymbol = self.activeSymbolDict[vtSymbol] - self.insertData(TICK_DB_NAME, activeSymbol, tick) - - - self.writeDrLog(text.TICK_LOGGING_MESSAGE.format(symbol=tick.vtSymbol, - time=tick.time, - last=tick.lastPrice, - bid=tick.bidPrice1, - ask=tick.askPrice1)) - - #---------------------------------------------------------------------- - def onBar(self, bar): - """分钟线更新""" - vtSymbol = bar.vtSymbol - - self.insertData(MINUTE_DB_NAME, vtSymbol, bar) - - if vtSymbol in self.activeSymbolDict: - activeSymbol = self.activeSymbolDict[vtSymbol] - self.insertData(MINUTE_DB_NAME, activeSymbol, bar) - - self.writeDrLog(text.BAR_LOGGING_MESSAGE.format(symbol=bar.vtSymbol, - time=bar.time, - open=bar.open, - high=bar.high, - low=bar.low, - close=bar.close)) - - #---------------------------------------------------------------------- - def registerEvent(self): - """注册事件监听""" - self.eventEngine.register(EVENT_TICK, self.procecssTickEvent) - - #---------------------------------------------------------------------- - def insertData(self, dbName, collectionName, data): - """插入数据到数据库(这里的data可以是VtTickData或者VtBarData)""" - self.queue.put((dbName, collectionName, data.__dict__)) - - #---------------------------------------------------------------------- - def run(self): - """运行插入线程""" - while self.active: - try: - dbName, collectionName, d = self.queue.get(block=True, timeout=1) - - # 这里采用MongoDB的update模式更新数据,在记录tick数据时会由于查询 - # 过于频繁,导致CPU占用和硬盘读写过高后系统卡死,因此不建议使用 - #flt = {'datetime': d['datetime']} - #self.mainEngine.dbUpdate(dbName, collectionName, d, flt, True) - - # 使用insert模式更新数据,可能存在时间戳重复的情况,需要用户自行清洗 - try: - self.mainEngine.dbInsert(dbName, collectionName, d) - except DuplicateKeyError: - self.writeDrLog(u'键值重复插入失败,报错信息:' %traceback.format_exc()) - except Empty: - pass - - #---------------------------------------------------------------------- - def start(self): - """启动""" - self.active = True - self.thread.start() - - #---------------------------------------------------------------------- - def stop(self): - """退出""" - if self.active: - self.active = False - self.thread.join() - - #---------------------------------------------------------------------- - def writeDrLog(self, content): - """快速发出日志事件""" - log = VtLogData() - log.logContent = content - event = Event(type_=EVENT_DATARECORDER_LOG) - event.dict_['data'] = log - self.eventEngine.put(event) - \ No newline at end of file diff --git a/vnpy/trader/app/histDataCollector/language/__init__.py b/vnpy/trader/app/histDataCollector/language/__init__.py deleted file mode 100644 index ecf72358..00000000 --- a/vnpy/trader/app/histDataCollector/language/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# encoding: UTF-8 - -import json -import os -import traceback - -# 默认设置 -from chinese import text - -# 是否要使用英文 -from vnpy.trader.vtGlobal import globalSetting -if globalSetting['language'] == 'english': - from english import text \ No newline at end of file diff --git a/vnpy/trader/app/histDataCollector/language/chinese/__init__.py b/vnpy/trader/app/histDataCollector/language/chinese/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/vnpy/trader/app/histDataCollector/language/chinese/text.py b/vnpy/trader/app/histDataCollector/language/chinese/text.py deleted file mode 100644 index fdb2179f..00000000 --- a/vnpy/trader/app/histDataCollector/language/chinese/text.py +++ /dev/null @@ -1,16 +0,0 @@ -# encoding: UTF-8 - -DATA_RECORDER = u'行情记录' - -TICK_RECORD = u'Tick记录' -BAR_RECORD = u'Bar记录' -TICK_RECORD = u'Tick记录' - -CONTRACT_SYMBOL = u'合约代码' -GATEWAY = u'接口' - -DOMINANT_CONTRACT = u'主力合约' -DOMINANT_SYMBOL = u'主力代码' - -TICK_LOGGING_MESSAGE = u'记录Tick数据{symbol},时间:{time}, last:{last}, bid:{bid}, ask:{ask}' -BAR_LOGGING_MESSAGE = u'记录分钟线数据{symbol},时间:{time}, O:{open}, H:{high}, L:{low}, C:{close}' \ No newline at end of file diff --git a/vnpy/trader/app/histDataCollector/language/english/__init__.py b/vnpy/trader/app/histDataCollector/language/english/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/vnpy/trader/app/histDataCollector/language/english/text.py b/vnpy/trader/app/histDataCollector/language/english/text.py deleted file mode 100644 index 2230e6ca..00000000 --- a/vnpy/trader/app/histDataCollector/language/english/text.py +++ /dev/null @@ -1,15 +0,0 @@ -# encoding: UTF-8 - -DATA_RECORDER = u'Data Recorder' - -TICK_RECORD = u'Tick Record' -BAR_RECORD = u'Bar Record' - -CONTRACT_SYMBOL = u'Contract Symbol' -GATEWAY = u'Gateway' - -DOMINANT_CONTRACT = u'Dominant Contract' -DOMINANT_SYMBOL = u'Dominant Symbol' - -TICK_LOGGING_MESSAGE = u'Record Tick Data {symbol}, Time:{time}, last:{last}, bid:{bid}, ask:{ask}' -BAR_LOGGING_MESSAGE = u'Record Bar Data {symbol}, Time:{time}, O:{open}, H:{high}, L:{low}, C:{close}' \ No newline at end of file