diff --git a/vnpy/app/spread_trading/algo.py b/vnpy/app/spread_trading/algo.py index 13b3e968..bda5d317 100644 --- a/vnpy/app/spread_trading/algo.py +++ b/vnpy/app/spread_trading/algo.py @@ -1,5 +1,4 @@ from typing import Any -from math import floor, ceil from vnpy.trader.constant import Direction from vnpy.trader.object import (TickData, OrderData, TradeData) @@ -35,6 +34,10 @@ class SpreadTakerAlgo(SpreadAlgoTemplate): def on_tick(self, tick: TickData): """""" + # Return if tick not inited + if not self.spread.bid_volume or not self.spread.ask_volume: + return + # Return if there are any existing orders if not self.check_order_finished(): return @@ -114,7 +117,7 @@ class SpreadTakerAlgo(SpreadAlgoTemplate): # Calculate passive leg target volume and do hedge for leg in self.spread.passive_legs: - passive_traded = self.leg_orders[leg.vt_symbol] + passive_traded = self.leg_traded[leg.vt_symbol] passive_target = self.spread.calculate_leg_volume( leg.vt_symbol, hedge_volume @@ -133,6 +136,6 @@ class SpreadTakerAlgo(SpreadAlgoTemplate): if leg_volume > 0: price = leg_tick.ask_price_1 + leg_contract.pricetick * self.payup self.send_long_order(leg.vt_symbol, price, abs(leg_volume)) - else: + elif leg_volume < 0: price = leg_tick.bid_price_1 - leg_contract.pricetick * self.payup self.send_short_order(leg.vt_symbol, price, abs(leg_volume)) diff --git a/vnpy/app/spread_trading/engine.py b/vnpy/app/spread_trading/engine.py index e12afeb2..a9f1d66e 100644 --- a/vnpy/app/spread_trading/engine.py +++ b/vnpy/app/spread_trading/engine.py @@ -11,15 +11,15 @@ from vnpy.trader.event import ( from vnpy.trader.utility import load_json, save_json from vnpy.trader.object import ( TickData, ContractData, LogData, - SubscribeRequest, OrderRequest, CancelRequest + SubscribeRequest, OrderRequest ) from vnpy.trader.constant import Direction, Offset, OrderType -from vnpy.trader.converter import OffsetConverter, PositionHolding +from vnpy.trader.converter import OffsetConverter from .base import ( LegData, SpreadData, EVENT_SPREAD_DATA, EVENT_SPREAD_ALGO, - EVENT_SPREAD_LOG, EVENT_SPREAD_STRATEGY + EVENT_SPREAD_LOG ) from .template import SpreadAlgoTemplate from .algo import SpreadTakerAlgo @@ -333,7 +333,8 @@ class SpreadAlgoEngine: price: float, volume: float, payup: int, - interval: int + interval: int, + lock: bool ) -> str: # Find spread object spread = self.spreads.get(spread_name, None) @@ -355,7 +356,8 @@ class SpreadAlgoEngine: price, volume, payup, - interval + interval, + lock ) self.algos[algoid] = algo @@ -420,13 +422,13 @@ class SpreadAlgoEngine: offset = Offset.CLOSE original_req = OrderRequest( - contract.symbol, - contract.exchange, - direction, - offset, - OrderType.LIMIT, - price, - volume + symbol=contract.symbol, + exchange=contract.exchange, + direction=direction, + offset=offset, + type=OrderType.LIMIT, + price=price, + volume=volume ) # Convert with offset converter diff --git a/vnpy/app/spread_trading/template.py b/vnpy/app/spread_trading/template.py index 0a0767ec..cef6781e 100644 --- a/vnpy/app/spread_trading/template.py +++ b/vnpy/app/spread_trading/template.py @@ -55,6 +55,8 @@ class SpreadAlgoTemplate: self.leg_traded: Dict[str, float] = defaultdict(int) self.leg_orders: Dict[str, List[str]] = defaultdict(list) + self.write_log("算法已启动") + def is_active(self): """""" if self.status not in [Status.CANCELLED, Status.ALLTRADED]: @@ -105,6 +107,7 @@ class SpreadAlgoTemplate: if self.is_active(): self.cancel_all_order() self.status = Status.CANCELLED + self.write_log("算法已停止") self.put_event() def update_tick(self, tick: TickData): @@ -118,14 +121,25 @@ class SpreadAlgoTemplate: else: self.leg_traded[trade.vt_symbol] -= trade.volume + msg = "委托成交,{},{},{}@{}".format( + trade.vt_symbol, + trade.direction, + trade.volume, + trade.price + ) + self.write_log(msg) + self.calculate_traded() + self.put_event() self.on_trade(trade) def update_order(self, order: OrderData): """""" if not order.is_active(): - self.leg_orders[order.vt_symbol].remove(order.vt_orderid) + vt_orderids = self.leg_orders[order.vt_symbol] + if order.vt_orderid in vt_orderids: + vt_orderids.remove(order.vt_orderid) self.on_order(order) @@ -144,7 +158,7 @@ class SpreadAlgoTemplate: def write_log(self, msg: str): """""" - self.algo_engine.write_algo_log(msg) + self.algo_engine.write_algo_log(self, msg) def send_long_order(self, vt_symbol: str, price: float, volume: float): """""" @@ -173,10 +187,18 @@ class SpreadAlgoTemplate: self.leg_orders[vt_symbol].extend(vt_orderids) + msg = "发出委托,{},{},{}@{}".format( + vt_symbol, + direction, + volume, + price + ) + self.write_log(msg) + def cancel_leg_order(self, vt_symbol: str): """""" for vt_orderid in self.leg_orders[vt_symbol]: - self.algo_engine.cancel_order(vt_orderid) + self.algo_engine.cancel_order(self, vt_orderid) def cancel_all_order(self): """""" @@ -201,8 +223,10 @@ class SpreadAlgoTemplate: else: if adjusted_leg_traded > 0: self.traded = min(self.traded, adjusted_leg_traded) - else: + elif adjusted_leg_traded < 0: self.traded = max(self.traded, adjusted_leg_traded) + else: + self.traded = 0 self.traded_volume = abs(self.traded) diff --git a/vnpy/app/spread_trading/ui/widget.py b/vnpy/app/spread_trading/ui/widget.py index 644bcef7..33ab52c9 100644 --- a/vnpy/app/spread_trading/ui/widget.py +++ b/vnpy/app/spread_trading/ui/widget.py @@ -9,9 +9,8 @@ from vnpy.trader.ui import QtWidgets, QtCore, QtGui from vnpy.trader.ui.widget import ( BaseMonitor, BaseCell, BidCell, AskCell, - TimeCell, MsgCell, - PnlCell, DirectionCell, - EnumCell, + TimeCell, PnlCell, + DirectionCell, EnumCell, ) from ..engine import ( @@ -19,8 +18,7 @@ from ..engine import ( APP_NAME, EVENT_SPREAD_DATA, EVENT_SPREAD_LOG, - EVENT_SPREAD_ALGO, - EVENT_SPREAD_STRATEGY + EVENT_SPREAD_ALGO ) @@ -153,7 +151,7 @@ class SpreadAlgoMonitor(BaseMonitor): headers = { "algoid": {"display": "算法", "cell": BaseCell, "update": False}, "spread_name": {"display": "价差", "cell": BaseCell, "update": False}, - "direction": {"display": "方向", "cell": EnumCell, "update": False}, + "direction": {"display": "方向", "cell": DirectionCell, "update": False}, "price": {"display": "价格", "cell": BaseCell, "update": False}, "payup": {"display": "超价", "cell": BaseCell, "update": False}, "volume": {"display": "数量", "cell": BaseCell, "update": False}, @@ -239,7 +237,7 @@ class SpreadAlgoDialog(QtWidgets.QDialog): form.addRow("数量", self.volume_line) form.addRow("超价", self.payup_line) form.addRow("间隔", self.interval_line) - form.addRow("锁仓", self.lock_line) + form.addRow("锁仓", self.lock_combo) form.addRow(button_start) self.setLayout(form) diff --git a/vnpy/gateway/bitmex/bitmex_gateway.py b/vnpy/gateway/bitmex/bitmex_gateway.py index ca62365f..18de3404 100644 --- a/vnpy/gateway/bitmex/bitmex_gateway.py +++ b/vnpy/gateway/bitmex/bitmex_gateway.py @@ -471,7 +471,10 @@ class BitmexRestApi(RestClient): headers = request.response.headers self.rate_limit_remaining = int(headers["x-ratelimit-remaining"]) - self.rate_limit_sleep = int(headers.get("Retry-After", 0)) + 1 # 1 extra second sleep + + self.rate_limit_sleep = int(headers.get("Retry-After", 0)) + if self.rate_limit_sleep: + self.rate_limit_sleep += 1 # 1 extra second sleep def reset_rate_limit(self): """ diff --git a/vnpy/trader/constant.py b/vnpy/trader/constant.py index 7bce5e10..72aea310 100644 --- a/vnpy/trader/constant.py +++ b/vnpy/trader/constant.py @@ -117,6 +117,7 @@ class Exchange(Enum): BINANCE = "BINANCE" COINBASE = "COINBASE" + class Currency(Enum): """ Currency. diff --git a/vnpy/trader/ui/widget.py b/vnpy/trader/ui/widget.py index 78f860dd..591b0b00 100644 --- a/vnpy/trader/ui/widget.py +++ b/vnpy/trader/ui/widget.py @@ -158,7 +158,7 @@ class TimeCell(BaseCell): """ if content is None: return - + timestamp = content.strftime("%H:%M:%S") millisecond = int(content.microsecond / 1000)