From 2dc8057de0e4442c6743a11699ffa39fcd365fb2 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sat, 26 Jan 2019 21:43:07 +0800 Subject: [PATCH] [Add] TurtleSignalStrategy for cta strategy app --- vnpy/app/cta_strategy/__init__.py | 6 +- vnpy/app/cta_strategy/engine.py | 3 +- .../strategies/turtle_signal_strategy.py | 163 ++++++++++++++++++ vnpy/app/cta_strategy/template.py | 18 +- vnpy/trader/ui/__init__.py | 2 +- vnpy/trader/ui/mainwindow.py | 7 +- 6 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 vnpy/app/cta_strategy/strategies/turtle_signal_strategy.py diff --git a/vnpy/app/cta_strategy/__init__.py b/vnpy/app/cta_strategy/__init__.py index 0b4da2ca..943b0ff5 100644 --- a/vnpy/app/cta_strategy/__init__.py +++ b/vnpy/app/cta_strategy/__init__.py @@ -1,7 +1,11 @@ from pathlib import Path from vnpy.trader.app import BaseApp -from .base import APP_NAME +from vnpy.trader.constant import Direction +from vnpy.trader.object import TickData, BarData, TradeData, OrderData +from vnpy.trader.utility import BarGenerator, ArrayManager + +from .base import APP_NAME, StopOrder from .engine import CtaEngine from .template import CtaTemplate diff --git a/vnpy/app/cta_strategy/engine.py b/vnpy/app/cta_strategy/engine.py index 2ab5664e..90f3f332 100644 --- a/vnpy/app/cta_strategy/engine.py +++ b/vnpy/app/cta_strategy/engine.py @@ -118,6 +118,7 @@ class CtaEngine(BaseEngine): strategy.pos -= trade.volume self.call_strategy_func(strategy, strategy.on_trade, trade) + self.put_strategy_event(strategy) def check_stop_order(self, tick: TickData): """""" @@ -393,7 +394,7 @@ class CtaEngine(BaseEngine): Stop a strategy. """ strategy = self.strategies[strategy_name] - self.call_strategy_func(strategy, strategy.on_start) + self.call_strategy_func(strategy, strategy.on_stop) strategy.trading = False self.put_strategy_event(strategy) diff --git a/vnpy/app/cta_strategy/strategies/turtle_signal_strategy.py b/vnpy/app/cta_strategy/strategies/turtle_signal_strategy.py new file mode 100644 index 00000000..b5a1044f --- /dev/null +++ b/vnpy/app/cta_strategy/strategies/turtle_signal_strategy.py @@ -0,0 +1,163 @@ +from vnpy.app.cta_strategy import ( + CtaTemplate, + StopOrder, + Direction, + TickData, + BarData, + TradeData, + OrderData, + StopOrder, + BarGenerator, + ArrayManager, +) + + +class TurtleSignalStrategy(CtaTemplate): + """""" + + author = "用Python的交易员" + + entry_window = 20 + exit_window = 10 + atr_window = 20 + fixed_size = 1 + + entry_up = 0 + entry_down = 0 + exit_up = 0 + exit_down = 0 + atr_value = 0 + + long_entry = 0 + short_entry = 0 + long_stop = 0 + short_stop = 0 + + parameters = ["entry_window", "exit_window", "atr_window", "fixed_size"] + variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"] + + def __init__(self, cta_engine, strategy_name, vt_symbol, setting): + """""" + super(DoubleMaStrategy, self).__init__( + cta_engine, strategy_name, vt_symbol, setting + ) + + self.bg = BarGenerator(self.on_bar) + self.am = ArrayManager() + + def on_init(self): + """ + Callback when strategy is inited. + """ + self.write_log("策略初始化") + + def on_start(self): + """ + Callback when strategy is started. + """ + self.write_log("策略启动") + + def on_stop(self): + """ + Callback when strategy is stopped. + """ + self.write_log("策略停止") + + def on_tick(self, tick: TickData): + """ + Callback of new tick data update. + """ + self.bg.update_tick(tick) + + def on_bar(self, bar: BarData): + """ + Callback of new bar data update. + """ + self.cancel_all() + + self.am.update_bar(bar) + if not self.am.inited: + return + + self.entry_up, self.entry_down = self.am.donchian(self.entry_window) + self.exit_up, self.exit_down = self.am.donchian(self.exit_window) + + if not self.pos: + self.atr_value = self.am.atr(self.atr_value) + + self.long_entry = 0 + self.short_entry = 0 + self.long_stop = 0 + self.short_stop = 0 + + self.send_buy_orders(self.long_entry) + self.send_short_orders(self.short_entry) + elif self.pos < 0: + self.send_buy_orders(self.long_entry) + + sell_price = max(self.long_stop, self.exit_down) + self.sell(sell_price, abs(self.pos), True) + + elif self.pos > 0: + self.send_short_orders(self.short_entry) + + cover_price = min(self.short_stop, self.exit_up) + self.cover(cover_price, abs(self.pos), True) + + self.put_event() + + def on_trade(self, trade: TradeData): + """ + Callback of new trade data update. + """ + if trade.dierction == Direction.LONG: + self.long_entry = trade.price + self.long_stop = self.long_entry - 2 * self.atr_value + else: + self.short_entry = trade.price + self.short_stop = self.short_entry + 2 * self.atr_value + + def on_order(self, order: OrderData): + """ + Callback of new order data update. + """ + pass + + def on_stop_order(self, stop_order: StopOrder): + """ + Callback of stop order update. + """ + pass + + def send_buy_orders(self, price): + """""" + t = self.pos / self.fixed_size + + if t < 1: + self.buy(price, self.fixed_size, True) + + if t < 2: + self.buy(price + self.atr_value * 0.5, self.fixed_size, True) + + if t < 3: + self.buy(price + self.atr_value, self.fixed_size, True) + + if t < 4: + self.buy(price + self.atr_value * 1.5, self.fixed_size, True) + + def send_short_orders(self, price): + """""" + t = self.pos / self.fixed_size + + if t > -1: + self.short(price, self.fixed_size, True) + + if t > -2: + self.short(price - self.atr_value * 0.5, self.fixed_size, True) + + if t > -3: + self.short(price - self.atr_value, self.fixed_size, True) + + if t > -4: + self.short(price - self.atr_value * 1.5, self.fixed_size, True) + diff --git a/vnpy/app/cta_strategy/template.py b/vnpy/app/cta_strategy/template.py index 46f93eca..c6dda25b 100644 --- a/vnpy/app/cta_strategy/template.py +++ b/vnpy/app/cta_strategy/template.py @@ -99,12 +99,24 @@ class CtaTemplate(ABC): """ pass + def on_stop(self): + """ + Callback when strategy is stopped. + """ + pass + def on_tick(self, tick: TickData): """ Callback of new tick data update. """ pass + def on_bar(self, bar: BarData): + """ + Callback of new bar data update. + """ + pass + def on_trade(self, trade: TradeData): """ Callback of new trade data update. @@ -123,12 +135,6 @@ class CtaTemplate(ABC): """ pass - def on_bar(self, bar: BarData): - """ - Callback of new bar data update. - """ - pass - def buy(self, price: float, volume: float, stop: bool = False): """ Send buy order to open a long position. diff --git a/vnpy/trader/ui/__init__.py b/vnpy/trader/ui/__init__.py index a5e988c8..e88065ae 100644 --- a/vnpy/trader/ui/__init__.py +++ b/vnpy/trader/ui/__init__.py @@ -4,7 +4,7 @@ import sys import traceback import qdarkstyle -from PyQt5 import QtGui, QtWidgets +from PyQt5 import QtGui, QtWidgets, QtCore from .mainwindow import MainWindow from ..setting import SETTINGS diff --git a/vnpy/trader/ui/mainwindow.py b/vnpy/trader/ui/mainwindow.py index bafc4411..ae93c5f3 100644 --- a/vnpy/trader/ui/mainwindow.py +++ b/vnpy/trader/ui/mainwindow.py @@ -104,11 +104,8 @@ class MainWindow(QtWidgets.QMainWindow): # App menu all_apps = self.main_engine.get_all_apps() for app in all_apps: - try: - ui_module = import_module(app.app_module + ".ui") - widget_class = getattr(ui_module, app.widget_name) - except ImportError: - continue + ui_module = import_module(app.app_module + ".ui") + widget_class = getattr(ui_module, app.widget_name) func = partial(self.open_widget, widget_class, app.app_name) icon_path = str(app.app_path.joinpath("ui", app.icon_name))