[Mod] complete test of algo trading function

This commit is contained in:
vn.py 2019-09-16 16:42:16 +08:00
parent be9142e878
commit 80c9dfe378
7 changed files with 59 additions and 28 deletions

View File

@ -1,5 +1,4 @@
from typing import Any from typing import Any
from math import floor, ceil
from vnpy.trader.constant import Direction from vnpy.trader.constant import Direction
from vnpy.trader.object import (TickData, OrderData, TradeData) from vnpy.trader.object import (TickData, OrderData, TradeData)
@ -35,6 +34,10 @@ class SpreadTakerAlgo(SpreadAlgoTemplate):
def on_tick(self, tick: TickData): 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 # Return if there are any existing orders
if not self.check_order_finished(): if not self.check_order_finished():
return return
@ -114,7 +117,7 @@ class SpreadTakerAlgo(SpreadAlgoTemplate):
# Calculate passive leg target volume and do hedge # Calculate passive leg target volume and do hedge
for leg in self.spread.passive_legs: 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( passive_target = self.spread.calculate_leg_volume(
leg.vt_symbol, leg.vt_symbol,
hedge_volume hedge_volume
@ -133,6 +136,6 @@ class SpreadTakerAlgo(SpreadAlgoTemplate):
if leg_volume > 0: if leg_volume > 0:
price = leg_tick.ask_price_1 + leg_contract.pricetick * self.payup price = leg_tick.ask_price_1 + leg_contract.pricetick * self.payup
self.send_long_order(leg.vt_symbol, price, abs(leg_volume)) 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 price = leg_tick.bid_price_1 - leg_contract.pricetick * self.payup
self.send_short_order(leg.vt_symbol, price, abs(leg_volume)) self.send_short_order(leg.vt_symbol, price, abs(leg_volume))

View File

@ -11,15 +11,15 @@ from vnpy.trader.event import (
from vnpy.trader.utility import load_json, save_json from vnpy.trader.utility import load_json, save_json
from vnpy.trader.object import ( from vnpy.trader.object import (
TickData, ContractData, LogData, TickData, ContractData, LogData,
SubscribeRequest, OrderRequest, CancelRequest SubscribeRequest, OrderRequest
) )
from vnpy.trader.constant import Direction, Offset, OrderType from vnpy.trader.constant import Direction, Offset, OrderType
from vnpy.trader.converter import OffsetConverter, PositionHolding from vnpy.trader.converter import OffsetConverter
from .base import ( from .base import (
LegData, SpreadData, LegData, SpreadData,
EVENT_SPREAD_DATA, EVENT_SPREAD_ALGO, EVENT_SPREAD_DATA, EVENT_SPREAD_ALGO,
EVENT_SPREAD_LOG, EVENT_SPREAD_STRATEGY EVENT_SPREAD_LOG
) )
from .template import SpreadAlgoTemplate from .template import SpreadAlgoTemplate
from .algo import SpreadTakerAlgo from .algo import SpreadTakerAlgo
@ -333,7 +333,8 @@ class SpreadAlgoEngine:
price: float, price: float,
volume: float, volume: float,
payup: int, payup: int,
interval: int interval: int,
lock: bool
) -> str: ) -> str:
# Find spread object # Find spread object
spread = self.spreads.get(spread_name, None) spread = self.spreads.get(spread_name, None)
@ -355,7 +356,8 @@ class SpreadAlgoEngine:
price, price,
volume, volume,
payup, payup,
interval interval,
lock
) )
self.algos[algoid] = algo self.algos[algoid] = algo
@ -420,13 +422,13 @@ class SpreadAlgoEngine:
offset = Offset.CLOSE offset = Offset.CLOSE
original_req = OrderRequest( original_req = OrderRequest(
contract.symbol, symbol=contract.symbol,
contract.exchange, exchange=contract.exchange,
direction, direction=direction,
offset, offset=offset,
OrderType.LIMIT, type=OrderType.LIMIT,
price, price=price,
volume volume=volume
) )
# Convert with offset converter # Convert with offset converter

View File

@ -55,6 +55,8 @@ class SpreadAlgoTemplate:
self.leg_traded: Dict[str, float] = defaultdict(int) self.leg_traded: Dict[str, float] = defaultdict(int)
self.leg_orders: Dict[str, List[str]] = defaultdict(list) self.leg_orders: Dict[str, List[str]] = defaultdict(list)
self.write_log("算法已启动")
def is_active(self): def is_active(self):
"""""" """"""
if self.status not in [Status.CANCELLED, Status.ALLTRADED]: if self.status not in [Status.CANCELLED, Status.ALLTRADED]:
@ -105,6 +107,7 @@ class SpreadAlgoTemplate:
if self.is_active(): if self.is_active():
self.cancel_all_order() self.cancel_all_order()
self.status = Status.CANCELLED self.status = Status.CANCELLED
self.write_log("算法已停止")
self.put_event() self.put_event()
def update_tick(self, tick: TickData): def update_tick(self, tick: TickData):
@ -118,14 +121,25 @@ class SpreadAlgoTemplate:
else: else:
self.leg_traded[trade.vt_symbol] -= trade.volume 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.calculate_traded()
self.put_event()
self.on_trade(trade) self.on_trade(trade)
def update_order(self, order: OrderData): def update_order(self, order: OrderData):
"""""" """"""
if not order.is_active(): 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) self.on_order(order)
@ -144,7 +158,7 @@ class SpreadAlgoTemplate:
def write_log(self, msg: str): 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): 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) 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): def cancel_leg_order(self, vt_symbol: str):
"""""" """"""
for vt_orderid in self.leg_orders[vt_symbol]: 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): def cancel_all_order(self):
"""""" """"""
@ -201,8 +223,10 @@ class SpreadAlgoTemplate:
else: else:
if adjusted_leg_traded > 0: if adjusted_leg_traded > 0:
self.traded = min(self.traded, adjusted_leg_traded) self.traded = min(self.traded, adjusted_leg_traded)
else: elif adjusted_leg_traded < 0:
self.traded = max(self.traded, adjusted_leg_traded) self.traded = max(self.traded, adjusted_leg_traded)
else:
self.traded = 0
self.traded_volume = abs(self.traded) self.traded_volume = abs(self.traded)

View File

@ -9,9 +9,8 @@ from vnpy.trader.ui import QtWidgets, QtCore, QtGui
from vnpy.trader.ui.widget import ( from vnpy.trader.ui.widget import (
BaseMonitor, BaseCell, BaseMonitor, BaseCell,
BidCell, AskCell, BidCell, AskCell,
TimeCell, MsgCell, TimeCell, PnlCell,
PnlCell, DirectionCell, DirectionCell, EnumCell,
EnumCell,
) )
from ..engine import ( from ..engine import (
@ -19,8 +18,7 @@ from ..engine import (
APP_NAME, APP_NAME,
EVENT_SPREAD_DATA, EVENT_SPREAD_DATA,
EVENT_SPREAD_LOG, EVENT_SPREAD_LOG,
EVENT_SPREAD_ALGO, EVENT_SPREAD_ALGO
EVENT_SPREAD_STRATEGY
) )
@ -153,7 +151,7 @@ class SpreadAlgoMonitor(BaseMonitor):
headers = { headers = {
"algoid": {"display": "算法", "cell": BaseCell, "update": False}, "algoid": {"display": "算法", "cell": BaseCell, "update": False},
"spread_name": {"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}, "price": {"display": "价格", "cell": BaseCell, "update": False},
"payup": {"display": "超价", "cell": BaseCell, "update": False}, "payup": {"display": "超价", "cell": BaseCell, "update": False},
"volume": {"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.volume_line)
form.addRow("超价", self.payup_line) form.addRow("超价", self.payup_line)
form.addRow("间隔", self.interval_line) form.addRow("间隔", self.interval_line)
form.addRow("锁仓", self.lock_line) form.addRow("锁仓", self.lock_combo)
form.addRow(button_start) form.addRow(button_start)
self.setLayout(form) self.setLayout(form)

View File

@ -471,7 +471,10 @@ class BitmexRestApi(RestClient):
headers = request.response.headers headers = request.response.headers
self.rate_limit_remaining = int(headers["x-ratelimit-remaining"]) 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): def reset_rate_limit(self):
""" """

View File

@ -117,6 +117,7 @@ class Exchange(Enum):
BINANCE = "BINANCE" BINANCE = "BINANCE"
COINBASE = "COINBASE" COINBASE = "COINBASE"
class Currency(Enum): class Currency(Enum):
""" """
Currency. Currency.

View File

@ -158,7 +158,7 @@ class TimeCell(BaseCell):
""" """
if content is None: if content is None:
return return
timestamp = content.strftime("%H:%M:%S") timestamp = content.strftime("%H:%M:%S")
millisecond = int(content.microsecond / 1000) millisecond = int(content.microsecond / 1000)