diff --git a/vnpy/api/ctp/vnctpmd.so b/vnpy/api/ctp/vnctpmd.so new file mode 100644 index 00000000..089841c7 Binary files /dev/null and b/vnpy/api/ctp/vnctpmd.so differ diff --git a/vnpy/api/ctp/vnctptd.so b/vnpy/api/ctp/vnctptd.so new file mode 100644 index 00000000..275a4679 Binary files /dev/null and b/vnpy/api/ctp/vnctptd.so differ diff --git a/vnpy/api/rest/rest_client.py b/vnpy/api/rest/rest_client.py index 96d2b163..6a70b0f5 100644 --- a/vnpy/api/rest/rest_client.py +++ b/vnpy/api/rest/rest_client.py @@ -311,7 +311,7 @@ class RestClient(object): not_finished_executors = [i for i in self._executors if not i.done()] self._executors = not_finished_executors - def _clean_finished_tasks(self, result = None): + def _clean_finished_tasks(self, result=None): with self._tasks_lock: not_finished_tasks = [i for i in self._tasks if not i.ready()] self._tasks = not_finished_tasks diff --git a/vnpy/app/cta_crypto/back_testing.py b/vnpy/app/cta_crypto/back_testing.py index 1054feb1..2e56b72d 100644 --- a/vnpy/app/cta_crypto/back_testing.py +++ b/vnpy/app/cta_crypto/back_testing.py @@ -65,6 +65,7 @@ from vnpy.trader.util_logger import setup_logger from vnpy.data.mongo.mongo_data import MongoData from uuid import uuid1 + class BackTestingEngine(object): """ CTA回测引擎 @@ -106,7 +107,7 @@ class BackTestingEngine(object): self.fix_commission = {} # 每手固定手续费 self.size = {} # 合约大小,默认为1 self.price_tick = {} # 价格最小变动 - self.volume_tick = {} # 合约委托单最小单位 + self.volume_tick = {} # 合约委托单最小单位 self.margin_rate = {} # 回测合约的保证金比率 self.price_dict = {} # 登记vt_symbol对应的最新价 self.contract_dict = {} # 登记vt_symbol得对应合约信息 @@ -207,7 +208,7 @@ class BackTestingEngine(object): # 回测任务/回测结果,保存在数据库中 self.mongo_api = None self.task_id = None - self.test_setting = None # 回测设置 + self.test_setting = None # 回测设置 self.strategy_setting = None # 所有回测策略得设置 def create_fund_kline(self, name, use_renko=False): @@ -543,7 +544,7 @@ class BackTestingEngine(object): for symbol, symbol_data in data_dict.items(): self.write_log(u'配置{}数据:{}'.format(symbol, symbol_data)) self.set_price_tick(symbol, symbol_data.get('price_tick', 1)) - self.set_volume_tick(symbol, symbol_data.get('min_volume',1)) + self.set_volume_tick(symbol, symbol_data.get('min_volume', 1)) self.set_slippage(symbol, symbol_data.get('slippage', 0)) self.set_size(symbol, symbol_data.get('symbol_size', 10)) margin_rate = symbol_data.get('margin_rate', 0.1) @@ -1664,7 +1665,7 @@ class BackTestingEngine(object): for t in self.long_position_list: # 当前持仓的保证金 cur_occupy_money = min(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate( - t.vt_symbol) + t.vt_symbol) # 更新该合约短号的累计保证金 underly_symbol = get_underlying_symbol(t.symbol) @@ -1680,7 +1681,8 @@ class BackTestingEngine(object): if len(self.short_position_list) > 0: for t in self.short_position_list: # 当前空单保证金 - cur_occupy_money = max(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate(t.vt_symbol) + cur_occupy_money = max(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate( + t.vt_symbol) # 该合约短号的累计空单保证金 underly_symbol = get_underlying_symbol(t.symbol) @@ -1695,7 +1697,8 @@ class BackTestingEngine(object): # 计算多空的保证金累加(对锁的取最大值) for underly_symbol in occupy_underly_symbol_set: - occupy_money += occupy_long_money_dict.get(underly_symbol, 0) + occupy_short_money_dict.get(underly_symbol, 0) + occupy_money += occupy_long_money_dict.get(underly_symbol, 0) + occupy_short_money_dict.get(underly_symbol, + 0) # 可用资金 = 当前净值 - 占用保证金 self.avaliable = self.net_capital - occupy_money @@ -2070,12 +2073,12 @@ class BackTestingEngine(object): self.mongo_api = MongoData(host=save_mongo.get('host', 'localhost'), port=save_mongo.get('port', 27017)) d = { - 'task_id': self.task_id, # 单实例回测任务id - 'name': self.test_name, # 回测实例名称, 策略名+参数+时间 + 'task_id': self.task_id, # 单实例回测任务id + 'name': self.test_name, # 回测实例名称, 策略名+参数+时间 'group_id': self.test_setting.get('group_id', datetime.now().strftime('%y-%m-%d')), # 回测组合id 'status': 'start', - 'task_start_time': datetime.now(), # 任务开始执行时间 - 'run_host': socket.gethostname(), # 任务运行得host主机 + 'task_start_time': datetime.now(), # 任务开始执行时间 + 'run_host': socket.gethostname(), # 任务运行得host主机 'test_setting': self.test_setting, # 回测参数 'strategy_setting': self.strategy_setting, # 策略参数 } @@ -2135,11 +2138,11 @@ class BackTestingEngine(object): flt=flt) if d: - d.update({'status': 'finish'}) # 更新状态未完成 - d.update(result_info) # 补充回测结果 - d.update({'task_finish_time': datetime.now()}) # 更新回测完成时间 - d.update({'trade_list': binary.Binary(zlib.compress(pickle.dumps(self.trade_pnl_list)))}) # 更新交易记录 - d.update({'daily_list': binary.Binary(zlib.compress(pickle.dumps(self.daily_list)))}) # 更新每日净值记录 + d.update({'status': 'finish'}) # 更新状态未完成 + d.update(result_info) # 补充回测结果 + d.update({'task_finish_time': datetime.now()}) # 更新回测完成时间 + d.update({'trade_list': binary.Binary(zlib.compress(pickle.dumps(self.trade_pnl_list)))}) # 更新交易记录 + d.update({'daily_list': binary.Binary(zlib.compress(pickle.dumps(self.daily_list)))}) # 更新每日净值记录 self.write_log(u'更新回测结果至数据库') diff --git a/vnpy/app/cta_crypto/engine.py b/vnpy/app/cta_crypto/engine.py index c1b9cd74..9367d2f1 100644 --- a/vnpy/app/cta_crypto/engine.py +++ b/vnpy/app/cta_crypto/engine.py @@ -344,7 +344,6 @@ class CtaEngine(BaseEngine): holding = self.get_position_holding(position.vt_symbol, position.gateway_name) holding.update_position(position) - def check_unsubscribed_symbols(self): """检查未订阅合约""" @@ -1179,7 +1178,7 @@ class CtaEngine(BaseEngine): self.write_log(msg) return True, msg - def save_strategy_data(self, select_name: str): + def save_strategy_data(self, select_name: str = 'ALL'): """ save strategy data""" has_executed = False msg = "" @@ -1215,7 +1214,7 @@ class CtaEngine(BaseEngine): self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex))) self.write_error(traceback.format_exc()) - def save_strategy_snapshot(self, select_name: str): + def save_strategy_snapshot(self, select_name: str = 'ALL'): """ 保存策略K线切片数据 :param select_name: @@ -1607,7 +1606,7 @@ class CtaEngine(BaseEngine): try: from vnpy.trader.util_wechat import send_wx_msg send_wx_msg(content=msg) - except Exception as ex: + except Exception: # noqa pass ret_msg = u'持仓不匹配: {}' \ .format(pos_compare_result) diff --git a/vnpy/app/cta_crypto/portfolio_testing.py b/vnpy/app/cta_crypto/portfolio_testing.py index 3b05604f..e192115d 100644 --- a/vnpy/app/cta_crypto/portfolio_testing.py +++ b/vnpy/app/cta_crypto/portfolio_testing.py @@ -13,9 +13,6 @@ import gc import pandas as pd import traceback import random -import bz2 -import pickle - from datetime import datetime, timedelta from time import sleep @@ -196,7 +193,6 @@ class PortfolioTestingEngine(BackTestingEngine): symbol, exchange = extract_vt_symbol(vt_symbol) self.load_bar_csv_to_df(vt_symbol, self.bar_csv_file.get(symbol)) - # 合并数据 self.comine_bar_df() @@ -309,6 +305,7 @@ class PortfolioTestingEngine(BackTestingEngine): traceback.print_exc() return + def single_test(test_setting: dict, strategy_setting: dict): """ 单一回测 diff --git a/vnpy/app/cta_crypto/template.py b/vnpy/app/cta_crypto/template.py index 35d1f68d..132d4478 100644 --- a/vnpy/app/cta_crypto/template.py +++ b/vnpy/app/cta_crypto/template.py @@ -16,11 +16,9 @@ from vnpy.trader.constant import Interval, Direction, Offset, Status, OrderType from vnpy.trader.object import BarData, TickData, OrderData, TradeData from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol -from .base import StopOrder, EngineType -from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade, LOCK_GRID +from .base import StopOrder +from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade from vnpy.component.cta_position import CtaPosition -from vnpy.component.cta_policy import CtaPolicy # noqa - class CtaTemplate(ABC): """CTA策略模板""" @@ -416,8 +414,6 @@ class CtaTemplate(ABC): self.cta_engine.sync_strategy_data(self) - - class CtaFutureTemplate(CtaTemplate): """ 合约期货模板 @@ -426,7 +422,7 @@ class CtaFutureTemplate(CtaTemplate): price_tick = 1 # 商品的最小价格跳动 symbol_size = 10 # 商品得合约乘数 margin_rate = 0.1 # 商品的保证金 - volumn_tick = 1 # 商品最小成交数量 + volumn_tick = 1 # 商品最小成交数量 # 委托类型 order_type = OrderType.LIMIT @@ -441,7 +437,7 @@ class CtaFutureTemplate(CtaTemplate): backtesting = False # 逻辑过程日志 - dist_fieldnames = ['datetime', 'symbol', 'volume', 'price','margin', + dist_fieldnames = ['datetime', 'symbol', 'volume', 'price', 'margin', 'operation', 'signal', 'stop_price', 'target_price', 'long_pos', 'short_pos'] @@ -844,37 +840,7 @@ class CtaFutureTemplate(CtaTemplate): self.active_orders.pop(order.vt_orderid, None) return - order_price = old_order['price'] - order_type = old_order.get('order_type', OrderType.LIMIT) - order_retry = old_order.get('retry', 0) grid = old_order.get('grid', None) - if order_retry > 20: - # 这里超过20次尝试失败后,不再尝试,发出告警信息 - msg = u'{} {}/{}手, 重试开仓次数{}>20' \ - .format(self.strategy_name, - order_vt_symbol, - order_volume, - order_retry) - self.write_error(msg) - self.send_wechat(msg) - - if grid: - if order.vt_orderid in grid.order_ids: - grid.order_ids.remove(order.vt_orderid) - - # 网格的所有委托单已经执行完毕 - if len(grid.order_ids) == 0: - grid.order_status = False - - self.gt.save() - self.write_log(u'网格信息更新:{}'.format(grid.__dict__)) - - self.write_log(u'移除:{}'.format(order.vt_orderid)) - self.active_orders.pop(order.vt_orderid, None) - return - - order_retry += 1 - pre_status = old_order.get('status', Status.NOTTRADED) old_order.update({'status': Status.CANCELLED}) self.write_log(u'委托单状态:{}=>{}'.format(pre_status, old_order.get('status'))) @@ -918,29 +884,7 @@ class CtaFutureTemplate(CtaTemplate): self.active_orders.pop(order.vt_orderid, None) return - order_price = old_order['price'] - order_type = old_order.get('order_type', OrderType.LIMIT) - order_retry = old_order.get('retry', 1) grid = old_order.get('grid', None) - if order_retry > 20: - msg = u'{} 平仓撤单 {}/{}手, 重试平仓次数{}>20' \ - .format(self.strategy_name, order_symbol, order_volume, order_retry) - self.write_error(msg) - self.send_wechat(msg) - if grid: - if order.vt_orderid in grid.order_ids: - grid.order_ids.remove(order.vt_orderid) - if not grid.order_ids: - grid.order_status = False - self.gt.save() - self.write_log(u'更新网格=>{}'.format(grid.__dict__)) - - self.write_log(u'移除活动订单:{}'.format(order.vt_orderid)) - self.active_orders.pop(order.vt_orderid, None) - return - - order_retry += 1 - pre_status = old_order.get('status', Status.NOTTRADED) old_order.update({'status': Status.CANCELLED}) self.write_log(u'委托单状态:{}=>{}'.format(pre_status, old_order.get('status'))) @@ -957,7 +901,6 @@ class CtaFutureTemplate(CtaTemplate): def on_stop_order(self, stop_order: StopOrder): self.write_log(f'停止单触发:{stop_order.__dict__}') - def grid_check_stop(self): """ 网格逐一止损/止盈检查 (根据指数价格进行止损止盈) @@ -976,12 +919,12 @@ class CtaFutureTemplate(CtaTemplate): if g.stop_price > 0 and g.stop_price > self.cur_price and g.open_status and not g.order_status: # 调用平仓模块 self.write_log(u'{} {}当前价:{} 触发多单止损线{},开仓价:{},v:{}'. - format(self.cur_datetime, - self.vt_symbol, - self.cur_price, - g.stop_price, - g.open_price, - g.volume)) + format(self.cur_datetime, + self.vt_symbol, + self.cur_price, + g.stop_price, + g.open_price, + g.volume)) if self.grid_sell(g): self.write_log(u'多单止盈/止损委托成功') else: @@ -993,8 +936,8 @@ class CtaFutureTemplate(CtaTemplate): if g.stop_price > 0 and g.stop_price < self.cur_price and g.open_status and not g.order_status: # 网格止损 self.write_log(u'{} {}当前价:{} 触发空单止损线:{}, 开仓价:{},v:{}'. - format(self.cur_datetime, self.vt_symbol, self.cur_price, g.stop_price, - g.open_price, g.volume)) + format(self.cur_datetime, self.vt_symbol, self.cur_price, g.stop_price, + g.open_price, g.volume)) if self.grid_cover(g): self.write_log(u'空单止盈/止损委托成功') else: @@ -1013,16 +956,15 @@ class CtaFutureTemplate(CtaTemplate): grid=grid) if len(vt_orderids) > 0: self.write_log(u'创建{}事务多单,开仓价:{},数量:{},止盈价:{},止损价:{}' - .format(grid.type, grid.open_price, grid.volume, grid.close_price, grid.stop_price)) + .format(grid.type, grid.open_price, grid.volume, grid.close_price, grid.stop_price)) self.gt.dn_grids.append(grid) self.gt.save() return True else: self.write_error(u'创建{}事务多单,委托失败,开仓价:{},数量:{},止盈价:{}' - .format(grid.type, grid.open_price, grid.volume, grid.close_price)) + .format(grid.type, grid.open_price, grid.volume, grid.close_price)) return False - def grid_short(self, grid): """ 事务开空仓 @@ -1036,14 +978,14 @@ class CtaFutureTemplate(CtaTemplate): grid=grid) if len(vt_orderids) > 0: self.write_log(u'创建{}事务空单,指数开空价:{},主力开仓价:{},数量:{},止盈价:{},止损价:{}' - .format(grid.type, grid.open_price, self.cur_price, grid.volume, grid.close_price, - grid.stop_price)) + .format(grid.type, grid.open_price, self.cur_price, grid.volume, grid.close_price, + grid.stop_price)) self.gt.up_grids.append(grid) self.gt.save() return True else: self.write_error(u'创建{}事务空单,委托失败,开仓价:{},数量:{},止盈价:{}' - .format(grid.type, grid.open_price, grid.volume, grid.close_price)) + .format(grid.type, grid.open_price, grid.volume, grid.close_price)) return False def grid_sell(self, grid): @@ -1302,7 +1244,6 @@ class CtaFutureTemplate(CtaTemplate): if len(self.active_orders) == 0: self.entrust = 0 - def display_grids(self): """更新网格显示信息""" if not self.inited: @@ -1340,7 +1281,9 @@ class CtaFutureTemplate(CtaTemplate): save_path = self.cta_engine.get_data_path() try: if 'margin' not in dist_data: - dist_data.update({'margin': dist_data.get('price', 0) * dist_data.get('volume', 0) * self.cta_engine.get_margin_rate(dist_data.get('symbol', self.vt_symbol))}) + dist_data.update({'margin': dist_data.get('price', 0) * dist_data.get('volume', + 0) * self.cta_engine.get_margin_rate( + dist_data.get('symbol', self.vt_symbol))}) if self.position and 'long_pos' not in dist_data: dist_data.update({'long_pos': self.position.long_pos}) if self.position and 'short_pos' not in dist_data: @@ -1373,5 +1316,3 @@ class CtaFutureTemplate(CtaTemplate): if self.backtesting: return self.cta_engine.send_wechat(msg=msg, strategy=self) - - diff --git a/vnpy/app/cta_strategy_pro/__init__.py b/vnpy/app/cta_strategy_pro/__init__.py index 728588b9..b21941cc 100644 --- a/vnpy/app/cta_strategy_pro/__init__.py +++ b/vnpy/app/cta_strategy_pro/__init__.py @@ -14,7 +14,11 @@ from .template import ( BarData, TradeData, OrderData, - CtaTemplate, CtaSignal, TargetPosTemplate, CtaProTemplate, CtaProFutureTemplate) # noqa + CtaTemplate, + CtaSignal, + TargetPosTemplate, + CtaProTemplate, + CtaProFutureTemplate) # noqa from vnpy.trader.utility import BarGenerator, ArrayManager # noqa from .template_spread import CtaSpreadTemplate diff --git a/vnpy/app/cta_strategy_pro/engine.py b/vnpy/app/cta_strategy_pro/engine.py index ebc5a1df..2f19372e 100644 --- a/vnpy/app/cta_strategy_pro/engine.py +++ b/vnpy/app/cta_strategy_pro/engine.py @@ -715,7 +715,9 @@ class CtaEngine(BaseEngine): strategy = self.strategies.get(strategy_name, None) if not strategy: return False - + if len(vt_symbol) == 0: + self.write_error(f'不能为{strategy_name}订阅空白合约') + return False contract = self.main_engine.get_contract(vt_symbol) if contract: if contract.gateway_name and not gateway_name: @@ -1101,7 +1103,7 @@ class CtaEngine(BaseEngine): self.write_log(msg) return True, msg - def save_strategy_data(self, select_name: str): + def save_strategy_data(self, select_name: str = 'ALL'): """ save strategy data""" has_executed = False msg = "" @@ -1137,7 +1139,7 @@ class CtaEngine(BaseEngine): self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex))) self.write_error(traceback.format_exc()) - def save_strategy_snapshot(self, select_name: str): + def save_strategy_snapshot(self, select_name: str = 'ALL'): """ 保存策略K线切片数据 :param select_name: @@ -1571,7 +1573,7 @@ class CtaEngine(BaseEngine): try: from vnpy.trader.util_wechat import send_wx_msg send_wx_msg(content=msg) - except Exception as ex: + except Exception as ex: # noqa pass ret_msg = u'持仓不匹配: {}' \ .format(pos_compare_result) diff --git a/vnpy/app/cta_strategy_pro/template.py b/vnpy/app/cta_strategy_pro/template.py index 786f72de..d5c9fe27 100644 --- a/vnpy/app/cta_strategy_pro/template.py +++ b/vnpy/app/cta_strategy_pro/template.py @@ -1568,7 +1568,8 @@ class CtaProFutureTemplate(CtaProTemplate): over_seconds = (dt - order_time).total_seconds() # 只处理未成交的限价委托单 - if order_status in [Status.NOTTRADED,Status.SUBMITTING] and (order_type == OrderType.LIMIT or '.SPD' in order_vt_symbol): + if order_status in [Status.NOTTRADED, Status.SUBMITTING] and ( + order_type == OrderType.LIMIT or '.SPD' in order_vt_symbol): if over_seconds > self.cancel_seconds or force: # 超过设置的时间还未成交 self.write_log(u'超时{}秒未成交,取消委托单:vt_orderid:{},order:{}' .format(over_seconds, vt_orderid, order_info)) diff --git a/vnpy/app/rpc_service/engine.py b/vnpy/app/rpc_service/engine.py index a9a80e56..442c6e7d 100644 --- a/vnpy/app/rpc_service/engine.py +++ b/vnpy/app/rpc_service/engine.py @@ -98,7 +98,7 @@ class RpcEngine(BaseEngine): self.save_setting() self.write_log("RPC服务启动成功") - return True,"RPC服务启动成功" + return True, "RPC服务启动成功" def stop(self): """""" diff --git a/vnpy/component/cta_line_bar.py b/vnpy/component/cta_line_bar.py index 53a57bf7..d1d7279c 100644 --- a/vnpy/component/cta_line_bar.py +++ b/vnpy/component/cta_line_bar.py @@ -3353,10 +3353,10 @@ class CtaLineBar(object): # 记录所有SK的顶部和底部 # 峰(顶部) if self.line_sk[-1] < self.line_sk[-2] and self.line_sk[-3] < self.line_sk[-2]: - t = {} + t = dict() t['type'] = u'T' t['sk'] = self.line_sk[-2] - t['price'] = max([self.high_array[-4:]]) + t['price'] = max(self.high_array[-4:]) t['time'] = self.line_bar[-1].datetime t['bars'] = 0 if len(self.skd_top_list) > self.max_hold_bars: @@ -3369,10 +3369,10 @@ class CtaLineBar(object): # 谷(底部) elif self.line_sk[-1] > self.line_sk[-2] and self.line_sk[-3] > self.line_sk[-2]: - b = {} + b = dict() b['type'] = u'B' b['sk'] = self.line_sk[-2] - b['price'] = min([bar.low_price for bar in self.line_bar[-4:]]) + b['price'] = min(self.low_array[-4:]) b['time'] = self.line_bar[-1].datetime b['bars'] = 0 if len(self.skd_buttom_list) > self.max_hold_bars: diff --git a/vnpy/component/cta_position.py b/vnpy/component/cta_position.py index 6342c725..5a59e559 100644 --- a/vnpy/component/cta_position.py +++ b/vnpy/component/cta_position.py @@ -81,7 +81,6 @@ class CtaPosition(CtaComponent): self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}') self.write_log(f'净:{pre_pos}->{self.pos}') - return True def clear(self): diff --git a/vnpy/data/binance/binance_future_data.py b/vnpy/data/binance/binance_future_data.py index 3d125a28..525cad13 100644 --- a/vnpy/data/binance/binance_future_data.py +++ b/vnpy/data/binance/binance_future_data.py @@ -201,7 +201,7 @@ class BinanceFutureData(RestClient): "name": name, "price_tick": pricetick, "symbol_size": 20, - "margin_rate" : round(float(d['requiredMarginPercent']) / 100,5), + "margin_rate": round(float(d['requiredMarginPercent']) / 100, 5), "min_volume": min_volume, "product": Product.FUTURES.value, "commission_rate": 0.005 @@ -218,7 +218,6 @@ class BinanceFutureData(RestClient): contracts = load_json(f, auto_save=False) return contracts - def save_contracts(self): """保存合约配置""" contracts = self.get_contracts() diff --git a/vnpy/gateway/binance/binance_gateway.py b/vnpy/gateway/binance/binance_gateway.py index 33781976..d42dac5a 100644 --- a/vnpy/gateway/binance/binance_gateway.py +++ b/vnpy/gateway/binance/binance_gateway.py @@ -37,7 +37,6 @@ from vnpy.trader.object import ( from vnpy.trader.event import EVENT_TIMER from vnpy.event import Event - REST_HOST = "https://www.binance.com" WEBSOCKET_TRADE_HOST = "wss://stream.binance.com:9443/ws/" WEBSOCKET_DATA_HOST = "wss://stream.binance.com:9443/stream?streams=" @@ -159,6 +158,7 @@ class BinanceGateway(BaseGateway): and self.status.get('mdws_con', False): self.status.update({'con': True}) + class BinanceRestApi(RestClient): """ BINANCE REST API @@ -234,12 +234,12 @@ class BinanceRestApi(RestClient): return request def connect( - self, - key: str, - secret: str, - session_number: int, - proxy_host: str, - proxy_port: int + self, + key: str, + secret: str, + session_number: int, + proxy_host: str, + proxy_port: int ): """ Initialize connection to REST server. @@ -250,7 +250,7 @@ class BinanceRestApi(RestClient): self.proxy_host = proxy_host self.connect_time = ( - int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count + int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count ) self.init(REST_HOST, proxy_host, proxy_port) @@ -504,7 +504,7 @@ class BinanceRestApi(RestClient): self.gateway.write_log(msg) def on_send_order_error( - self, exception_type: type, exception_value: Exception, tb, request: Request + self, exception_type: type, exception_value: Exception, tb, request: Request ): """ Callback when sending order caused exception. @@ -545,13 +545,13 @@ class BinanceRestApi(RestClient): "symbol": req.symbol, "interval": INTERVAL_VT2BINANCE[req.interval], "limit": limit, - "startTime": start_time * 1000, # convert to millisecond + "startTime": start_time * 1000, # convert to millisecond } # Add end time if specified if req.end: end_time = int(datetime.timestamp(req.end)) - params["endTime"] = end_time * 1000 # convert to millisecond + params["endTime"] = end_time * 1000 # convert to millisecond # Get response from server resp = self.request( @@ -576,7 +576,7 @@ class BinanceRestApi(RestClient): buf = [] for l in data: - dt = datetime.fromtimestamp(l[0] / 1000) # convert to second + dt = datetime.fromtimestamp(l[0] / 1000) # convert to second bar = BarData( symbol=req.symbol, diff --git a/vnpy/gateway/binancef/binancef_gateway.py b/vnpy/gateway/binancef/binancef_gateway.py index d8f1f71c..ca179521 100644 --- a/vnpy/gateway/binancef/binancef_gateway.py +++ b/vnpy/gateway/binancef/binancef_gateway.py @@ -212,7 +212,6 @@ class BinancefRestApi(RestClient): self.orders = {} - def sign(self, request: Request) -> Request: """ Generate BINANCE signature. @@ -262,13 +261,13 @@ class BinancefRestApi(RestClient): return request def connect( - self, - key: str, - secret: str, - session_number: int, - server: str, - proxy_host: str, - proxy_port: int + self, + key: str, + secret: str, + session_number: int, + server: str, + proxy_host: str, + proxy_port: int ) -> None: """ Initialize connection to REST server. @@ -280,7 +279,7 @@ class BinancefRestApi(RestClient): self.server = server self.connect_time = ( - int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count + int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count ) if self.server == "REAL": @@ -306,7 +305,6 @@ class BinancefRestApi(RestClient): # 添加到定时查询队列中 self.gateway.query_functions = [self.query_account, self.query_position] - def query_time(self) -> Request: """""" data = { @@ -366,12 +364,11 @@ class BinancefRestApi(RestClient): data=data ) - def query_trade(self, vt_symbol: str = '') -> Request: """""" data = {"security": Security.SIGNED} if vt_symbol: - if '.' in vt_symbol: + if '.' in vt_symbol: vt_symbol = vt_symbol.split('.')[0] data.update({'symbol': vt_symbol}) @@ -607,7 +604,6 @@ class BinancefRestApi(RestClient): self.gateway.write_log("委托信息查询成功") - def on_query_trade(self, data: dict, request: Request) -> None: """""" for d in data: @@ -624,6 +620,7 @@ class BinancefRestApi(RestClient): price=float(d["price"]), volume=float(d['qty']), time=time, + datetime=dt, gateway_name=self.gateway_name, ) self.gateway.on_trade(trade) @@ -664,7 +661,7 @@ class BinancefRestApi(RestClient): name=name, pricetick=pricetick, size=symbol_size, - margin_rate= round(float(d['requiredMarginPercent'])/100, 5), + margin_rate=round(float(d['requiredMarginPercent']) / 100, 5), min_volume=min_volume, product=Product.FUTURES, history_data=True, @@ -692,7 +689,7 @@ class BinancefRestApi(RestClient): self.gateway.write_log(msg) def on_send_order_error( - self, exception_type: type, exception_value: Exception, tb, request: Request + self, exception_type: type, exception_value: Exception, tb, request: Request ) -> None: """ Callback when sending order caused exception. @@ -738,13 +735,13 @@ class BinancefRestApi(RestClient): "symbol": req.symbol, "interval": INTERVAL_VT2BINANCEF[req.interval], "limit": limit, - "startTime": start_time * 1000, # convert to millisecond + "startTime": start_time * 1000, # convert to millisecond } # Add end time if specified if req.end: end_time = int(datetime.timestamp(req.end)) - params["endTime"] = end_time * 1000 # convert to millisecond + params["endTime"] = end_time * 1000 # convert to millisecond # Get response from server resp = self.request( @@ -769,7 +766,7 @@ class BinancefRestApi(RestClient): buf = [] for l in data: - dt = datetime.fromtimestamp(l[0] / 1000) # convert to second + dt = datetime.fromtimestamp(l[0] / 1000) # convert to second bar = BarData( symbol=req.symbol, @@ -910,6 +907,7 @@ class BinancefTradeWebsocketApi(WebsocketClient): price=float(ord_data["L"]), volume=trade_volume, time=trade_time, + datetime=trade_time, gateway_name=self.gateway_name, ) self.gateway.on_trade(trade) @@ -928,10 +926,10 @@ class BinancefDataWebsocketApi(WebsocketClient): self.ticks: Dict[str, TickData] = {} def connect( - self, - proxy_host: str, - proxy_port: int, - server: str + self, + proxy_host: str, + proxy_port: int, + server: str ) -> None: """""" self.proxy_host = proxy_host diff --git a/vnpy/trader/gateway.py b/vnpy/trader/gateway.py index 70675dd3..94b3510f 100644 --- a/vnpy/trader/gateway.py +++ b/vnpy/trader/gateway.py @@ -1,7 +1,6 @@ """ """ -import os import sys from abc import ABC, abstractmethod from typing import Any, Sequence, Dict, List, Optional, Callable @@ -324,6 +323,7 @@ class BaseGateway(ABC): """ return self.status + class LocalOrderManager: """ Management tool to support use local order id for trading. diff --git a/vnpy/trader/ui/widget.py b/vnpy/trader/ui/widget.py index fd4e36ed..2c8bbee1 100644 --- a/vnpy/trader/ui/widget.py +++ b/vnpy/trader/ui/widget.py @@ -48,6 +48,8 @@ class BaseCell(QtWidgets.QTableWidgetItem): Set text content. """ self.setText(str(content)) + if isinstance(data, float): + data = round(data, 7) self._data = data def get_data(self) -> Any: @@ -737,36 +739,36 @@ class TradingWidget(QtWidgets.QWidget): if not self.checkFixed.isChecked(): self.price_line.setText(str(tick.last_price)) - self.lp_label.setText(str(tick.last_price)) - self.bp1_label.setText(str(tick.bid_price_1)) - self.bv1_label.setText(str(tick.bid_volume_1)) - self.ap1_label.setText(str(tick.ask_price_1)) - self.av1_label.setText(str(tick.ask_volume_1)) + self.lp_label.setText(str(round(tick.last_price, 7))) + self.bp1_label.setText(str(round(tick.bid_price_1, 7))) + self.bv1_label.setText(str(round(tick.bid_volume_1, 7))) + self.ap1_label.setText(str(round(tick.ask_price_1, 7))) + self.av1_label.setText(str(round(tick.ask_volume_1, 7))) if tick.pre_close: r = (tick.last_price / tick.pre_close - 1) * 100 self.return_label.setText(f"{r:.2f}%") if tick.bid_price_2: - self.bp2_label.setText(str(tick.bid_price_2)) - self.bv2_label.setText(str(tick.bid_volume_2)) - self.ap2_label.setText(str(tick.ask_price_2)) - self.av2_label.setText(str(tick.ask_volume_2)) + self.bp2_label.setText(str(round(tick.bid_price_2), 7)) + self.bv2_label.setText(str(round(tick.bid_volume_2, 7))) + self.ap2_label.setText(str(round(tick.ask_price_2, 7))) + self.av2_label.setText(str(round(tick.ask_volume_2, 7))) - self.bp3_label.setText(str(tick.bid_price_3)) - self.bv3_label.setText(str(tick.bid_volume_3)) - self.ap3_label.setText(str(tick.ask_price_3)) - self.av3_label.setText(str(tick.ask_volume_3)) + self.bp3_label.setText(str(round(tick.bid_price_3, 7))) + self.bv3_label.setText(str(round(tick.bid_volume_3, 7))) + self.ap3_label.setText(str(round(tick.ask_price_3, 7))) + self.av3_label.setText(str(round(tick.ask_volume_3, 7))) - self.bp4_label.setText(str(tick.bid_price_4)) - self.bv4_label.setText(str(tick.bid_volume_4)) - self.ap4_label.setText(str(tick.ask_price_4)) - self.av4_label.setText(str(tick.ask_volume_4)) + self.bp4_label.setText(str(round(tick.bid_price_4, 7))) + self.bv4_label.setText(str(round(tick.bid_volume_4, 7))) + self.ap4_label.setText(str(round(tick.ask_price_4, 7))) + self.av4_label.setText(str(round(tick.ask_volume_4, 7))) - self.bp5_label.setText(str(tick.bid_price_5)) - self.bv5_label.setText(str(tick.bid_volume_5)) - self.ap5_label.setText(str(tick.ask_price_5)) - self.av5_label.setText(str(tick.ask_volume_5)) + self.bp5_label.setText(str(round(tick.bid_price_5, 7))) + self.bv5_label.setText(str(round(tick.bid_volume_5, 7))) + self.ap5_label.setText(str(round(tick.ask_price_5, 7))) + self.av5_label.setText(str(round(tick.ask_volume_5, 7))) def set_vt_symbol(self) -> None: """ diff --git a/vnpy/trader/util_monitor.py b/vnpy/trader/util_monitor.py index 40b1150c..1ad3070d 100644 --- a/vnpy/trader/util_monitor.py +++ b/vnpy/trader/util_monitor.py @@ -1,9 +1,8 @@ # encoding: UTF-8 # 华富资产 -import os -from collections import OrderedDict -from typing import Any, Dict + +from typing import Dict from .utility import get_folder_path from .util_logger import setup_logger @@ -83,6 +82,7 @@ class LogMonitor(BasicMonitor): def __init__(self, event_engine=None, monitor_name='LogMonitor'): super().__init__(event_engine, monitor_name) + class TradeMonitor(BasicMonitor): """ Monitor for trade data. @@ -108,6 +108,7 @@ class TradeMonitor(BasicMonitor): def __init__(self, event_engine=None, monitor_name='TradeMonitor'): super().__init__(event_engine, monitor_name) + class OrderMonitor(BasicMonitor): """ Monitor for order data. @@ -135,6 +136,7 @@ class OrderMonitor(BasicMonitor): def __init__(self, event_engine=None, monitor_name='OrderMonitor'): super().__init__(event_engine, monitor_name) + class PositionMonitor(BasicMonitor): """ Monitor for position data. diff --git a/vnpy/trader/util_pid.py b/vnpy/trader/util_pid.py index 00279137..6ac9d87f 100644 --- a/vnpy/trader/util_pid.py +++ b/vnpy/trader/util_pid.py @@ -16,6 +16,7 @@ assert os.path.isdir(logs_path) # 记录pid得文件 pid_file = os.path.abspath(os.path.join(logs_path, 'gpid.txt')) + def _check_pid(pid): """ 检查pid是否与当前进程pid一致 @@ -70,6 +71,7 @@ def update_pid(): # 执行检查 if _check_status(): import sys + print(u'another service is already running...', file=sys.stderr) exit(0) diff --git a/vnpy/trader/utility.py b/vnpy/trader/utility.py index 45cbc0c5..3b67b3ca 100644 --- a/vnpy/trader/utility.py +++ b/vnpy/trader/utility.py @@ -234,7 +234,7 @@ def get_folder_path(folder_name: str) -> Path: folder_path = TEMP_DIR.joinpath(folder_name) if not folder_path.exists(): os.makedirs(str(folder_path)) - #folder_path.mkdir() + # folder_path.mkdir() return folder_path