vnpy/vnpy/app/algo_trading/engine.py
2019-11-07 16:08:34 +08:00

283 lines
8.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from vnpy.event import EventEngine, Event
from vnpy.trader.engine import BaseEngine, MainEngine
from vnpy.trader.event import (
EVENT_TICK, EVENT_TIMER, EVENT_ORDER, EVENT_TRADE)
from vnpy.trader.constant import (Direction, Offset, OrderType)
from vnpy.trader.object import (SubscribeRequest, OrderRequest, LogData)
from vnpy.trader.utility import load_json, save_json, round_to
from .template import AlgoTemplate
APP_NAME = "AlgoTrading"
EVENT_ALGO_LOG = "eAlgoLog"
EVENT_ALGO_SETTING = "eAlgoSetting"
EVENT_ALGO_VARIABLES = "eAlgoVariables"
EVENT_ALGO_PARAMETERS = "eAlgoParameters"
class AlgoEngine(BaseEngine):
""""""
setting_filename = "algo_trading_setting.json"
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
"""Constructor"""
super().__init__(main_engine, event_engine, APP_NAME)
self.algos = {}
self.symbol_algo_map = {}
self.orderid_algo_map = {}
self.algo_templates = {}
self.algo_settings = {}
self.load_algo_template()
self.register_event()
def init_engine(self):
""""""
self.write_log("算法交易引擎启动")
self.load_algo_setting()
def load_algo_template(self):
""""""
from .algos.twap_algo import TwapAlgo
from .algos.iceberg_algo import IcebergAlgo
from .algos.sniper_algo import SniperAlgo
from .algos.stop_algo import StopAlgo
from .algos.best_limit_algo import BestLimitAlgo
from .algos.grid_algo import GridAlgo
from .algos.dma_algo import DmaAlgo
from .algos.arbitrage_algo import ArbitrageAlgo
self.add_algo_template(TwapAlgo)
self.add_algo_template(IcebergAlgo)
self.add_algo_template(SniperAlgo)
self.add_algo_template(StopAlgo)
self.add_algo_template(BestLimitAlgo)
self.add_algo_template(GridAlgo)
self.add_algo_template(DmaAlgo)
self.add_algo_template(ArbitrageAlgo)
def add_algo_template(self, template: AlgoTemplate):
""""""
self.algo_templates[template.__name__] = template
def load_algo_setting(self):
""""""
self.algo_settings = load_json(self.setting_filename)
for setting_name, setting in self.algo_settings.items():
self.put_setting_event(setting_name, setting)
self.write_log("算法配置载入成功")
def save_algo_setting(self):
""""""
save_json(self.setting_filename, self.algo_settings)
def register_event(self):
""""""
self.event_engine.register(EVENT_TICK, self.process_tick_event)
self.event_engine.register(EVENT_TIMER, self.process_timer_event)
self.event_engine.register(EVENT_ORDER, self.process_order_event)
self.event_engine.register(EVENT_TRADE, self.process_trade_event)
def process_tick_event(self, event: Event):
""""""
tick = event.data
algos = self.symbol_algo_map.get(tick.vt_symbol, None)
if algos:
for algo in algos:
algo.update_tick(tick)
def process_timer_event(self, event: Event):
""""""
# Generate a list of algos first to avoid dict size change
algos = list(self.algos.values())
for algo in algos:
algo.update_timer()
def process_trade_event(self, event: Event):
""""""
trade = event.data
algo = self.orderid_algo_map.get(trade.vt_orderid, None)
if algo:
algo.update_trade(trade)
def process_order_event(self, event: Event):
""""""
order = event.data
algo = self.orderid_algo_map.get(order.vt_orderid, None)
if algo:
algo.update_order(order)
def start_algo(self, setting: dict):
""""""
template_name = setting["template_name"]
algo_template = self.algo_templates[template_name]
algo = algo_template.new(self, setting)
algo.start()
self.algos[algo.algo_name] = algo
return algo.algo_name
def stop_algo(self, algo_name: str):
""""""
algo = self.algos.get(algo_name, None)
if algo:
algo.stop()
self.algos.pop(algo_name)
def stop_all(self):
""""""
for algo_name in list(self.algos.keys()):
self.stop_algo(algo_name)
def subscribe(self, algo: AlgoTemplate, vt_symbol: str):
""""""
contract = self.main_engine.get_contract(vt_symbol)
if not contract:
self.write_log(f'订阅行情失败,找不到合约:{vt_symbol}', algo)
return
algos = self.symbol_algo_map.setdefault(vt_symbol, set())
if not algos:
req = SubscribeRequest(
symbol=contract.symbol,
exchange=contract.exchange
)
self.main_engine.subscribe(req, contract.gateway_name)
algos.add(algo)
def send_order(
self,
algo: AlgoTemplate,
vt_symbol: str,
direction: Direction,
price: float,
volume: float,
order_type: OrderType,
offset: Offset
):
""""""
contract = self.main_engine.get_contract(vt_symbol)
if not contract:
self.write_log(f'委托下单失败,找不到合约:{vt_symbol}', algo)
return
volume = round_to(volume, contract.min_volume)
if not volume:
return ""
req = OrderRequest(
symbol=contract.symbol,
exchange=contract.exchange,
direction=direction,
type=order_type,
volume=volume,
price=price,
offset=offset
)
vt_orderid = self.main_engine.send_order(req, contract.gateway_name)
self.orderid_algo_map[vt_orderid] = algo
return vt_orderid
def cancel_order(self, algo: AlgoTemplate, vt_orderid: str):
""""""
order = self.main_engine.get_order(vt_orderid)
if not order:
self.write_log(f"委托撤单失败,找不到委托:{vt_orderid}", algo)
return
req = order.create_cancel_request()
self.main_engine.cancel_order(req, order.gateway_name)
def get_tick(self, algo: AlgoTemplate, vt_symbol: str):
""""""
tick = self.main_engine.get_tick(vt_symbol)
if not tick:
self.write_log(f"查询行情失败,找不到行情:{vt_symbol}", algo)
return tick
def get_contract(self, algo: AlgoTemplate, vt_symbol: str):
""""""
contract = self.main_engine.get_contract(vt_symbol)
if not contract:
self.write_log(f"查询合约失败,找不到合约:{vt_symbol}", algo)
return contract
def write_log(self, msg: str, algo: AlgoTemplate = None):
""""""
if algo:
msg = f"{algo.algo_name}{msg}"
log = LogData(msg=msg, gateway_name=APP_NAME)
event = Event(EVENT_ALGO_LOG, data=log)
self.event_engine.put(event)
def put_setting_event(self, setting_name: str, setting: dict):
""""""
event = Event(EVENT_ALGO_SETTING)
event.data = {
"setting_name": setting_name,
"setting": setting
}
self.event_engine.put(event)
def update_algo_setting(self, setting_name: str, setting: dict):
""""""
self.algo_settings[setting_name] = setting
self.save_algo_setting()
self.put_setting_event(setting_name, setting)
def remove_algo_setting(self, setting_name: str):
""""""
if setting_name not in self.algo_settings:
return
self.algo_settings.pop(setting_name)
event = Event(EVENT_ALGO_SETTING)
event.data = {
"setting_name": setting_name,
"setting": None
}
self.event_engine.put(event)
self.save_algo_setting()
def put_parameters_event(self, algo: AlgoTemplate, parameters: dict):
""""""
event = Event(EVENT_ALGO_PARAMETERS)
event.data = {
"algo_name": algo.algo_name,
"parameters": parameters
}
self.event_engine.put(event)
def put_variables_event(self, algo: AlgoTemplate, variables: dict):
""""""
event = Event(EVENT_ALGO_VARIABLES)
event.data = {
"algo_name": algo.algo_name,
"variables": variables
}
self.event_engine.put(event)