[Add] TurtleSignalStrategy for cta strategy app
This commit is contained in:
parent
fdf2d4cf13
commit
2dc8057de0
@ -1,7 +1,11 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from vnpy.trader.app import BaseApp
|
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 .engine import CtaEngine
|
||||||
from .template import CtaTemplate
|
from .template import CtaTemplate
|
||||||
|
|
||||||
|
@ -118,6 +118,7 @@ class CtaEngine(BaseEngine):
|
|||||||
strategy.pos -= trade.volume
|
strategy.pos -= trade.volume
|
||||||
|
|
||||||
self.call_strategy_func(strategy, strategy.on_trade, trade)
|
self.call_strategy_func(strategy, strategy.on_trade, trade)
|
||||||
|
self.put_strategy_event(strategy)
|
||||||
|
|
||||||
def check_stop_order(self, tick: TickData):
|
def check_stop_order(self, tick: TickData):
|
||||||
""""""
|
""""""
|
||||||
@ -393,7 +394,7 @@ class CtaEngine(BaseEngine):
|
|||||||
Stop a strategy.
|
Stop a strategy.
|
||||||
"""
|
"""
|
||||||
strategy = self.strategies[strategy_name]
|
strategy = self.strategies[strategy_name]
|
||||||
self.call_strategy_func(strategy, strategy.on_start)
|
self.call_strategy_func(strategy, strategy.on_stop)
|
||||||
strategy.trading = False
|
strategy.trading = False
|
||||||
|
|
||||||
self.put_strategy_event(strategy)
|
self.put_strategy_event(strategy)
|
||||||
|
163
vnpy/app/cta_strategy/strategies/turtle_signal_strategy.py
Normal file
163
vnpy/app/cta_strategy/strategies/turtle_signal_strategy.py
Normal file
@ -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)
|
||||||
|
|
@ -99,12 +99,24 @@ class CtaTemplate(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def on_stop(self):
|
||||||
|
"""
|
||||||
|
Callback when strategy is stopped.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def on_tick(self, tick: TickData):
|
def on_tick(self, tick: TickData):
|
||||||
"""
|
"""
|
||||||
Callback of new tick data update.
|
Callback of new tick data update.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def on_bar(self, bar: BarData):
|
||||||
|
"""
|
||||||
|
Callback of new bar data update.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def on_trade(self, trade: TradeData):
|
def on_trade(self, trade: TradeData):
|
||||||
"""
|
"""
|
||||||
Callback of new trade data update.
|
Callback of new trade data update.
|
||||||
@ -123,12 +135,6 @@ class CtaTemplate(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_bar(self, bar: BarData):
|
|
||||||
"""
|
|
||||||
Callback of new bar data update.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def buy(self, price: float, volume: float, stop: bool = False):
|
def buy(self, price: float, volume: float, stop: bool = False):
|
||||||
"""
|
"""
|
||||||
Send buy order to open a long position.
|
Send buy order to open a long position.
|
||||||
|
@ -4,7 +4,7 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import qdarkstyle
|
import qdarkstyle
|
||||||
from PyQt5 import QtGui, QtWidgets
|
from PyQt5 import QtGui, QtWidgets, QtCore
|
||||||
|
|
||||||
from .mainwindow import MainWindow
|
from .mainwindow import MainWindow
|
||||||
from ..setting import SETTINGS
|
from ..setting import SETTINGS
|
||||||
|
@ -104,11 +104,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
# App menu
|
# App menu
|
||||||
all_apps = self.main_engine.get_all_apps()
|
all_apps = self.main_engine.get_all_apps()
|
||||||
for app in all_apps:
|
for app in all_apps:
|
||||||
try:
|
ui_module = import_module(app.app_module + ".ui")
|
||||||
ui_module = import_module(app.app_module + ".ui")
|
widget_class = getattr(ui_module, app.widget_name)
|
||||||
widget_class = getattr(ui_module, app.widget_name)
|
|
||||||
except ImportError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
func = partial(self.open_widget, widget_class, app.app_name)
|
func = partial(self.open_widget, widget_class, app.app_name)
|
||||||
icon_path = str(app.app_path.joinpath("ui", app.icon_name))
|
icon_path = str(app.app_path.joinpath("ui", app.icon_name))
|
||||||
|
Loading…
Reference in New Issue
Block a user