[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 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))

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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):
"""

View File

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

View File

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