From 4b1cd4d602f4a02b604d7a521f85b1384ab33293 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sun, 30 Jun 2019 23:39:02 +0800 Subject: [PATCH 1/3] [Mod] change working path when MainEngine created --- vnpy/trader/engine.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vnpy/trader/engine.py b/vnpy/trader/engine.py index 3aa882b0..79fa1634 100644 --- a/vnpy/trader/engine.py +++ b/vnpy/trader/engine.py @@ -3,6 +3,7 @@ import logging import smtplib +import os from abc import ABC from datetime import datetime from email.message import EmailMessage @@ -30,7 +31,7 @@ from .object import ( HistoryRequest ) from .setting import SETTINGS -from .utility import get_folder_path +from .utility import get_folder_path, TRADER_DIR class MainEngine: @@ -51,7 +52,8 @@ class MainEngine: self.apps = {} self.exchanges = [] - self.init_engines() + os.chdir(TRADER_DIR) # Change working directory + self.init_engines() # Initialize function engines def add_engine(self, engine_class: Any): """ From c7171fc3123ddb6d7fe51538b6f1d5ce09763825 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sun, 30 Jun 2019 23:39:39 +0800 Subject: [PATCH 2/3] [Add] ScriptTrader for running script strategies --- examples/vn_trader/run.py | 10 +- vnpy/app/script_trader/__init__.py | 14 ++ vnpy/app/script_trader/engine.py | 262 ++++++++++++++++++++++++++ vnpy/app/script_trader/ui/__init__.py | 1 + vnpy/app/script_trader/ui/script.ico | Bin 0 -> 59966 bytes vnpy/app/script_trader/ui/widget.py | 97 ++++++++++ 6 files changed, 380 insertions(+), 4 deletions(-) create mode 100644 vnpy/app/script_trader/__init__.py create mode 100644 vnpy/app/script_trader/engine.py create mode 100644 vnpy/app/script_trader/ui/__init__.py create mode 100644 vnpy/app/script_trader/ui/script.ico create mode 100644 vnpy/app/script_trader/ui/widget.py diff --git a/examples/vn_trader/run.py b/examples/vn_trader/run.py index 5dcbe65d..187b5abf 100644 --- a/examples/vn_trader/run.py +++ b/examples/vn_trader/run.py @@ -5,9 +5,9 @@ from vnpy.trader.engine import MainEngine from vnpy.trader.ui import MainWindow, create_qapp # from vnpy.gateway.binance import BinanceGateway -# from vnpy.gateway.bitmex import BitmexGateway +from vnpy.gateway.bitmex import BitmexGateway # from vnpy.gateway.futu import FutuGateway -from vnpy.gateway.ib import IbGateway +# from vnpy.gateway.ib import IbGateway # from vnpy.gateway.ctp import CtpGateway # from vnpy.gateway.ctptest import CtptestGateway # from vnpy.gateway.femas import FemasGateway @@ -30,6 +30,7 @@ from vnpy.app.cta_strategy import CtaStrategyApp from vnpy.app.cta_backtester import CtaBacktesterApp # from vnpy.app.data_recorder import DataRecorderApp # from vnpy.app.risk_manager import RiskManagerApp +from vnpy.app.script_trader import ScriptTraderApp def main(): @@ -44,9 +45,9 @@ def main(): # main_engine.add_gateway(CtpGateway) # main_engine.add_gateway(CtptestGateway) # main_engine.add_gateway(FemasGateway) - main_engine.add_gateway(IbGateway) + # main_engine.add_gateway(IbGateway) # main_engine.add_gateway(FutuGateway) - # main_engine.add_gateway(BitmexGateway) + main_engine.add_gateway(BitmexGateway) # main_engine.add_gateway(TigerGateway) # main_engine.add_gateway(OesGateway) # main_engine.add_gateway(OkexGateway) @@ -66,6 +67,7 @@ def main(): # main_engine.add_app(AlgoTradingApp) # main_engine.add_app(DataRecorderApp) # main_engine.add_app(RiskManagerApp) + main_engine.add_app(ScriptTraderApp) main_window = MainWindow(main_engine, event_engine) main_window.showMaximized() diff --git a/vnpy/app/script_trader/__init__.py b/vnpy/app/script_trader/__init__.py new file mode 100644 index 00000000..c54b69f8 --- /dev/null +++ b/vnpy/app/script_trader/__init__.py @@ -0,0 +1,14 @@ +from pathlib import Path +from vnpy.trader.app import BaseApp +from .engine import ScriptEngine, APP_NAME + + +class ScriptTraderApp(BaseApp): + """""" + app_name = APP_NAME + app_module = __module__ + app_path = Path(__file__).parent + display_name = "脚本策略" + engine_class = ScriptEngine + widget_name = "ScriptManager" + icon_name = "script.ico" diff --git a/vnpy/app/script_trader/engine.py b/vnpy/app/script_trader/engine.py new file mode 100644 index 00000000..45642c24 --- /dev/null +++ b/vnpy/app/script_trader/engine.py @@ -0,0 +1,262 @@ +"""""" + +import sys +import importlib +import traceback +from typing import Sequence +from pathlib import Path +from datetime import datetime +from threading import Thread + +from vnpy.event import Event, EventEngine +from vnpy.trader.engine import BaseEngine, MainEngine +from vnpy.trader.constant import Direction, Offset, OrderType, Interval +from vnpy.trader.object import ( + OrderRequest, + HistoryRequest, + SubscribeRequest, + TickData, + OrderData, + TradeData, + PositionData, + AccountData, + ContractData, + LogData, + BarData +) +from vnpy.trader.rqdata import rqdata_client + + +APP_NAME = "ScriptTrader" + +EVENT_SCRIPT_LOG = "eScriptLog" + + +class ScriptEngine(BaseEngine): + """""" + setting_filename = "script_trader_setting.json" + + def __init__(self, main_engine: MainEngine, event_engine: EventEngine): + """""" + super().__init__(main_engine, event_engine, APP_NAME) + + self.main_engine = main_engine + self.event_engine = event_engine + + self.get_tick = main_engine.get_tick + self.get_order = main_engine.get_order + self.get_trade = main_engine.get_trade + self.get_position = main_engine.get_position + self.get_account = main_engine.get_account + self.get_contract = main_engine.get_contract + self.get_all_ticks = main_engine.get_all_ticks + self.get_all_orders = main_engine.get_all_orders + self.get_all_trades = main_engine.get_all_trades + self.get_all_positions = main_engine.get_all_positions + self.get_all_accounts = main_engine.get_all_accounts + self.get_all_contracts = main_engine.get_all_contracts + self.get_all_active_orders = main_engine.get_all_active_orders + + self.strategy_active = False + self.strategy_thread = None + + def init(self): + """ + Start script engine. + """ + result = rqdata_client.init() + if result: + self.write_log("RQData数据接口初始化成功") + + def start_strategy(self, script_path: str): + """""" + if self.strategy_active: + return + self.strategy_active = True + + self.strategy_thread = Thread( + target=self.run_strategy, args=(script_path,)) + self.strategy_thread.start() + + self.write_log("策略交易脚本启动") + + def run_strategy(self, script_path: str): + """""" + path = Path(script_path) + sys.path.append(str(path.parent)) + + script_name = path.parts[-1] + module_name = script_name.replace(".py", "") + + try: + module = importlib.import_module(module_name) + importlib.reload(module) + module.run(self) + except: # noqa + msg = f"触发异常已停止\n{traceback.format_exc()}" + self.write_log(msg) + + def stop_strategy(self): + """""" + if not self.strategy_active: + return + self.strategy_active = False + + if self.strategy_thread: + self.strategy_thread.join() + self.strategy_thread = None + + self.write_log("策略交易脚本停止") + + def send_order( + self, + vt_symbol: str, + price: float, + volume: float, + direction: Direction, + offset: Offset, + order_type: OrderType + ) -> str: + """""" + contract = self.get_contract(vt_symbol) + if not contract: + return "" + + req = OrderRequest( + symbol=contract.symbol, + exchange=contract.exchange, + type=order_type, + volume=volume, + price=price, + offset=offset + ) + + vt_orderid = self.main_engine.send_order(req, contract.gateway_name) + return vt_orderid + + def subscribe(self, vt_symbols): + """""" + for vt_symbol in vt_symbols: + contract = self.main_engine.get_contract(vt_symbol) + if contract: + req = SubscribeRequest( + symbol=contract.symbol, + exchange=contract.exchange + ) + self.main_engine.subscribe(req, contract.gateway_name) + + def buy(self, vt_symbol: str, price: str, volume: str, order_type: OrderType = OrderType.LIMIT) -> str: + """""" + return self.send_order(vt_symbol, price, volume, Direction.LONG, Offset.OPEN, order_type) + + def sell(self, vt_symbol: str, price: str, volume: str, order_type: OrderType = OrderType.LIMIT) -> str: + """""" + return self.send_order(vt_symbol, price, volume, Direction.SHORT, Offset.CLOSE, order_type) + + def short(self, vt_symbol: str, price: str, volume: str, order_type: OrderType = OrderType.LIMIT) -> str: + """""" + return self.send_order(vt_symbol, price, volume, Direction.SHORT, Offset.OPEN, order_type) + + def cover(self, vt_symbol: str, price: str, volume: str, order_type: OrderType = OrderType.LIMIT) -> str: + """""" + return self.send_order(vt_symbol, price, volume, Direction.LONG, Offset.CLOSE, order_type) + + def cancel_order(self, vt_orderid: str) -> None: + """""" + order = self.get_order(vt_orderid) + if not order: + return + + req = order.create_cancel_request() + self.main_engine.cancel_order(req, order.gateway_name) + + def get_tick(self, vt_symbol: str) -> TickData: + """""" + return self.main_engine.get_tick(vt_symbol) + + def get_ticks(self, vt_symbols: Sequence[str]) -> Sequence[TickData]: + """""" + ticks = [] + for vt_symbol in vt_symbols: + tick = self.main_engine.get_tick(vt_symbol) + ticks.append(tick) + return ticks + + def get_order(self, vt_orderid: str) -> OrderData: + """""" + return self.main_engine.get_order(vt_orderid) + + def get_orders(self, vt_orderids: Sequence[str]) -> Sequence[OrderData]: + """""" + orders = [] + for vt_orderid in vt_orderids: + order = self.main_engine.get_order(vt_orderid) + orders.append(order) + return orders + + def get_trades(self, vt_orderid: str) -> Sequence[TradeData]: + """""" + trades = [] + all_trades = self.main_engine.get_all_trades() + + for trade in all_trades: + if trade.vt_orderid == vt_orderid: + trades.append(trade) + + return trades + + def get_all_active_orders(self) -> Sequence[OrderData]: + """""" + return self.main_engine.get_all_active_orders() + + def get_contract(self, vt_symbol) -> ContractData: + """""" + return self.main_engine.get_contract(vt_symbol) + + def get_all_contracts(self) -> Sequence[ContractData]: + """""" + return self.main_engine.get_all_contracts() + + def get_account(self, vt_accountid: str) -> AccountData: + """""" + return self.main_engine.get_account(vt_accountid) + + def get_all_accounts(self) -> Sequence[AccountData]: + """""" + return self.main_engine.get_all_accounts() + + def get_position(self, vt_positionid: str) -> PositionData: + """""" + return self.main_engine.get_position(vt_positionid) + + def get_all_positions(self) -> Sequence[AccountData]: + """""" + return self.main_engine.get_all_positions() + + def get_bars(self, vt_symbol: str, start_date: str, interval: Interval) -> Sequence[BarData]: + """""" + contract = self.main_engine.get_contract(vt_symbol) + if not contract: + return [] + + start = datetime.strptime(start_date, "%Y%m%d") + + req = HistoryRequest( + symbol=contract.symbol, + exchange=contract.exchange, + start=start, + interval=interval + ) + + bars = rqdata_client.query_history(req) + if not bars: + return [] + return bars + + def write_log(self, msg: str) -> None: + """""" + log = LogData(msg=msg, gateway_name=APP_NAME) + print(f"{log.time}\t{log.msg}") + + event = Event(EVENT_SCRIPT_LOG, log) + self.event_engine.put(event) diff --git a/vnpy/app/script_trader/ui/__init__.py b/vnpy/app/script_trader/ui/__init__.py new file mode 100644 index 00000000..53442534 --- /dev/null +++ b/vnpy/app/script_trader/ui/__init__.py @@ -0,0 +1 @@ +from .widget import ScriptManager diff --git a/vnpy/app/script_trader/ui/script.ico b/vnpy/app/script_trader/ui/script.ico new file mode 100644 index 0000000000000000000000000000000000000000..06fc921ff79e5b87315bef9dd914a4c57bf16875 GIT binary patch literal 59966 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 Date: Sun, 30 Jun 2019 23:41:15 +0800 Subject: [PATCH 3/3] [Mod] flake8 code quality improve --- vnpy/gateway/onetoken/onetoken_gateway.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vnpy/gateway/onetoken/onetoken_gateway.py b/vnpy/gateway/onetoken/onetoken_gateway.py index e140c37f..e6af5faa 100644 --- a/vnpy/gateway/onetoken/onetoken_gateway.py +++ b/vnpy/gateway/onetoken/onetoken_gateway.py @@ -619,7 +619,7 @@ class OnetokenTradeWebsocketApi(WebsocketClient): elif _type == "future": long_position = PositionData( symbol=account_data["contract"], - exchange=Exchange(self.exchange.upper()), + exchange=Exchange(self.exchange.upper()), direction=Direction.LONG, price=account_data["average_open_price_long"], volume=account_data["total_amount_long"], @@ -629,7 +629,7 @@ class OnetokenTradeWebsocketApi(WebsocketClient): ) short_position = PositionData( symbol=account_data["contract"], - exchange=Exchange(self.exchange.upper()), + exchange=Exchange(self.exchange.upper()), direction=Direction.SHORT, price=account_data["average_open_price_short"], volume=account_data["total_amount_short"], @@ -661,7 +661,7 @@ class OnetokenTradeWebsocketApi(WebsocketClient): gateway_name=self.gateway_name ) - if order_data["status"] in ("withdrawn","part-deal-withdrawn"): + if order_data["status"] in ("withdrawn", "part-deal-withdrawn"): order.status = Status.CANCELLED else: if order.traded == order.volume: