海龟策略深入研究-策略回测系列-7 海龟策略要素代码解析

海龟策略7大要素分别是品种选择、头寸规模、单位头寸限制、入场信号、逐步建仓、止损、止盈。由于品种选择无法通过不属于交易策略内容,故只对后面5大要素的进行代码解析。
 

1.头寸规模


头寸规模=(1%账户资金)/(ATR 合约规模),其代码如下

class TurtlePortfolio(object):
......
    #----------------------------------------------------------------------
    def newSignal(self, signal, direction, offset, price, volume):
......
            riskValue = self.portfolioValue * 0.01
            multiplier = riskValue / (signal.atrVolatility * size)
            multiplier = int(round(multiplier, 0))   # multiplier即为头寸规模
            self.multiplierDict[signal.vtSymbol] = multiplier
......
    #----------------------------------------------------------------------
    def sendOrder(self, vtSymbol, direction, offset, price, volume, multiplier):
        """"""
        # 计算合约持仓
        if direction == DIRECTION_LONG:
            self.unitDict[vtSymbol] += volume         # volume即为单位头寸
            self.posDict[vtSymbol] += volume * multiplier
        else:
            self.unitDict[vtSymbol] -= volume
            self.posDict[vtSymbol] -= volume * multiplier  # 实际持仓=单位头寸 * 头寸规模

 
 

2.单位头寸限制


原版海龟策略规定了4个维度的单位头寸限制,分别是

  • 单个市场:头寸上限是4个
  • 高度关联的多个市场:单个方向头寸单位不超过6个
  • 松散关联的多个市场:某一个方向上的头寸单位不超过10个
  • 单个方向:最多12个
     

基于高度关联市场和松散关联市场判断起来都非常主观,并无统一标准。在客观上的层面只能实现单个市场和单个方向的头寸限制。
在开仓交易前,需要检查上一笔交易是否盈利,若是盈利则直接返回,不进行买卖操作(仅仅适用于短周期版本的入场策略,即profitCheck=True;长周期版本对应的是profitCheck=False)

 

MAX_PRODUCT_POS = 4         # 单品种最大持仓
MAX_DIRECTION_POS = 12      # 单方向最大持仓
......
class TurtlePortfolio(object):
......
    #----------------------------------------------------------------------
    def newSignal(self, signal, direction, offset, price, volume):
......
        # 开仓
        if offset == OFFSET_OPEN:
            # 检查上一次是否为盈利
            if signal.profitCheck:
                pnl = signal.getLastPnl()
                if pnl > 0:
                    return

            # 买入
            if direction == DIRECTION_LONG:
                # 组合持仓不能超过上限
                if self.totalLong >= MAX_DIRECTION_POS:
                    return

                # 单品种持仓不能超过上限
                if self.unitDict[signal.vtSymbol] >= MAX_PRODUCT_POS:
                    return
            # 卖出
            else:
                if self.totalShort <= -MAX_DIRECTION_POS:
                    return

                if self.unitDict[signal.vtSymbol] <= -MAX_PRODUCT_POS:
                    return

 
 

3.入场信号、逐步建仓、止损、止盈


原版海龟策略提供2个版本的入场和止盈信号,分别是长周期版本和短周期版本的唐奇安通道突破。

  • 短周期信号:入场用是20日唐奇安通道,止盈用是10日唐奇安通道,用20日周期计算ATR值,有上一笔盈利当前信号无效的过滤条件。
  • 短周期信号:入场用是55日唐奇安通道,止盈用是20日唐奇安通道,用20日周期计算ATR值,无上一笔盈利当前信号无效的过滤条件。

逐步建仓的规则是每隔0.5*ATR幅度慢慢加满至4个单位头寸,止损也相应根据0.5*ATR的步进移动。
 

class TurtleSignal(object):
    #----------------------------------------------------------------------
    def __init__(self, portfolio, vtSymbol, 
                 entryWindow, exitWindow, atrWindow,
                 profitCheck=False):
......
    #----------------------------------------------------------------------
    def onBar(self, bar):
        self.bar = bar
        self.am.bar
        if not self.am.inited:
            return

        self.generateSignal(bar)
        self.calculateIndicator()       
    #----------------------------------------------------------------------
    def generateSignal(self, bar):
        """        
        判断交易信号
        """
        # 如果指标尚未初始化,则忽略
        if not self.longEntry1:
            return

        # 优先检查平仓
        if self.unit > 0:
            longExit = max(self.longStop, self.exitDown)

            if bar.low <= longExit:
                self.sell(longExit)
                return
        elif self.unit < 0:
            shortExit = min(self.shortStop, self.exitUp)
            if bar.high >= shortExit:
                self.cover(shortExit)
                return

        # 没有仓位或者持有多头仓位的时候,可以做多(加仓)
        if self.unit >= 0:
            trade = False

            if bar.high >= self.longEntry1 and self.unit < 1:
                self.buy(self.longEntry1, 1)
                trade = True

            if bar.high >= self.longEntry2 and self.unit < 2:
                self.buy(self.longEntry2, 1)
                trade = True

            if bar.high >= self.longEntry3 and self.unit < 3:
                self.buy(self.longEntry3, 1)
                trade = True

            if bar.high >= self.longEntry4 and self.unit < 4:
                self.buy(self.longEntry4, 1)
                trade = True

            if trade:
                return

        # 没有仓位或者持有空头仓位的时候,可以做空(加仓)
        if self.unit <= 0:
            if bar.low <= self.shortEntry1 and self.unit > -1:
                self.short(self.shortEntry1, 1)

            if bar.low <= self.shortEntry2 and self.unit > -2:
                self.short(self.shortEntry2, 1)

            if bar.low <= self.shortEntry3 and self.unit > -3:
                self.short(self.shortEntry3, 1)

            if bar.low <= self.shortEntry4 and self.unit > -4:
                self.short(self.shortEntry4, 1)

    #----------------------------------------------------------------------
    def calculateIndicator(self):
        """计算技术指标"""
        self.entryUp, self.entryDown = self.am.donchian(self.entryWindow)
        self.exitUp, self.exitDown = self.am.donchian(self.exitWindow)

        # 有持仓后,ATR波动率和入场位等都不再变化
        if not self.unit:
            self.atrVolatility = self.am.atr(self.atrWindow)

            self.longEntry1 = self.entryUp
            self.longEntry2 = self.entryUp + self.atrVolatility * 0.5
            self.longEntry3 = self.entryUp + self.atrVolatility * 1
            self.longEntry4 = self.entryUp + self.atrVolatility * 1.5
            self.longStop = 0

            self.shortEntry1 = self.entryDown
            self.shortEntry2 = self.entryDown - self.atrVolatility * 0.5
            self.shortEntry3 = self.entryDown - self.atrVolatility * 1
            self.shortEntry4 = self.entryDown - self.atrVolatility * 1.5
            self.shortStop = 0

......
class TurtlePortfolio(object):
......
    #----------------------------------------------------------------------
    def init(self, portfolioValue, vtSymbolList, sizeDict):
        """"""
        self.portfolioValue = portfolioValue
        self.sizeDict = sizeDict

        for vtSymbol in vtSymbolList:
            signal1 = TurtleSignal(self, vtSymbol, 20, 10, 20, True)
            signal2 = TurtleSignal(self, vtSymbol, 55, 20, 20, False)

            l = self.signalDict[vtSymbol]
            l.append(signal1)
            l.append(signal2) 
            self.unitDict[vtSymbol] = 0
            self.posDict[vtSymbol] = 0

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """"""
        for signal in self.signalDict[bar.vtSymbol]:
            signal.onBar(bar)
以下是一个简单的海龟策略的 Python 代码示例: ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt # 计算移动平均线 def MA(df, window): ma = df.rolling(window=window).mean() return ma # 计算真实波动幅度 def ATR(df, window): high = df['High'] low = df['Low'] close = df['Close'] tr = pd.DataFrame(np.zeros(len(df)), columns=['TR']) for i in range(1, len(df)): tr.loc[i] = max(high[i] - low[i], abs(high[i] - close[i-1]), abs(low[i] - close[i-1])) atr = MA(tr, window) return atr # 计算海龟策略的入场点和离场点 def turtle_signal(df, n1, n2): atr = ATR(df, n1) df['MA1'] = MA(df['Close'], n1) df['MA2'] = MA(df['Close'], n2) df['Signal'] = np.where(df['Close'] > df['MA1'] + 0.5 * atr, 1, 0) df['Signal'] = np.where(df['Close'] < df['MA2'], -1, df['Signal']) return df['Signal'] # 测试代码 data = pd.read_csv('data.csv') data['Date'] = pd.to_datetime(data['Date']) data.set_index('Date', inplace=True) signal = turtle_signal(data, 20, 55) data['Signal'] = signal data['Return'] = np.log(data['Close'].shift(-1) / data['Close']) * data['Signal'].shift(1) data['Cumulative Return'] = data['Return'].cumsum() data[['Close', 'MA1', 'MA2']].plot(figsize=(10, 6)) plt.plot(data.loc[data['Signal'] == 1].index, data['MA1'][data['Signal'] == 1], '^', markersize=10, color='g') plt.plot(data.loc[data['Signal'] == -1].index, data['MA2'][data['Signal'] == -1], 'v', markersize=10, color='r') plt.show() ``` 这段代码实现了海龟策略的核心部分,包括计算移动平均线、真实波动幅度、海龟策略的入场点和离场点,并且将策略的信号标记在了数据中。最后,代码还画出了收益曲线和入场、离场点的标记。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值