[Mod] complete test of algo trading function
This commit is contained in:
parent
be9142e878
commit
80c9dfe378
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -117,6 +117,7 @@ class Exchange(Enum):
|
|||||||
BINANCE = "BINANCE"
|
BINANCE = "BINANCE"
|
||||||
COINBASE = "COINBASE"
|
COINBASE = "COINBASE"
|
||||||
|
|
||||||
|
|
||||||
class Currency(Enum):
|
class Currency(Enum):
|
||||||
"""
|
"""
|
||||||
Currency.
|
Currency.
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user