[增强] 策略切片=》同步=》mongodb

This commit is contained in:
msincenselee 2020-04-16 15:01:00 +08:00
parent 59acdfdf08
commit d5599bc530
13 changed files with 283 additions and 93 deletions

View File

@ -8,6 +8,7 @@
6. 监听股票接口的 EVENT_HISTORY_ORDER 事件, 数据 => history_trades 6. 监听股票接口的 EVENT_HISTORY_ORDER 事件, 数据 => history_trades
7. 监听股票接口的 EVENT_FUNDS_FLOW 事件, 数据 => funds_flow 7. 监听股票接口的 EVENT_FUNDS_FLOW 事件, 数据 => funds_flow
8. 监听 EVENT_STRATEGY_POS事件数据 =》 mongodb Account.today_strategy_pos 8. 监听 EVENT_STRATEGY_POS事件数据 =》 mongodb Account.today_strategy_pos
9. 监听 EVENT_STRATEGY_SNAPSHOT事件 数据=》 mongodb Account.strategy_snapshot
配置文件 ar_setting.json 配置文件 ar_setting.json

View File

@ -22,6 +22,7 @@ from datetime import datetime, timedelta
from queue import Queue from queue import Queue
from threading import Thread from threading import Thread
from time import time from time import time
from bson import binary
from vnpy.event import Event, EventEngine from vnpy.event import Event, EventEngine
from vnpy.trader.event import ( from vnpy.trader.event import (
@ -34,6 +35,7 @@ from vnpy.trader.event import (
EVENT_HISTORY_ORDER, EVENT_HISTORY_ORDER,
EVENT_FUNDS_FLOW, EVENT_FUNDS_FLOW,
EVENT_STRATEGY_POS, EVENT_STRATEGY_POS,
EVENT_STRATEGY_SNAPSHOT,
EVENT_ERROR, EVENT_ERROR,
EVENT_WARNING, EVENT_WARNING,
EVENT_CRITICAL, EVENT_CRITICAL,
@ -55,13 +57,14 @@ HISTORY_ORDER_COL = 'history_orders'
HISTORY_TRADE_COL = 'history_trades' HISTORY_TRADE_COL = 'history_trades'
HISTORY_STRATEGY_POS_COL = 'history_strategy_pos' HISTORY_STRATEGY_POS_COL = 'history_strategy_pos'
FUNDS_FLOW_COL = 'funds_flow' FUNDS_FLOW_COL = 'funds_flow'
STRATEGY_SNAPSHOT = 'strategy_snapshot'
ALERT_DB_NAME = "Alert" ALERT_DB_NAME = "Alert"
GW_ERROR_COL_NAME = "gw_error_msg" GW_ERROR_COL_NAME = "gw_error_msg"
WARNING_COL_NAME = "warning_msg" WARNING_COL_NAME = "warning_msg"
CRITICAL_COL_NAME = "critical_msg" CRITICAL_COL_NAME = "critical_msg"
APP_NAME = "ACCOUNT_RECORDER" APP_NAME = "AccountRecorder"
######################################################################## ########################################################################
@ -129,11 +132,12 @@ class AccountRecorder(BaseEngine):
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def load_setting(self): def load_setting(self):
"""读取配置""" """读取配置"""
self.write_log(f'{self.name}读取配置')
try: try:
d = load_json(self.setting_file_name) d = load_json(self.setting_file_name)
# mongo 数据库连接 # mongo 数据库连接
mongo_seetting = d.get('mongo', {}) mongo_seetting = d.get('mongo_db', {})
self.mongo_db = MongoData(host=mongo_seetting.get('host', 'localhost'), self.mongo_db = MongoData(host=mongo_seetting.get('host', 'localhost'),
port=mongo_seetting.get('port', 27017)) port=mongo_seetting.get('port', 27017))
@ -151,6 +155,7 @@ class AccountRecorder(BaseEngine):
if account_setting.get('copy_history_strategypos', False): if account_setting.get('copy_history_strategypos', False):
self.copy_history_strategypos.append(gateway_name) self.copy_history_strategypos.append(gateway_name)
self.write_log(f'{self.name}读取配置完成')
except Exception as ex: except Exception as ex:
self.main_engine.writeCritical(u'读取:{}异常:{}'.format(self.setting_file_name, str(ex))) self.main_engine.writeCritical(u'读取:{}异常:{}'.format(self.setting_file_name, str(ex)))
@ -175,6 +180,7 @@ class AccountRecorder(BaseEngine):
self.event_engine.register(EVENT_ERROR, self.process_gw_error) self.event_engine.register(EVENT_ERROR, self.process_gw_error)
self.event_engine.register(EVENT_WARNING, self.process_warning) self.event_engine.register(EVENT_WARNING, self.process_warning)
self.event_engine.register(EVENT_CRITICAL, self.process_critical) self.event_engine.register(EVENT_CRITICAL, self.process_critical)
self.event_engine.register(EVENT_STRATEGY_SNAPSHOT, self.update_strategy_snapshot)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def update_timer(self, event: Event): def update_timer(self, event: Event):
@ -214,7 +220,7 @@ class AccountRecorder(BaseEngine):
def update_account(self, event: Event): def update_account(self, event: Event):
"""更新账号资金""" """更新账号资金"""
account = event.data account = event.data
fld = {'accountid': account.accountid, fld = {'account_id': account.accountid,
'gateway_name': account.gateway_name, 'gateway_name': account.gateway_name,
'trading_day': account.trading_day, 'trading_day': account.trading_day,
'currency': account.currency} 'currency': account.currency}
@ -224,14 +230,15 @@ class AccountRecorder(BaseEngine):
self.gw_name_acct_id.update({account.gateway_name: account.accountid}) self.gw_name_acct_id.update({account.gateway_name: account.accountid})
data = account.__dict__ acc_data = copy.copy(account.__dict__)
acc_data.update({'account_id': acc_data.pop('accountid')})
# 更新至历史净值数据表 # 更新至历史净值数据表
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=DAILY_INFO_COL, fld=copy.copy(fld), self.update_data(db_name=ACCOUNT_DB_NAME, col_name=DAILY_INFO_COL, fld=copy.copy(fld),
data=copy.copy(data)) data=acc_data)
fld.pop('trading_day', None) fld.pop('trading_day', None)
# 更新至最新净值数据 # 更新至最新净值数据
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=ACCOUNT_INFO_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=ACCOUNT_INFO_COL, fld=fld, data=copy.copy(acc_data))
self.remove_pre_trading_day_data(account.accountid, account.trading_day) self.remove_pre_trading_day_data(account.accountid, account.trading_day)
@ -274,7 +281,7 @@ class AccountRecorder(BaseEngine):
return begin_day return begin_day
def remove_pre_trading_day_data(self, accountid: str, trading_day: str): def remove_pre_trading_day_data(self, account_id: str, trading_day: str):
""" """
移除非当前交易日得所有当日交易数据 移除非当前交易日得所有当日交易数据
:param accountid: :param accountid:
@ -285,20 +292,35 @@ class AccountRecorder(BaseEngine):
return return
# 移除非当日得交易/持仓 # 移除非当日得交易/持仓
flt = {'accountid': accountid, flt = {'account_id': account_id,
'trade_date': {'$ne': trading_day}} 'trade_date': {'$ne': trading_day}}
self.main_engine.dbDelete(ACCOUNT_DB_NAME, TODAY_TRADE_COL, flt) self.write_log(f'移除非当日交易持仓:{flt}')
self.main_engine.dbDelete(ACCOUNT_DB_NAME, TODAY_POSITION_COL, flt) self.mongo_db.db_delete(
db_name=ACCOUNT_DB_NAME,
col_name=TODAY_TRADE_COL,
flt=flt)
self.mongo_db.db_delete(
db_name=ACCOUNT_DB_NAME,
col_name=TODAY_POSITION_COL,
flt=flt)
# 移除非当日得委托 # 移除非当日得委托
flt = {'accountid': accountid, flt = {'account_id': account_id,
'order_date': {'$ne': trading_day}} 'order_date': {'$ne': trading_day}}
self.main_engine.dbDelete(ACCOUNT_DB_NAME, TODAY_ORDER_COL, flt) self.write_log(f'移除非当日委托:{flt}')
self.mongo_db.db_delete(
db_name=ACCOUNT_DB_NAME,
col_name=TODAY_ORDER_COL,
flt=flt)
# 移除非当日得持仓 # 移除非当日得持仓
flt = {'account_id': accountid, flt = {'account_id': account_id,
'trading_day': {'$ne': trading_day}} 'trading_day': {'$ne': trading_day}}
self.main_engine.dbDelete(ACCOUNT_DB_NAME, TODAY_STRATEGY_POS_COL, flt) self.write_log(f'移除非当日持仓:{flt}')
self.mongo_db.db_delete(
db_name=ACCOUNT_DB_NAME,
col_name=TODAY_STRATEGY_POS_COL,
flt=flt)
self.is_remove_pre_data = True self.is_remove_pre_data = True
@ -306,39 +328,46 @@ class AccountRecorder(BaseEngine):
"""更新当日记录""" """更新当日记录"""
order = event.data order = event.data
self.write_log(u'记录委托日志:{}'.format(order.__dict__)) self.write_log(u'记录委托日志:{}'.format(order.__dict__))
if len(order.sysOrderID) == 0: if len(order.sys_orderid) == 0:
# 未有系统的委托编号,不做持久化 # 未有系统的委托编号,不做持久化
return return
dt = getattr(order, 'datetime')
order_date = get_trading_date(datetime.now()) if not dt:
order_date = datetime.now().strftime('%Y-%m-%d')
else:
order_date = dt.strftime('%Y-%m-%d')
# 数据库需要提前建立多重索引 # 数据库需要提前建立多重索引
# db.today_orders.createIndex({'accountid':1,'vt_symbol':1,'sys_orderid':1,'order_date':1,'holder_id':1},{'name':'accountid_vtsymbol_sysorderid_order_date_holder_id','unique':true}) # db.today_orders.createIndex({'account_id':1,'vt_symbol':1,'sys_orderid':1,'order_date':1,'holder_id':1},{'name':'accountid_vtsymbol_sysorderid_order_date_holder_id','unique':true})
# db.today_orders.createIndex({'accountID':1})
fld = {'vt_symbol': order.vt_symbol, fld = {'vt_symbol': order.vt_symbol,
'accountid': order.accountid, 'account_id': order.accountid,
'sys_orderid': order.sys_orderid, 'sys_orderid': order.sys_orderid,
'order_date': order_date, 'order_date': order_date,
'holder_id': order.holder_id} 'holder_id': getattr(order,'holder_id','')}
data = copy.copy(order.__dict__) data = copy.copy(order.__dict__)
data.update({'account_id': data.pop('accountid')})
data.update({'order_date': order_date}) data.update({'order_date': order_date})
data.update({'exchange': order.exchange.value}) data.update({'exchange': order.exchange.value})
data.update({'direction': order.direction.value}) data.update({'direction': order.direction.value})
data.update({'offset': order.offset.value})
data.update({'type': order.type.value})
data.update({'status': order.status.value})
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_ORDER_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_ORDER_COL, fld=fld, data=data)
# 数据库需要提前建立多重索引 # 数据库需要提前建立多重索引
# db.history_orders.createIndex({'accountid':1,'vt_symbol':1,'sys_orderid':1,'order_date':1,'holder_id':1},{'name':'history_accountid_vtsymbol_sysorderid_order_date_holder_id'}) # db.history_orders.createIndex({'account_id':1,'vt_symbol':1,'sys_orderid':1,'order_date':1,'holder_id':1},{'name':'history_accountid_vtsymbol_sysorderid_order_date_holder_id'})
# db.history_orders.createIndex({'accountid':1})
# 复制委托记录=》历史委托记录 # 复制委托记录=》历史委托记录
if order.gatewayName in self.copy_history_orders: if order.gateway_name in self.copy_history_orders:
history_data = copy.copy(data) history_data = copy.copy(data)
fld2 = {'vt_symbol': order.vt_symbol, fld2 = {'vt_symbol': order.vt_symbol,
'accountid': order.accountid, 'account_id': order.accountid,
'sys_orderid': order.sys_orderid, 'sys_orderid': order.sys_orderid,
'order_date': order_date, 'order_date': order_date,
'holder_id': order.holder_id} 'holder_id': getattr(order,'holder_id','')}
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=HISTORY_ORDER_COL, fld=fld2, data=history_data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=HISTORY_ORDER_COL, fld=fld2, data=history_data)
@ -348,28 +377,30 @@ class AccountRecorder(BaseEngine):
trade_date = get_trading_date(datetime.now()) trade_date = get_trading_date(datetime.now())
fld = {'vt_symbol': trade.vt_symbol, fld = {'vt_symbol': trade.vt_symbol,
'accountid': trade.accountid, 'account_id': trade.accountid,
'vt_tradeid': trade.vt_tradeid, 'vt_tradeid': trade.vt_tradeid,
'trade_date': trade_date, 'trade_date': trade_date,
'holder_id': trade.holder_id} 'holder_id': trade.holder_id}
# 提前创建索引 # 提前创建索引
# db.today_trades.createIndex({'accountid':1,'vt_symbol':1,'vt_tradeid':1,'trade_date':1,'holder_id':1},{'name':'accountID_vtSymbol_vtTradeID_trade_date_holder_id','unique':true}) # db.today_trades.createIndex({'account_id':1,'vt_symbol':1,'vt_tradeid':1,'trade_date':1,'holder_id':1},{'name':'accountid_vtSymbol_vt_tradeid_trade_date_holder_id','unique':true})
# db.today_trades.createIndex({'accountid':1})
data = copy.copy(trade.__dict__) data = copy.copy(trade.__dict__)
data.update({'account_id': data.pop('accountid')})
data.update({'trade_date': trade_date}) data.update({'trade_date': trade_date})
data.update({'exchange': trade.exchange.value}) data.update({'exchange': trade.exchange.value})
data.update({'direction': trade.direction.value}) data.update({'direction': trade.direction.value})
data.update({'offset': trade.offset.value})
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_TRADE_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_TRADE_COL, fld=fld, data=data)
# db.history_trades.createIndex({'accountid':1,'vt_symbol':1,'vt_tradeid':1,'trade_date':1,'holder_id':1},{'name':'accountID_vtSymbol_vtTradeID_trade_date_holder_id'}) # db.history_trades.createIndex({'account_id':1,'vt_symbol':1,'vt_tradeid':1,'trade_date':1,'holder_id':1},{'name':'accountid_vtSymbol_vt_tradeid_trade_date_holder_id'})
# db.history_trades.createIndex({'accountid':1})
# 复制成交记录=》历史成交记录 # 复制成交记录=》历史成交记录
if trade.gateway_name in self.copy_history_trades: if trade.gateway_name in self.copy_history_trades:
history_trade = copy.copy(data) history_trade = copy.copy(data)
fld2 = {'vt_symbol': trade.vt_symbol, fld2 = {'vt_symbol': trade.vt_symbol,
'accountid': trade.accountid, 'account_id': trade.accountid,
'vt_tradeid': trade.vt_tradeid, 'vt_tradeid': trade.vt_tradeid,
'trade_date': trade_date, 'trade_date': trade_date,
'holder_id': trade.holder_id} 'holder_id': trade.holder_id}
@ -387,90 +418,106 @@ class AccountRecorder(BaseEngine):
fld = {'vt_symbol': pos.vt_symbol, fld = {'vt_symbol': pos.vt_symbol,
'direction': pos.direction.value, 'direction': pos.direction.value,
'accountid': pos.accountid, 'account_id': pos.accountid,
'trade_date': trade_date, 'trade_date': trade_date,
'holder_id': pos.holder_id} 'holder_id': pos.holder_id}
# db.today_positions.createIndex({'accountid':1,'vt_symbol':1,'direction':1,'trade_date':1,'holder_id':1},{'name':'accountID_vtSymbol_direction_trade_date_holder_id'}) # db.today_positions.createIndex({'account_id':1,'vt_symbol':1,'direction':1,'trade_date':1,'holder_id':1},{'name':'accountid_vtsymbol_direction_trade_date_holder_id'})
# db.today_positions.createIndex({'accountid':1})
data = pos.__dict__ data = copy.copy(pos.__dict__)
data.update({'account_id': data.pop('accountid')})
data.update({'trade_date': trade_date}) data.update({'trade_date': trade_date})
data.update({'exchange': pos.exchange.value}) data.update({'exchange': pos.exchange.value})
data.update({'direction': pos.direction.value}) data.update({'direction': pos.direction.value})
# 补充 当前价格 # 补充 当前价格
try: if pos.cur_price == 0:
price = self.main_engine.get_price(pos.vt_symbol) price = self.main_engine.get_price(pos.vt_symbol)
if price: if price:
data.update({'cur_price': price}) data.update({'cur_price': price})
except: # noqa
pass
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_POSITION_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_POSITION_COL, fld=fld, data=data)
def update_strategy_snapshot(self, event: Event):
"""更新策略切片"""
snapshot = event.data
self.write_log(f"保存切片,{snapshot.get('account_id')},策略:{snapshot.get('strategy')}")
klines = snapshot.pop('klines', None)
if klines:
self.write_log(f"转换 =>BSON.binary.Binary")
snapshot.update({'klines': binary.Binary(klines)})
fld = {
'account_id': snapshot.get('account_id'),
'strategy': snapshot.get('strategy'),
'guid': snapshot.get('guid')
}
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=STRATEGY_SNAPSHOT, fld=fld, data=snapshot)
def update_history_trade(self, event: Event): def update_history_trade(self, event: Event):
"""更新历史查询记录""" """更新历史查询记录"""
trade = event.data trade = event.data
trade_date = trade.time.split(' ')[0] trade_date = trade.time.split(' ')[0]
fld = {'vt_symbol': trade.vt_symbol, fld = {'vt_symbol': trade.vt_symbol,
'accountid': trade.accountid, 'account_id': trade.accountid,
'vt_tradeID': trade.vt_tradeid, 'vt_tradeid': trade.vt_tradeid,
'trade_date': trade_date, 'trade_date': trade_date,
'holder_id': trade.holder_id} 'holder_id': trade.holder_id}
data = trade.__dict__ data = copy.copy(trade.__dict__)
data.update({'account_id': data.pop('accountid')})
data.update({'trade_date': trade_date}) data.update({'trade_date': trade_date})
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=HISTORY_TRADE_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=HISTORY_TRADE_COL, fld=fld, data=data)
self.update_begin_day(trade.gatewayName, HISTORY_TRADE_COL, trade_date) self.update_begin_day(trade.gateway_name, HISTORY_TRADE_COL, trade_date)
def update_history_order(self, event: Event): def update_history_order(self, event: Event):
"""更新历史委托""" """更新历史委托"""
order = event.data order = event.data
order_date = order.time.split(' ')[0] order_date = order.time.split(' ')[0]
fld = {'vt_symbol': order.vt_symbol, fld = {'vt_symbol': order.vt_symbol,
'accountid': order.accountid, 'account_id': order.accountid,
'sys_orderid': order.sys_orderid, 'sys_orderid': order.sys_orderid,
'order_date': order_date, 'order_date': order_date,
'holder_id': order.holder_id} 'holder_id': order.holder_id}
data = order.__dict__ data = copy.copy(order.__dict__)
data.update({'account_id': data.pop('accountid')})
data.update({'order_date': order_date}) data.update({'order_date': order_date})
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=HISTORY_ORDER_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=HISTORY_ORDER_COL, fld=fld, data=data)
self.update_begin_day(order.gatewayName, HISTORY_ORDER_COL, order_date) self.update_begin_day(order.gateway_name, HISTORY_ORDER_COL, order_date)
def update_funds_flow(self, event: Event): def update_funds_flow(self, event: Event):
"""更新历史资金流水""" """更新历史资金流水"""
funds_flow = event.data funds_flow = event.data
data = funds_flow.__dict__ data = copy.copy(funds_flow.__dict__)
fld = {'accountid': funds_flow.accountid, fld = {'account_id': funds_flow.accountid,
'trade_date': funds_flow.trade_date, 'trade_date': funds_flow.trade_date,
'trade_amount': funds_flow.trade_amount, 'trade_amount': funds_flow.trade_amount,
'fund_remain': funds_flow.fund_remain, 'fund_remain': funds_flow.fund_remain,
'contract_id': funds_flow.contract_id, 'contract_id': funds_flow.contract_id,
'holder_id': funds_flow.holder_id} 'holder_id': funds_flow.holder_id}
data.update({'account_id': data.pop('accountid')})
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=FUNDS_FLOW_COL, fld=fld, data=data) self.update_data(db_name=ACCOUNT_DB_NAME, col_name=FUNDS_FLOW_COL, fld=fld, data=data)
self.update_begin_day(funds_flow.gatewayName, HISTORY_ORDER_COL, funds_flow.trade_date) self.update_begin_day(funds_flow.gateway_name, HISTORY_ORDER_COL, funds_flow.trade_date)
def update_strategy_pos(self, event: Event): def update_strategy_pos(self, event: Event):
"""更新策略持仓事件"""
data = event.data data = event.data
dt = data.get('datetime') dt = data.get('datetime')
pos_trading_day = get_trading_date(dt)
data.update({'trading_day': pos_trading_day})
accountid = data.get('accountid')
fld = {
'accountid': accountid,
'stratregy_group': data.get('straregy_group', '-'),
'strategy_name': data.get('strategy_name'),
'datetime': dt.strftime("%Y-%m-%d %H:%M:%S"),
'inited': True,
'trading': True
}
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_STRATEGY_POS_COL, fld=fld, data=data) account_id = data.get('accountid')
fld = {
'account_id': account_id,
'strategy_group': data.get('strategy_group', '-'),
'strategy_name': data.get('strategy_name')
}
pos_data = copy.copy(data)
pos_data.update({'account_id': pos_data.get('accountid')})
pos_data.update({'datetime': dt.strftime("%Y-%m-%d %H:%M:%S")})
self.update_data(db_name=ACCOUNT_DB_NAME, col_name=TODAY_STRATEGY_POS_COL, fld=fld, data=pos_data)
def process_gw_error(self, event: Event): def process_gw_error(self, event: Event):
""" 处理gw的回报错误日志""" """ 处理gw的回报错误日志"""
@ -512,7 +559,7 @@ class AccountRecorder(BaseEngine):
d.update({'log_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S")}) d.update({'log_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S")})
d.update({'trading_day': get_trading_date()}) d.update({'trading_day': get_trading_date()})
account_id = self.gw_name_acct_id.get(data.gatewayName, None) account_id = self.gw_name_acct_id.get(data.gateway_name, None)
if account_id: if account_id:
d.update({'account_id': account_id}) d.update({'account_id': account_id})
fld = copy.copy(d) fld = copy.copy(d)
@ -579,10 +626,12 @@ class AccountRecorder(BaseEngine):
"""启动""" """启动"""
self.active = True self.active = True
self.thread.start() self.thread.start()
self.write_log(f'账号记录引擎启动')
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def stop(self): def stop(self):
"""退出""" """退出"""
self.write_log(f'账号记录引擎退出')
if self.mongo_db: if self.mongo_db:
self.mongo_db = None self.mongo_db = None

View File

@ -19,6 +19,7 @@ from collections import OrderedDict
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from copy import copy from copy import copy
from functools import lru_cache from functools import lru_cache
from uuid import uuid1
from vnpy.event import Event, EventEngine from vnpy.event import Event, EventEngine
from vnpy.trader.engine import BaseEngine, MainEngine from vnpy.trader.engine import BaseEngine, MainEngine
@ -40,6 +41,7 @@ from vnpy.trader.event import (
EVENT_TRADE, EVENT_TRADE,
EVENT_POSITION, EVENT_POSITION,
EVENT_STRATEGY_POS, EVENT_STRATEGY_POS,
EVENT_STRATEGY_SNAPSHOT
) )
from vnpy.trader.constant import ( from vnpy.trader.constant import (
Direction, Direction,
@ -1250,6 +1252,15 @@ class CtaEngine(BaseEngine):
pickle.dump(snapshot, f) pickle.dump(snapshot, f)
self.write_log(u'切片保存成功:{}'.format(str(snapshot_file))) self.write_log(u'切片保存成功:{}'.format(str(snapshot_file)))
# 通过事件方式传导到account_recorder
snapshot.update({
'account_id': self.engine_config.get('accountid', '-'),
'strategy_group': self.engine_config.get('strategy_group', self.engine_name),
'guid': str(uuid1())
})
event = Event(EVENT_STRATEGY_SNAPSHOT, snapshot)
self.event_engine.put(event)
except Exception as ex: except Exception as ex:
self.write_error(u'获取策略{}切片数据异常:'.format(strategy_name, str(ex))) self.write_error(u'获取策略{}切片数据异常:'.format(strategy_name, str(ex)))
self.write_error(traceback.format_exc()) self.write_error(traceback.format_exc())
@ -1419,11 +1430,10 @@ class CtaEngine(BaseEngine):
for strategy_name in list(self.strategies.keys()): for strategy_name in list(self.strategies.keys()):
d = OrderedDict() d = OrderedDict()
d['accountid'] = self.engine_config.get('accountid', '-') d['accountid'] = self.engine_config.get('accountid', '-')
d['strategy_group'] = self.engine_config.get('strategy_group', '-') d['strategy_group'] = self.engine_config.get('strategy_group', self.engine_name)
d['strategy_name'] = strategy_name d['strategy_name'] = strategy_name
dt = datetime.now() dt = datetime.now()
d['date'] = dt.strftime('%Y%m%d') d['trading_day'] = dt.strftime('%Y-%m-%d')
d['hour'] = dt.hour
d['datetime'] = datetime.now() d['datetime'] = datetime.now()
strategy = self.strategies.get(strategy_name) strategy = self.strategies.get(strategy_name)
d['inited'] = strategy.inited d['inited'] = strategy.inited

View File

@ -815,6 +815,7 @@ class CtaFutureTemplate(CtaTemplate):
# 开仓完毕( buy, short) # 开仓完毕( buy, short)
else: else:
grid.open_status = True grid.open_status = True
grid.open_time = self.cur_datetime
self.write_log(f'{grid.direction.value}单已开仓完毕,order_price:{order.price}' self.write_log(f'{grid.direction.value}单已开仓完毕,order_price:{order.price}'
+ f',volume:{order.volume}') + f',volume:{order.volume}')
@ -1312,36 +1313,41 @@ class CtaFutureTemplate(CtaTemplate):
up_grids_info = "" up_grids_info = ""
for grid in list(self.gt.up_grids): for grid in list(self.gt.up_grids):
if not grid.open_status and grid.order_status: if not grid.open_status and grid.order_status:
up_grids_info += f'平空中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n' up_grids_info += f'平空中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
if len(grid.order_ids) > 0: if len(grid.order_ids) > 0:
up_grids_info += f'委托单号:{grid.order_ids}' up_grids_info += f'委托单号:{grid.order_ids}'
continue continue
if grid.open_status and not grid.order_status: if grid.open_status and not grid.order_status:
up_grids_info += f'持空中: [数量:{grid.volume}\n, 开仓时间:{grid.open_time}' up_grids_info += f'持空中: [数量:{grid.volume}\n, 开仓时间:{grid.open_time}]\n'
continue continue
if not grid.open_status and grid.order_status: if not grid.open_status and grid.order_status:
up_grids_info += f'开空中: [已开:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n' up_grids_info += f'开空中: [已开:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
if len(grid.order_ids) > 0: if len(grid.order_ids) > 0:
up_grids_info += f'委托单号:{grid.order_ids}' up_grids_info += f'委托单号:{grid.order_ids}'
dn_grids_info = "" dn_grids_info = ""
for grid in list(self.gt.dn_grids): for grid in list(self.gt.dn_grids):
if not grid.open_status and grid.order_status: if not grid.open_status and grid.order_status:
up_grids_info += f'平多中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n' dn_grids_info += f'平多中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
if len(grid.order_ids) > 0: if len(grid.order_ids) > 0:
up_grids_info += f'委托单号:{grid.order_ids}' dn_grids_info += f'委托单号:{grid.order_ids}'
continue continue
if grid.open_status and not grid.order_status: if grid.open_status and not grid.order_status:
up_grids_info += f'持多中: [数量:{grid.volume}\n, 开仓时间:{grid.open_time}' dn_grids_info += f'持多中: [数量:{grid.volume}\n, 开仓时间:{grid.open_time}]\n'
continue continue
if not grid.open_status and grid.order_status: if not grid.open_status and grid.order_status:
up_grids_info += f'开多中: [已开:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n' dn_grids_info += f'开多中: [已开:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
if len(grid.order_ids) > 0: if len(grid.order_ids) > 0:
up_grids_info += f'委托单号:{grid.order_ids}' dn_grids_info += f'委托单号:{grid.order_ids}'
if len(up_grids_info) > 0:
self.write_log(up_grids_info)
if len(dn_grids_info) > 0:
self.write_log(dn_grids_info)
def display_tns(self): def display_tns(self):
"""显示事务的过程记录=》 log""" """显示事务的过程记录=》 log"""

View File

@ -202,9 +202,12 @@ class StrategyManager(QtWidgets.QFrame):
reload_button = QtWidgets.QPushButton("重载") reload_button = QtWidgets.QPushButton("重载")
reload_button.clicked.connect(self.reload_strategy) reload_button.clicked.connect(self.reload_strategy)
save_button = QtWidgets.QPushButton("") save_button = QtWidgets.QPushButton("")
save_button.clicked.connect(self.save_strategy) save_button.clicked.connect(self.save_strategy)
snapshot_button = QtWidgets.QPushButton("切片")
snapshot_button.clicked.connect(self.save_snapshot)
strategy_name = self._data["strategy_name"] strategy_name = self._data["strategy_name"]
vt_symbol = self._data["vt_symbol"] vt_symbol = self._data["vt_symbol"]
class_name = self._data["class_name"] class_name = self._data["class_name"]
@ -227,6 +230,7 @@ class StrategyManager(QtWidgets.QFrame):
hbox.addWidget(remove_button) hbox.addWidget(remove_button)
hbox.addWidget(reload_button) hbox.addWidget(reload_button)
hbox.addWidget(save_button) hbox.addWidget(save_button)
hbox.addWidget(snapshot_button)
vbox = QtWidgets.QVBoxLayout() vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(label) vbox.addWidget(label)
@ -279,8 +283,12 @@ class StrategyManager(QtWidgets.QFrame):
self.cta_engine.reload_strategy(self.strategy_name) self.cta_engine.reload_strategy(self.strategy_name)
def save_strategy(self): def save_strategy(self):
"""保存K线缓存"""
self.cta_engine.save_strategy_data(self.strategy_name) self.cta_engine.save_strategy_data(self.strategy_name)
def save_snapshot(self):
""" 保存切片"""
self.cta_engine.save_strategy_snapshot(self.strategy_name)
class DataMonitor(QtWidgets.QTableWidget): class DataMonitor(QtWidgets.QTableWidget):
""" """

View File

@ -19,6 +19,7 @@ from collections import OrderedDict
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from copy import copy from copy import copy
from functools import lru_cache from functools import lru_cache
from uuid import uuid1
from vnpy.event import Event, EventEngine from vnpy.event import Event, EventEngine
from vnpy.trader.engine import BaseEngine, MainEngine from vnpy.trader.engine import BaseEngine, MainEngine
@ -37,6 +38,7 @@ from vnpy.trader.event import (
EVENT_TRADE, EVENT_TRADE,
EVENT_POSITION, EVENT_POSITION,
EVENT_STRATEGY_POS, EVENT_STRATEGY_POS,
EVENT_STRATEGY_SNAPSHOT
) )
from vnpy.trader.constant import ( from vnpy.trader.constant import (
Direction, Direction,
@ -203,21 +205,27 @@ class CtaEngine(BaseEngine):
def process_timer_event(self, event: Event): def process_timer_event(self, event: Event):
""" 处理定时器事件""" """ 处理定时器事件"""
all_trading = True
# 触发每个策略的定时接口 # 触发每个策略的定时接口
for strategy in list(self.strategies.values()): for strategy in list(self.strategies.values()):
strategy.on_timer() strategy.on_timer()
if not strategy.trading:
all_trading = False
dt = datetime.now() dt = datetime.now()
if self.last_minute != dt.minute: if self.last_minute != dt.minute:
self.last_minute = dt.minute self.last_minute = dt.minute
# 主动获取所有策略得持仓信息 if all_trading:
all_strategy_pos = self.get_all_strategy_pos() # 主动获取所有策略得持仓信息
all_strategy_pos = self.get_all_strategy_pos()
# 推送到事件 # 比对仓位,使用上述获取得持仓信息,不用重复获取
self.put_all_strategy_pos_event(all_strategy_pos) self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
# 推送到事件
self.put_all_strategy_pos_event(all_strategy_pos)
def process_tick_event(self, event: Event): def process_tick_event(self, event: Event):
"""处理tick到达事件""" """处理tick到达事件"""
@ -867,6 +875,7 @@ class CtaEngine(BaseEngine):
self.write_log(msg=msg, self.write_log(msg=msg,
strategy_name=strategy.strategy_name, strategy_name=strategy.strategy_name,
level=logging.CRITICAL) level=logging.CRITICAL)
self.send_wechat(msg)
def add_strategy( def add_strategy(
self, class_name: str, self, class_name: str,
@ -1197,6 +1206,15 @@ class CtaEngine(BaseEngine):
pickle.dump(snapshot, f) pickle.dump(snapshot, f)
self.write_log(u'切片保存成功:{}'.format(str(snapshot_file))) self.write_log(u'切片保存成功:{}'.format(str(snapshot_file)))
# 通过事件方式传导到account_recorder
snapshot.update({
'account_id': self.engine_config.get('accountid', '-'),
'strategy_group': self.engine_config.get('strategy_group', self.engine_name),
'guid': str(uuid1())
})
event = Event(EVENT_STRATEGY_SNAPSHOT, snapshot)
self.event_engine.put(event)
except Exception as ex: except Exception as ex:
self.write_error(u'获取策略{}切片数据异常:'.format(strategy_name, str(ex))) self.write_error(u'获取策略{}切片数据异常:'.format(strategy_name, str(ex)))
self.write_error(traceback.format_exc()) self.write_error(traceback.format_exc())

View File

@ -636,6 +636,8 @@ class CtaLineBar(object):
self.line_bd_fast = [] # 波段快线 self.line_bd_fast = [] # 波段快线
self.line_bd_slow = [] # 波段慢线 self.line_bd_slow = [] # 波段慢线
self.cur_bd_count = 0 # 当前波段快线慢线金叉死叉, +金叉计算, - 死叉技术 self.cur_bd_count = 0 # 当前波段快线慢线金叉死叉, +金叉计算, - 死叉技术
self._bd_fast = 0
self._bd_slow = 0
def set_params(self, setting: dict = {}): def set_params(self, setting: dict = {}):
"""设置参数""" """设置参数"""
@ -3492,7 +3494,7 @@ class CtaLineBar(object):
:param:direction检查是否有顶背离检查是否有底背离 :param:direction检查是否有顶背离检查是否有底背离
:return: :return:
""" """
if len(self.skd_top_list) < 2 or len(self.skd_buttom_list) < 2 or self._rt_sk is None or self._rt_sd is None: if len(self.skd_top_list) < 2 or len(self.skd_buttom_list) < 2:
return False return False
t1 = self.skd_top_list[-1] t1 = self.skd_top_list[-1]
@ -3501,6 +3503,8 @@ class CtaLineBar(object):
b2 = self.__get_2nd_item(self.skd_buttom_list[:-1]) b2 = self.__get_2nd_item(self.skd_buttom_list[:-1])
if runtime: if runtime:
if self._rt_sk is None or self._rt_sd is None:
return False
# 峰(顶部) # 峰(顶部)
if self._rt_sk < self.line_sk[-1] and self.line_sk[-2] < self.line_sk[-1]: if self._rt_sk < self.line_sk[-1] and self.line_sk[-2] < self.line_sk[-1]:
t1 = {} t1 = {}
@ -3610,10 +3614,12 @@ class CtaLineBar(object):
检查SDK的方向风险 检查SDK的方向风险
:return: :return:
""" """
if not self.para_active_skd or len(self.line_sk) < 2 or self._rt_sk is None: if not self.para_active_skd or len(self.line_sk) < 2 :
return False return False
if runtime: if runtime:
if self._rt_sk is None:
return False
sk = self._rt_sk sk = self._rt_sk
else: else:
sk = self.line_sk[-1] sk = self.line_sk[-1]
@ -4057,6 +4063,46 @@ class CtaLineBar(object):
elif self.line_bd_fast[-1] < self.line_bd_slow[-1]: elif self.line_bd_fast[-1] < self.line_bd_slow[-1]:
self.cur_bd_count = min(-1, self.cur_bd_count - 1) self.cur_bd_count = min(-1, self.cur_bd_count - 1)
def rt_count_bd(self):
"""实时计算波段指标"""
if self.para_bd_len <= 0:
# 不计算
return
if len(self.line_bar) < 2 * self.para_bd_len:
return
bar_mid4 = (self.line_bar[-1].close_price * 2 + self.line_bar[-1].high_price + self.line_bar[-1].low_price)/4
bar_mid4 = round(bar_mid4, self.round_n)
mid4_array = np.append(self.mid4_array, [bar_mid4])
mid4_ema_array = ta.EMA(mid4_array, self.para_bd_len)
mid4_std = np.std(mid4_array[-self.para_bd_len:], ddof=1)
mid4_ema_diff_array = mid4_array - mid4_ema_array
var5_array = (mid4_ema_diff_array / mid4_std * 100 + 200) / 4
var6_array = (ta.EMA(var5_array, 5) - 25) * 1.56
fast_array = ta.EMA(var6_array, 2) * 1.22
slow_array = ta.EMA(fast_array, 2)
self._bd_fast = fast_array[-1]
self._bd_slow = slow_array[-1]
@property
def rt_bd_fast(self):
self.check_rt_funcs(self.rt_count_bd)
if self._bd_fast is None and len(self.para_bd_len) > 0:
return self.line_bd_fast[-1]
return self._bd_fast
@property
def rt_bd_slow(self):
self.check_rt_funcs(self.rt_count_bd)
if self._bd_slow is None and len(self.para_bd_len) > 0:
return self.line_bd_slow[-1]
return self._bd_slow
def write_log(self, content): def write_log(self, content):
"""记录CTA日志""" """记录CTA日志"""
self.strategy.write_log(u'[' + self.name + u']' + content) self.strategy.write_log(u'[' + self.name + u']' + content)

View File

@ -214,6 +214,8 @@ class BinancefRestApi(RestClient):
self.orders = {} self.orders = {}
self.accountid = ""
def sign(self, request: Request) -> Request: def sign(self, request: Request) -> Request:
""" """
Generate BINANCE signature. Generate BINANCE signature.
@ -398,6 +400,9 @@ class BinancefRestApi(RestClient):
orderid, orderid,
self.gateway_name self.gateway_name
) )
order.accountid = self.accountid
order.vt_accountid = f"{self.gateway_name}.{self.accountid}"
order.datetime = datetime.now()
self.orders.update({orderid: copy(order)}) self.orders.update({orderid: copy(order)})
self.gateway.write_log(f'委托返回订单更新:{order.__dict__}') self.gateway.write_log(f'委托返回订单更新:{order.__dict__}')
self.gateway.on_order(order) self.gateway.on_order(order)
@ -510,14 +515,19 @@ class BinancefRestApi(RestClient):
"walletBalance": "9.19485176" // 账户余额 "walletBalance": "9.19485176" // 账户余额
}""" }"""
# self.gateway.write_log(print_dict(asset)) # self.gateway.write_log(print_dict(asset))
if asset['asset'] != "USDT":
continue
if not self.accountid:
self.accountid = f"{self.gateway_name}_{asset['asset']}"
account = AccountData( account = AccountData(
accountid=f"{self.gateway_name}_{asset['asset']}", accountid=self.accountid,
balance=float(asset["marginBalance"]), balance=float(asset["marginBalance"]),
frozen=float(asset["maintMargin"]), frozen=float(asset["maintMargin"]),
holding_profit=float(asset['unrealizedProfit']), holding_profit=float(asset['unrealizedProfit']),
currency='USDT', currency='USDT',
margin=float(asset["initialMargin"]), margin=float(asset["initialMargin"]),
gateway_name=self.gateway_name gateway_name=self.gateway_name,
trading_day=datetime.now().strftime('%Y-%m-%d')
) )
if account.balance: if account.balance:
@ -536,13 +546,16 @@ class BinancefRestApi(RestClient):
def on_query_position(self, data: dict, request: Request) -> None: def on_query_position(self, data: dict, request: Request) -> None:
"""""" """"""
for d in data: for d in data:
# self.gateway.write_log(d)
volume = float(d["positionAmt"]) volume = float(d["positionAmt"])
position = PositionData( position = PositionData(
accountid=self.accountid,
symbol=d["symbol"], symbol=d["symbol"],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
direction=Direction.NET, direction=Direction.NET,
volume=volume, volume=volume,
price=float(d["entryPrice"]), price=float(d["entryPrice"]),
cur_price=float(d["markPrice"]),
pnl=float(d["unRealizedProfit"]), pnl=float(d["unRealizedProfit"]),
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
@ -557,7 +570,9 @@ class BinancefRestApi(RestClient):
time = dt.strftime("%Y-%m-%d %H:%M:%S") time = dt.strftime("%Y-%m-%d %H:%M:%S")
order = OrderData( order = OrderData(
accountid=self.accountid,
orderid=d["clientOrderId"], orderid=d["clientOrderId"],
sys_orderid=str(d["orderId"]),
symbol=d["symbol"], symbol=d["symbol"],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
price=float(d["price"]), price=float(d["price"]),
@ -566,6 +581,7 @@ class BinancefRestApi(RestClient):
direction=DIRECTION_BINANCEF2VT[d["side"]], direction=DIRECTION_BINANCEF2VT[d["side"]],
traded=float(d["executedQty"]), traded=float(d["executedQty"]),
status=STATUS_BINANCEF2VT.get(d["status"], None), status=STATUS_BINANCEF2VT.get(d["status"], None),
datetime=dt,
time=time, time=time,
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
@ -582,6 +598,7 @@ class BinancefRestApi(RestClient):
time = dt.strftime("%Y-%m-%d %H:%M:%S") time = dt.strftime("%Y-%m-%d %H:%M:%S")
trade = TradeData( trade = TradeData(
accountid=self.accountid,
symbol=d['symbol'], symbol=d['symbol'],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
orderid=d['orderId'], orderid=d['orderId'],
@ -655,6 +672,11 @@ class BinancefRestApi(RestClient):
order.status = Status.REJECTED order.status = Status.REJECTED
self.orders.update({order.orderid: copy(order)}) self.orders.update({order.orderid: copy(order)})
self.gateway.write_log(f'订单委托失败:{order.__dict__}') self.gateway.write_log(f'订单委托失败:{order.__dict__}')
if not order.accountid:
order.accountid = self.accountid
order.vt_accountid = f"{self.gateway_name}.{self.accountid}"
if not order.datetime:
order.datetime = datetime.now()
self.gateway.on_order(order) self.gateway.on_order(order)
msg = f"委托失败,状态码:{status_code},信息:{request.response.text}" msg = f"委托失败,状态码:{status_code},信息:{request.response.text}"
@ -670,6 +692,11 @@ class BinancefRestApi(RestClient):
order.status = Status.REJECTED order.status = Status.REJECTED
self.orders.update({order.orderid: copy(order)}) self.orders.update({order.orderid: copy(order)})
self.gateway.write_log(f'发送订单异常:{order.__dict__}') self.gateway.write_log(f'发送订单异常:{order.__dict__}')
if not order.accountid:
order.accountid = self.accountid
order.vt_accountid = f"{self.gateway_name}.{self.accountid}"
if not order.datetime:
order.datetime = datetime.now()
self.gateway.on_order(order) self.gateway.on_order(order)
msg = f"委托失败,拒单" msg = f"委托失败,拒单"
@ -784,6 +811,7 @@ class BinancefTradeWebsocketApi(WebsocketClient):
self.gateway: BinancefGateway = gateway self.gateway: BinancefGateway = gateway
self.gateway_name: str = gateway.gateway_name self.gateway_name: str = gateway.gateway_name
self.accountid = ""
def connect(self, url: str, proxy_host: str, proxy_port: int) -> None: def connect(self, url: str, proxy_host: str, proxy_port: int) -> None:
"""""" """"""
@ -836,9 +864,12 @@ class BinancefTradeWebsocketApi(WebsocketClient):
# 计算持仓收益 # 计算持仓收益
holding_pnl = 0 holding_pnl = 0
for pos_data in packet["a"]["P"]: for pos_data in packet["a"]["P"]:
print(pos_data) # print(pos_data)
volume = float(pos_data["pa"]) volume = float(pos_data["pa"])
if not self.accountid:
self.accountid = f"{self.gateway_name}_USDT"
position = PositionData( position = PositionData(
accountid=self.accountid,
symbol=pos_data["s"], symbol=pos_data["s"],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
direction=Direction.NET, direction=Direction.NET,
@ -851,12 +882,16 @@ class BinancefTradeWebsocketApi(WebsocketClient):
self.gateway.on_position(position) self.gateway.on_position(position)
for acc_data in packet["a"]["B"]: for acc_data in packet["a"]["B"]:
if acc_data['a'] != 'USDT':
continue
account = AccountData( account = AccountData(
accountid=f"{self.gateway_name}_{acc_data['a']}", accountid=self.accountid,
balance=round(float(acc_data["wb"]), 7), balance=round(float(acc_data["wb"]), 7),
frozen=float(acc_data["wb"]) - float(acc_data["cw"]), frozen=float(acc_data["wb"]) - float(acc_data["cw"]),
holding_profit=round(holding_pnl, 7), holding_profit=round(holding_pnl, 7),
gateway_name=self.gateway_name currency='USDT',
gateway_name=self.gateway_name,
trading_day=datetime.now().strftime('%Y-%m-%d')
) )
if account.balance: if account.balance:
@ -884,15 +919,18 @@ class BinancefTradeWebsocketApi(WebsocketClient):
else: else:
self.gateway.write_log(u'缓存中找不到Order,创建一个新的') self.gateway.write_log(u'缓存中找不到Order,创建一个新的')
order = OrderData( order = OrderData(
accountid=self.accountid,
symbol=ord_data["s"], symbol=ord_data["s"],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
orderid=str(ord_data["c"]), orderid=str(ord_data["c"]),
sys_orderid=str(ord_data["i"]),
type=ORDERTYPE_BINANCEF2VT[ord_data["o"]], type=ORDERTYPE_BINANCEF2VT[ord_data["o"]],
direction=DIRECTION_BINANCEF2VT[ord_data["S"]], direction=DIRECTION_BINANCEF2VT[ord_data["S"]],
price=float(ord_data["p"]), price=float(ord_data["p"]),
volume=float(ord_data["q"]), volume=float(ord_data["q"]),
traded=float(ord_data["z"]), traded=float(ord_data["z"]),
status=STATUS_BINANCEF2VT[ord_data["X"]], status=STATUS_BINANCEF2VT[ord_data["X"]],
datetime=dt,
time=time, time=time,
gateway_name=self.gateway_name gateway_name=self.gateway_name
) )
@ -908,6 +946,7 @@ class BinancefTradeWebsocketApi(WebsocketClient):
trade_time = trade_dt.strftime("%Y-%m-%d %H:%M:%S") trade_time = trade_dt.strftime("%Y-%m-%d %H:%M:%S")
trade = TradeData( trade = TradeData(
accountid=self.accountid,
symbol=order.symbol, symbol=order.symbol,
exchange=order.exchange, exchange=order.exchange,
orderid=order.orderid, orderid=order.orderid,

View File

@ -640,6 +640,8 @@ class CtpTdApi(TdApi):
self.sysid_orderid_map = {} self.sysid_orderid_map = {}
self.future_contract_changed = False self.future_contract_changed = False
self.accountid = ""
def onFrontConnected(self): def onFrontConnected(self):
"""""" """"""
self.gateway.write_log("交易服务器连接成功") self.gateway.write_log("交易服务器连接成功")
@ -754,6 +756,7 @@ class CtpTdApi(TdApi):
position = self.positions.get(key, None) position = self.positions.get(key, None)
if not position: if not position:
position = PositionData( position = PositionData(
accountid=self.accountid,
symbol=data["InstrumentID"], symbol=data["InstrumentID"],
exchange=symbol_exchange_map[data["InstrumentID"]], exchange=symbol_exchange_map[data["InstrumentID"]],
direction=DIRECTION_CTP2VT[data["PosiDirection"]], direction=DIRECTION_CTP2VT[data["PosiDirection"]],
@ -800,6 +803,8 @@ class CtpTdApi(TdApi):
"""""" """"""
if "AccountID" not in data: if "AccountID" not in data:
return return
if not self.accountid:
self.accountid = data['AccountID']
account = AccountData( account = AccountData(
accountid=data["AccountID"], accountid=data["AccountID"],

View File

@ -111,7 +111,7 @@ class MainEngine:
if app.app_name == "RiskManager": if app.app_name == "RiskManager":
self.rm_engine = engine self.rm_engine = engine
elif app.app_name == "AlgoTrading": elif app.app_name == "AlgoTrading":
self.algo_engine == engine self.algo_engine = engine
elif app.app_name == 'RpcService': elif app.app_name == 'RpcService':
self.rpc_service = engine self.rpc_service = engine

View File

@ -15,6 +15,7 @@ EVENT_LOG = "eLog"
# 扩展 # 扩展
EVENT_BAR = "eBar." EVENT_BAR = "eBar."
EVENT_STRATEGY_POS = "eStrategyPos." EVENT_STRATEGY_POS = "eStrategyPos."
EVENT_STRATEGY_SNAPSHOT = "eStrategySnapshot."
# 拓展, 支持股票账号中,历史交成交/历史委托/资金流水 # 拓展, 支持股票账号中,历史交成交/历史委托/资金流水
EVENT_HISTORY_TRADE = 'eHistoryTrade.' EVENT_HISTORY_TRADE = 'eHistoryTrade.'

View File

@ -136,7 +136,7 @@ class OrderData(BaseData):
exchange: Exchange exchange: Exchange
orderid: str orderid: str
sys_orderid: str = "" sys_orderid: str = ""
accountid: str = ""
type: OrderType = OrderType.LIMIT type: OrderType = OrderType.LIMIT
direction: Direction = "" direction: Direction = ""
offset: Offset = Offset.NONE offset: Offset = Offset.NONE
@ -144,6 +144,7 @@ class OrderData(BaseData):
volume: float = 0 volume: float = 0
traded: float = 0 traded: float = 0
status: Status = Status.SUBMITTING status: Status = Status.SUBMITTING
datetime: datetime = None
time: str = "" time: str = ""
cancel_time: str = "" cancel_time: str = ""
@ -151,6 +152,7 @@ class OrderData(BaseData):
"""""" """"""
self.vt_symbol = f"{self.symbol}.{self.exchange.value}" self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
self.vt_orderid = f"{self.gateway_name}.{self.orderid}" self.vt_orderid = f"{self.gateway_name}.{self.orderid}"
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
def is_active(self) -> bool: def is_active(self) -> bool:
""" """
@ -183,6 +185,7 @@ class TradeData(BaseData):
orderid: str orderid: str
tradeid: str tradeid: str
sys_orderid: str = "" sys_orderid: str = ""
accountid: str = ""
direction: Direction = "" direction: Direction = ""
@ -204,7 +207,7 @@ class TradeData(BaseData):
self.vt_symbol = f"{self.symbol}.{self.exchange.value}" self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
self.vt_orderid = f"{self.gateway_name}.{self.orderid}" self.vt_orderid = f"{self.gateway_name}.{self.orderid}"
self.vt_tradeid = f"{self.gateway_name}.{self.tradeid}" self.vt_tradeid = f"{self.gateway_name}.{self.tradeid}"
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
@dataclass @dataclass
class PositionData(BaseData): class PositionData(BaseData):
@ -215,12 +218,13 @@ class PositionData(BaseData):
symbol: str symbol: str
exchange: Exchange exchange: Exchange
direction: Direction direction: Direction
accountid: str = "" # 账号id
volume: float = 0 volume: float = 0
frozen: float = 0 frozen: float = 0
price: float = 0 price: float = 0
pnl: float = 0 pnl: float = 0
yd_volume: float = 0 yd_volume: float = 0
cur_price: float = 0 # 当前价
# 股票相关 # 股票相关
holder_id: str = "" # 股东代码 holder_id: str = "" # 股东代码
@ -229,7 +233,7 @@ class PositionData(BaseData):
"""""" """"""
self.vt_symbol = f"{self.symbol}.{self.exchange.value}" self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
self.vt_positionid = f"{self.gateway_name}.{self.vt_symbol}.{self.direction.value}" self.vt_positionid = f"{self.gateway_name}.{self.vt_symbol}.{self.direction.value}"
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
@dataclass @dataclass
class AccountData(BaseData): class AccountData(BaseData):

View File

@ -73,7 +73,10 @@ class EnumCell(BaseCell):
Set text using enum.constant.value. Set text using enum.constant.value.
""" """
if content: if content:
super(EnumCell, self).set_content(content.value, data) if isinstance(content, str):
super(EnumCell, self).set_content(content, data)
else:
super(EnumCell, self).set_content(content.value, data)
class DirectionCell(EnumCell): class DirectionCell(EnumCell):