コード例 #1
0
ファイル: strategyMultiSignal.py プロジェクト: ongbe/pytrader
class MaSignal(CtaSignal):
    """双均线信号"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        super(MaSignal, self).__init__()

        self.fastWindow = 5
        self.slowWindow = 20

        self.bg = BarGenerator(self.onBar, 5, self.onFiveBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """Tick更新"""
        self.bg.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """K线更新"""
        self.bg.updateBar(bar)

    #----------------------------------------------------------------------
    def onFiveBar(self, bar):
        """5分钟K线更新"""
        self.am.updateBar(bar)

        if not self.am.inited:
            self.setSignalPos(0)

        fastMa = self.am.sma(self.fastWindow)
        slowMa = self.am.sma(self.slowWindow)

        if fastMa > slowMa:
            self.setSignalPos(1)
        elif fastMa < slowMa:
            self.setSignalPos(-1)
        else:
            self.setSignalPos(0)
コード例 #2
0
ファイル: strategyMultiSignal.py プロジェクト: ongbe/pytrader
class CciSignal(CtaSignal):
    """CCI信号"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        super(CciSignal, self).__init__()

        self.cciWindow = 30
        self.cciLevel = 10
        self.cciLong = self.cciLevel
        self.cciShort = -self.cciLevel

        self.bg = BarGenerator(self.onBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """Tick更新"""
        self.bg.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """K线更新"""
        self.am.updateBar(bar)

        if not self.am.inited:
            self.setSignalPos(0)

        cciValue = self.am.cci(self.cciWindow)

        if cciValue >= self.cciLong:
            self.setSignalPos(1)
        elif cciValue <= self.cciShort:
            self.setSignalPos(-1)
        else:
            self.setSignalPos(0)
コード例 #3
0
ファイル: strategyMultiSignal.py プロジェクト: ongbe/pytrader
class RsiSignal(CtaSignal):
    """RSI信号"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        super(RsiSignal, self).__init__()

        self.rsiWindow = 14
        self.rsiLevel = 20
        self.rsiLong = 50 + self.rsiLevel
        self.rsiShort = 50 - self.rsiLevel

        self.bg = BarGenerator(self.onBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """Tick更新"""
        self.bg.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """K线更新"""
        self.am.updateBar(bar)

        if not self.am.inited:
            self.setSignalPos(0)

        rsiValue = self.am.rsi(self.rsiWindow)

        if rsiValue >= self.rsiLong:
            self.setSignalPos(1)
        elif rsiValue <= self.rsiShort:
            self.setSignalPos(-1)
        else:
            self.setSignalPos(0)
コード例 #4
0
class MultiTimeframeStrategy(CtaTemplate):
    """跨时间周期交易策略"""
    className = 'MultiTimeframeStrategy'
    author = u'用Python的交易员'

    # 策略参数
    rsiSignal = 20  # RSI信号阈值
    rsiWindow = 14  # RSI窗口
    fastWindow = 5  # 快速均线窗口
    slowWindow = 20  # 慢速均线窗口

    initDays = 10  # 初始化数据所用的天数
    fixedSize = 1  # 每次交易的数量

    # 策略变量
    rsiValue = 0  # RSI指标的数值
    rsiLong = 0  # RSI买开阈值
    rsiShort = 0  # RSI卖开阈值
    fastMa = 0  # 5分钟快速均线
    slowMa = 0  # 5分钟慢速均线
    maTrend = 0  # 均线趋势,多头1,空头-1

    # 参数列表,保存了参数的名称
    paramList = [
        'name', 'className', 'author', 'vtSymbol', 'rsiSignal', 'rsiWindow',
        'fastWindow', 'slowWindow'
    ]

    # 变量列表,保存了变量的名称
    varList = [
        'inited', 'trading', 'pos', 'rsiValue', 'rsiLong', 'rsiShort',
        'fastMa', 'slowMa', 'maTrend'
    ]

    # 同步列表,保存了需要保存到数据库的变量名称
    syncList = ['pos']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(MultiTimeframeStrategy, self).__init__(ctaEngine, setting)

        self.rsiLong = 50 + self.rsiSignal
        self.rsiShort = 50 - self.rsiSignal

        # 创建K线合成器对象
        self.bg5 = BarGenerator(self.onBar, 5, self.on5MinBar)
        self.am5 = ArrayManager()

        self.bg15 = BarGenerator(self.onBar, 15, self.on15MinBar)
        self.am15 = ArrayManager()

    #----------------------------------------------------------------------
    def onInit(self):
        """初始化策略(必须由用户继承实现)"""
        self.writeCtaLog(u'%s策略初始化' % self.name)

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        initData = self.loadBar(self.initDays)
        for bar in initData:
            self.onBar(bar)

        self.putEvent()

    #----------------------------------------------------------------------
    def onStart(self):
        """启动策略(必须由用户继承实现)"""
        self.writeCtaLog(u'%s策略启动' % self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略(必须由用户继承实现)"""
        self.writeCtaLog(u'%s策略停止' % self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        # 只需要要在一个BarGenerator中合成1分钟K线
        self.bg5.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""
        # 基于15分钟判断趋势过滤,因此先更新
        self.bg15.updateBar(bar)

        # 基于5分钟判断
        self.bg5.updateBar(bar)

    #----------------------------------------------------------------------
    def on5MinBar(self, bar):
        """5分钟K线"""
        self.cancelAll()

        # 保存K线数据
        self.am5.updateBar(bar)
        if not self.am5.inited:
            return

        # 如果15分钟数据尚未初始化完毕,则直接返回
        if not self.maTrend:
            return

        # 计算指标数值
        self.rsiValue = self.am5.rsi(self.rsiWindow)

        # 判断是否要进行交易

        # 当前无仓位
        if self.pos == 0:
            if self.maTrend > 0 and self.rsiValue >= self.rsiLong:
                self.buy(bar.close + 5, self.fixedSize)

            elif self.maTrend < 0 and self.rsiValue <= self.rsiShort:
                self.short(bar.close - 5, self.fixedSize)

        # 持有多头仓位
        elif self.pos > 0:
            if self.maTrend < 0 or self.rsiValue < 50:
                self.sell(bar.close - 5, abs(self.pos))

        # 持有空头仓位
        elif self.pos < 0:
            if self.maTrend > 0 or self.rsiValue > 50:
                self.cover(bar.close + 5, abs(self.pos))

        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def on15MinBar(self, bar):
        """15分钟K线推送"""
        self.am15.updateBar(bar)

        if not self.am15.inited:
            return

        # 计算均线并判断趋势
        self.fastMa = self.am15.sma(self.fastWindow)
        self.slowMa = self.am15.sma(self.slowWindow)

        if self.fastMa > self.slowMa:
            self.maTrend = 1
        else:
            self.maTrend = -1

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        pass

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止单推送"""
        pass
コード例 #5
0
class BollingerBotStrategy01(CtaTemplate):
    """基于布林通道的交易策略"""
    className = 'BollingerBotStrategy01'
    author = 'Y.Raul'

    # 策略参数
    bollWindow = 28  # 通道窗口数
    entryDevUp = 4  # 开仓偏差
    entryDevDown = 3.2
    # exitDev = 1.2           # 平仓偏差
    # trailingPrcnt = 0.4
    # 移动止损百分比
    maWindow = 10  # 过滤用均线窗口
    initDays = 10  # 初始化数据所用的天数
    fixedSize = 1  # 每次交易的数量

    # 策略变量
    bollMid = 0  # 布林带中轨
    bollStd = 0  # 布林带宽度
    entryUp = 0  # 开仓上轨
    # exitUp = 0                          # 平仓上轨
    entryDown = 0  #开仓下轨
    # exitDown = 0                        #平仓下轨

    dispacedLen = 0  #均线平移长度
    maFilter = 0  # 均线过滤
    maFilter1 = 0  # 上一期均线

    # 分级出场设置
    trailingStart1 = 20
    trailingStart2 = 30
    exitOnTrailingStop1 = 5  # Trailing Stop 距离
    exitOnTrailingStop2 = 10  # Trailing Stop 距离
    exitOnLossStop = 20  # Loss Stop 距离

    # 价格相关变量
    intraTradeHigh = 0  # 持仓期内的最高点
    intraTradeLow = 0  # 持仓期内的最低点
    avgEntryPrice = 0
    minDiff = 1
    trailingExit = 0  #
    stopExit = 0  # 空头止损
    # longEntry = 0  # 多头开仓
    # shortEntry = 0

    # 信号相关变量
    buySig = False
    shortSig = False
    sellSig = False
    coverSig = False
    # entrusted = False #是否已有委托

    orderList = []  # 保存委托代码的列表

    # 参数列表,保存了参数的名称
    paramList = [
        'name', 'className', 'author', 'vtSymbol', 'bollWindow', 'entryDevUp',
        'entryDevDown', 'trailingStart1', 'trailingStart2',
        'exitOnTrailingStop1', 'exitOnTrailingStop2', 'maWindow', 'initDays',
        'fixedSize'
    ]

    # 变量列表,保存了变量的名称
    varList = [
        'inited', 'trading', 'pos', 'buySig', 'shortSig', 'sellSig',
        'coverSig', 'entryUp', 'entryDown', 'trailingExit', 'stopExit',
        'intraTradeHigh', 'intraTradeLow', 'avgEntryPrice'
    ]

    # 同步列表
    syncList = ['pos', 'intraTradeHigh', 'intraTradeLow']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(BollingerBotStrategy01, self).__init__(ctaEngine, setting)

        self.bm = BarGenerator(self.onBar, 5, self.onFiveBar)
        self.am = ArrayManager(30)
        self.orderList = []
        self.entryPriceList = []

    #----------------------------------------------------------------------
    def onInit(self):
        """初始化策略(必须由用户继承实现)"""
        self.writeCtaLog('%s策略初始化' % self.name)

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        initData = self.loadBar(self.initDays)
        for bar in initData:
            self.onBar(bar)

        self.putEvent()

    #----------------------------------------------------------------------
    def onStart(self):
        """启动策略(必须由用户继承实现)"""
        self.writeCtaLog('%s策略启动' % self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略(必须由用户继承实现)"""
        self.writeCtaLog('%s策略停止' % self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        self.bm.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""
        # 观察周期1 Min,根据信号进行交易
        # 回测数据传送的bar.datetime,为bar的开始时间
        self.bm.updateBar(bar)
        # if not self.trading:
        #     return

        self.date = bar.date
        self.time = bar.time
        # 检查交易信号
        if self.buySig:
            res = self.buy(bar.close, self.fixedSize, True)
            self.orderList.extend([x.split('.')[1] for x in res])
            # self.orderList.extend(res.split('.')[1])

            # self.entryPriceList.append(self.longEntry)
            # self.avgEntryPrice = sum(self.entryPriceList) / len(self.entryPriceList)
            # self.LossStopPrice = round(self.avgEntryPrice * (100.0 + self.exitOnLossStop) / 100)

            # self.intraTradeHigh = max(bar.high, self.avgEntryPrice)
            # self.intraTradeLow = min(bar.low, self.avgEntryPrice)
            # log = "-----" * 10 + "\n@onBar\n" + \
            #       "bar.datetime: {0}; pos: {1} \n".format(bar.datetime, self.pos) + \
            #       "buySig: {0}; shortSig: {1}\n".format(self.buySig, self.shortSig) + \
            #       "sellSig: {0}; coverSig: {1}\n".format(self.sellSig, self.coverSig) + \
            #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
            #       "intraTradeLow: {0}\n".format(self.intraTradeLow)
            # self.writeCtaLog(log)
            # 记录log
            # log = "\n Trading: {0}\n".format(self.trading) + \
            #       "{0} Buy : longEntry: {1};\n".format(bar.datetime, bar.close) + \
            #       " entryUp:{0}; maFilter:{1}; maFilter1:{2}; \n".format(self.entryUp, self.maFilter, self.maFilter1)
            # self.writeCtaLog(log)
            self.buySig = False
            self.saveSyncData()
            # return

        if self.shortSig:
            self.res = self.short(bar.close, self.fixedSize, True)
            self.orderList.extend([x.split('.')[1] for x in self.res])
            # self.orderList.extend(res.split('.')[1])

            # self.LossStopPrice = round(self.shortEntry * (100.0 + self.exitOnLossStop) / 100)
            # self.entryPriceList.append(self.shortEntry)
            # self.avgEntryPrice = sum(self.entryPriceList) / len(self.entryPriceList)
            # self.LossStopPrice = round(self.avgEntryPrice * (100.0 + self.exitOnLossStop) / 100)
            #
            # self.intraTradeHigh = max(bar.high, self.avgEntryPrice)
            # self.intraTradeLow = min(bar.low, self.avgEntryPrice)
            # log = "-----" * 10 + "\n@onBar\n" + \
            #       "bar.datetime: {0}; pos: {1} \n".format(bar.datetime, self.pos) + \
            #       "buySig: {0}; shortSig: {1}\n".format(self.buySig, self.shortSig) + \
            #       "sellSig: {0}; coverSig: {1}\n".format(self.sellSig, self.coverSig) + \
            #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
            #       "intraTradeLow: {0}\n".format(self.intraTradeLow)
            # self.writeCtaLog(log)
            # # 记录log
            # log = "\n Trading: {0}\n".format(self.trading) + \
            #       "{0} Short : shortEntry: {1};\n".format(bar.datetime, bar.close) + \
            #       " entryDown:{0}; maFilter:{1}; maFilter1:{2}; \n".format(self.entryDown, self.maFilter, self.maFilter1)
            # self.writeCtaLog(log)

            self.shortSig = False
            self.saveSyncData()
            # return

        if self.sellSig:
            if bar.close > self.stopExit:
                price = self.trailingExit
            else:
                price = bar.close
            res = self.sell(price, abs(self.pos), True)
            # self.orderList.extend(res)
            # log = "-----" * 10 + "\n@onBar\n" + \
            #       "bar.datetime: {0}; pos: {1} \n".format(bar.datetime, self.pos) + \
            #       "buySig: {0}; shortSig: {1}\n".format(self.buySig, self.shortSig) + \
            #       "sellSig: {0}; coverSig: {1}\n".format(self.sellSig, self.coverSig) + \
            #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
            #       "intraTradeLow: {0}\n".format(self.intraTradeLow)
            # self.writeCtaLog(log)
            # # 记录log
            # log = "\n Trading: {0}\n".format(self.trading) + \
            #       "{0} Sell : {1};\n".format(bar.datetime, bar.close) + \
            #       " price:{0}; stopExit: {1}\n".format(price,self.stopExit)
            # self.writeCtaLog(log)

            # self.entryPriceList = []
            # self.avgEntryPrice = 0
            # self.stopExit = 0
            self.sellSig = False
            self.saveSyncData()
            # return

        if self.coverSig:
            if bar.close < self.stopExit:
                price = self.trailingExit
            else:
                price = bar.close
            res = self.cover(price, abs(self.pos), True)
            # self.orderList.extend(res)
            # log = "-----" * 10 + "\n@onBar\n" + \
            #       "bar.datetime: {0}; pos: {1} \n".format(bar.datetime, self.pos) + \
            #       "buySig: {0}; shortSig: {1}\n".format(self.buySig, self.shortSig) + \
            #       "sellSig: {0}; coverSig: {1}\n".format(self.sellSig, self.coverSig) + \
            #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
            #       "intraTradeLow: {0}\n".format(self.intraTradeLow)
            # self.writeCtaLog(log)
            # # 记录log
            # log = "\n Trading: {0}\n".format(self.trading) + \
            #       "{0} Cover : {1};\n".format(bar.datetime, bar.close) + \
            #       " price:{0}; stopExit: {1}\n".format(price,self.stopExit)
            # self.writeCtaLog(log)

            # self.entryPriceList = []
            # self.avgEntryPrice = 0
            # self.stopExit = 0
            self.coverSig = False
            self.saveSyncData()
            # return

        self.putEvent()

    #----------------------------------------------------------------------
    def onFiveBar(self, bar):
        """收到5分钟K线"""
        # 策略周期5Min,生成交易信号
        # 保存K线数据
        self.am.updateBar(bar)

        if not self.am.inited:
            return

        # 撤销之前发出的尚未成交的委托(包括限价单和停止单)
        self.cancelAll()

        # 计算指标数值
        self.bollMid = self.am.sma(self.bollWindow,
                                   True)[-1 * (self.dispacedLen + 1)]
        self.bollStd = self.am.std(self.bollWindow)
        self.entryUp = round(self.bollMid + self.bollStd * self.entryDevUp)
        self.entryDown = round(self.bollMid - self.bollStd * self.entryDevDown)
        maArray = self.am.sma(self.maWindow, True)
        self.maFilter = round(maArray[-1])
        self.maFilter1 = round(maArray[-2])

        # 判断是否要进行交易
        # 当前无仓位
        if self.pos == 0:
            self.intraTradeHigh = bar.high
            self.intraTradeLow = bar.low
            self.entryPriceList = []
            self.orderList = []
            self.avgEntryPrice = 0

            if bar.close > self.maFilter and self.maFilter > self.maFilter1:
                # 均线多头过滤
                if bar.close >= self.entryUp:
                    # 上轨突破
                    self.buySig = True

            if bar.close < self.maFilter and self.maFilter < self.maFilter1:
                # 均线空头过滤
                if bar.close <= self.entryDown:
                    # 下轨突破
                    self.shortSig = True

            # log = "-----" * 10 + "\n@onFiveBar\n" + \
            #       "bar.datetime: {0}; pos: {1} ; close: {2}\n".format(bar.datetime, self.pos,bar.close) + \
            #       "buySig: {0}; shortSig: {1}\n".format(self.buySig, self.shortSig) + \
            #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
            #       "intraTradeLow: {0}\n".format(self.intraTradeLow)
            # self.writeCtaLog(log)

        # 当前有仓位
        else:
            self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
            self.intraTradeLow = min(self.intraTradeLow, bar.low)

            if self.pos > 0:
                # self.stopExit = self.avgEntryPrice - self.exitOnLossStop * self.minDiff #固定止损价位

                if self.intraTradeHigh >= self.avgEntryPrice + self.trailingStart2 * self.minDiff:
                    # 二级止赢判断 盈利80跳
                    if (bar.close <= self.intraTradeHigh -
                            self.exitOnTrailingStop2 * self.minDiff):
                        # 回撤20跳
                        self.trailingExit = self.intraTradeHigh - self.exitOnTrailingStop2 * self.minDiff
                        self.sellSig = True
                        # if bar.close < self.longExit:
                        #     self.longExit = bar.close
                        # 记录log
                        # log = "\n{0} Sell(Trailing Stop2)\n".format(bar.datetime) + \
                        #     'bar.close: {0}; bar.low: {1}; longExit: {2}'.format(bar.close,bar.low, self.longExit)+ \
                        #     'intraTradeHigh: {0}; avgEntryPrice: {1}; bar.open: {2}'.format(self.intraTradeHigh,self.avgEntryPrice, bar.open)
                        # self.writeCtaLog(log)

                elif self.intraTradeHigh >= self.avgEntryPrice + self.trailingStart1 * self.minDiff:
                    # 一级止赢判断,盈利50跳
                    if (bar.close <= self.intraTradeHigh -
                            self.exitOnTrailingStop1 * self.minDiff):
                        # 回撤20跳
                        self.trailingExit = self.intraTradeHigh - self.exitOnTrailingStop1 * self.minDiff
                        self.sellSig = True
                        # if bar.close < self.longExit:
                        #     self.longExit = bar.close
                        # 记录log
                        # log = "\n{0} Sell(Trailing Stop1)\n".format(bar.datetime) + \
                        #       'bar.close: {0}; bar.low: {1}; longExit: {2}'.format(bar.close, bar.low,
                        #                                                            self.longExit)+ \
                        #       'intraTradeHigh: {0}; avgEntryPrice: {1}; bar.open: {2}'.format(self.intraTradeHigh,self.avgEntryPrice, bar.open)
                        # self.writeCtaLog(log)
                elif self.stopExit != 0:
                    if (bar.close <= self.stopExit):
                        # 固定止损,回撤20跳
                        self.sellSig = True
                # log = "-----" * 10 + "\n@onFiveBar\n" + \
                #       "bar.datetime: {0}; pos: {1} ; close:{2}\n".format(bar.datetime, self.pos, bar.close) + \
                #       "sellSig: {0}; coverSig: {1}\n".format(self.sellSig, self.coverSig) + \
                #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
                #       "intraTradeLow: {0}\n".format(self.intraTradeLow) + \
                #       "trailingStart1: {0}\n".format(self.avgEntryPrice + self.trailingStart1 * self.minDiff) + \
                #       "trailingStart2: {0}\n".format(self.avgEntryPrice + self.trailingStart2 * self.minDiff) + \
                #       "avgEntryPrice: {0}\n".format(self.avgEntryPrice) + \
                #       "trailingStop: {0}\n".format(self.trailingExit) + \
                #       "stopExit: {0}\n".format(self.stopExit)
                #
                # self.writeCtaLog(log)
                # if bar.close < self.longExit:
                #     self.longExit = bar.close
                # 记录log
                # log = "\n{0} Sell(Loss Stop)\n".format(bar.datetime) + \
                #       'bar.close: {0}; bar.low: {1}; longExit: {2}'.format(bar.close, bar.low,
                #                                                            self.longExit)+ \
                #       'intraTradeHigh: {0}; avgEntryPrice: {1}; bar.open: {2}'.format(self.intraTradeHigh,
                #                                                                       self.avgEntryPrice,
                #                                                                       bar.open)
                # self.writeCtaLog(log)

            elif self.pos < 0:
                # self.stopExit = self.avgEntryPrice + self.exitOnLossStop * self.minDiff #固定止损价
                if self.intraTradeLow <= self.avgEntryPrice - self.trailingStart2 * self.minDiff:
                    # 二级止赢判断 盈利80跳
                    if (bar.close >= self.intraTradeLow +
                            self.exitOnTrailingStop2 * self.minDiff):
                        # 回撤20跳
                        self.trailingExit = self.intraTradeLow + self.exitOnTrailingStop2 * self.minDiff
                        self.coverSig = True
                        # if bar.close > self.shortExit:
                        #     self.shortExit = bar.close
                        # 记录log
                        # log = "\n{0} Cover(Trailing Stop1)\n".format(bar.datetime) + \
                        #       'bar.close: {0}; bar.low: {1}; shortExit: {2}'.format(bar.close, bar.low,
                        #                                                            self.shortExit)+ \
                        #       'intraTradeLow: {0}; avgEntryPrice: {1}; bar.open: {2}'.format(self.intraTradeLow,
                        #                                                                       self.avgEntryPrice,
                        #                                                                       bar.open)
                        # self.writeCtaLog(log)

                elif self.intraTradeLow <= self.avgEntryPrice - self.trailingStart1 * self.minDiff:
                    # 一级止赢判断,盈利50跳
                    if (bar.close >= self.intraTradeLow +
                            self.exitOnTrailingStop1 * self.minDiff):
                        # 回撤20跳
                        self.trailingExit = self.intraTradeLow + self.exitOnTrailingStop1 * self.minDiff
                        self.coverSig = True
                        # if bar.close > self.shortExit:
                        #     self.shortExit = bar.close
                        # 记录log
                        # log = "\n{0} Cover(Trailing Stop2)\n".format(bar.datetime) + \
                        #       'bar.close: {0}; bar.low: {1}; shortExit: {2}'.format(bar.close, bar.low,
                        #                                                            self.shortExit)+ \
                        #       'intraTradeLow: {0}; avgEntryPrice: {1}; bar.open: {2}'.format(self.intraTradeLow,
                        #                                                                      self.avgEntryPrice,
                        #                                                                      bar.open)
                        # self.writeCtaLog(log)
                elif self.stopExit != 0:
                    if (bar.close >= self.stopExit):
                        # 固定止损,回撤20跳
                        # self.shortExit = self.avgEntryPrice + self.exitOnLossStop * self.minDiff
                        self.coverSig = True
                # if bar.close > self.shortExit:
                #     self.shortExit = bar.close
                # 记录log
                # log = "\n{0} Cover(Loss Stop)\n".format(bar.datetime) + \
                #       'bar.close: {0}; bar.low: {1}; shortExit: {2}'.format(bar.close, bar.low,
                #                                                             self.shortExit)+ \
                #       'intraTradeLow: {0}; avgEntryPrice: {1}; bar.open: {2}'.format(self.intraTradeLow,
                #                                                                      self.avgEntryPrice,
                #                                                                      bar.open)
                # self.writeCtaLog(log)

                # log = "-----" * 10 + "\n@onFiveBar\n" + \
                #       "bar.datetime: {0}; pos: {1} ; close:{2}\n".format(bar.datetime, self.pos, bar.close) + \
                #       "sellSig: {0}; coverSig: {1}\n".format(self.sellSig, self.coverSig) + \
                #       "intraTradeHigh: {0}\n".format(self.intraTradeHigh) + \
                #       "intraTradeLow: {0}\n".format(self.intraTradeLow) + \
                #       "trailingStart1: {0}\n".format(self.avgEntryPrice - self.trailingStart1 * self.minDiff)+\
                #       "trailingStart2: {0}\n".format(self.avgEntryPrice - self.trailingStart2 * self.minDiff)+\
                #       "avgEntryPrice: {0}\n".format(self.avgEntryPrice)+\
                #       "trailingStop: {0}\n".format(self.trailingExit)+\
                #       "stopExit: {0}\n".format(self.stopExit)
                #
                # self.writeCtaLog(log)

        # 发出状态更新事件
        self.saveSyncData()
        self.putEvent()

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        # CTA引擎中涉及到的交易方向类型
        # CTAORDER_BUY = u'买开'
        # CTAORDER_SELL = u'卖平'
        # CTAORDER_SHORT = u'卖开'
        # CTAORDER_COVER = u'买平'
        # log = "-----" * 10 + "\n@onOrder\n" + \
        #       "orderTime: {0}; pos: {1} \n".format(order.orderTime, order.totalVolume) + \
        #       "status {0}; vtOrderID: {1}\n".format(order.status, order.vtOrderID)
        # self.writeCtaLog(log)

        # 对于开仓,记录相关价格
        # if order.vtOrderID in self.orderList:
        if order.direction == DIRECTION_LONG and order.offset == OFFSET_OPEN:
            if order.totalVolume == order.tradedVolume:
                # 更新入场价列表,更新平均入场价
                self.entryPriceList.append(order.price)
                self.avgEntryPrice = sum(self.entryPriceList) / len(
                    self.entryPriceList)
                self.stopExit = self.avgEntryPrice - self.exitOnLossStop * self.minDiff  # 固定止损价
                # self.orderList.remove(order.vtOrderID)

        elif order.direction == DIRECTION_SHORT and order.offset == OFFSET_OPEN:
            # 更新入场价列表,更新平均入场价
            if order.totalVolume == order.tradedVolume:
                # 更新入场价列表,更新平均入场价
                self.entryPriceList.append(order.price)
                self.avgEntryPrice = sum(self.entryPriceList) / len(
                    self.entryPriceList)
                self.stopExit = self.avgEntryPrice + self.exitOnLossStop * self.minDiff  # 固定止损价
                # self.orderList.remove(order.vtOrderID)

        self.putEvent()

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # 发出状态更新事件
        data = trade.__dict__

        self.putEvent()

    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止单推送"""
        data = so.__dict__
        self.putEvent()
コード例 #6
0
class TurtleTradingStrategy(CtaTemplate):
    """海龟交易策略"""
    className = 'TurtleTradingStrategy'
    author = u'用Python的交易员'

    # 策略参数
    entryWindow = 55  # 入场通道窗口
    exitWindow = 20  # 出场通道窗口
    atrWindow = 20  # 计算ATR波动率的窗口
    initDays = 10  # 初始化数据所用的天数
    fixedSize = 1  # 每次交易的数量

    # 策略变量
    entryUp = 0  # 入场通道上轨
    entryDown = 0  # 入场通道下轨
    exitUp = 0  # 出场通道上轨
    exitDown = 0  # 出场通道下轨
    atrVolatility = 0  # ATR波动率

    longEntry = 0  # 多头入场价格
    shortEntry = 0  # 空头入场价格
    longStop = 0  # 多头止损价格
    shortStop = 0  # 空头止损价格

    # 参数列表,保存了参数的名称
    paramList = [
        'name', 'className', 'author', 'vtSymbol', 'entryWindow', 'exitWindow',
        'atrWindow', 'initDays', 'fixedSize'
    ]

    # 变量列表,保存了变量的名称
    varList = [
        'inited', 'trading', 'pos', 'entryUp', 'entryDown', 'exitUp',
        'exitDown', 'longEntry', 'shortEntry', 'longStop', 'shortStop'
    ]

    # 同步列表,保存了需要保存到数据库的变量名称
    syncList = ['pos']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(TurtleTradingStrategy, self).__init__(ctaEngine, setting)

        self.bg = BarGenerator(self.onBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def onInit(self):
        """初始化策略(必须由用户继承实现)"""
        self.writeCtaLog(u'%s策略初始化' % self.name)

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        initData = self.loadBar(self.initDays)
        for bar in initData:
            self.onBar(bar)

        self.putEvent()

    #----------------------------------------------------------------------
    def onStart(self):
        """启动策略(必须由用户继承实现)"""
        self.writeCtaLog(u'%s策略启动' % self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略(必须由用户继承实现)"""
        self.writeCtaLog(u'%s策略停止' % self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        self.bg.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""
        self.cancelAll()

        # 保存K线数据
        self.am.updateBar(bar)
        if not self.am.inited:
            return

        # 计算指标数值
        self.entryUp, self.entryDown = self.am.donchian(self.entryWindow)
        self.exitUp, self.exitDown = self.am.donchian(self.exitWindow)

        if not self.pos:
            self.atrVolatility = self.am.atr(self.atrWindow)

        # 判断是否要进行交易
        if self.pos == 0:
            self.longEntry = 0
            self.shortEntry = 0
            self.longStop = 0
            self.shortStop = 0

            self.sendBuyOrders(self.entryUp)
            self.sendShortOrders(self.entryDown)

        elif self.pos > 0:
            # 加仓逻辑
            self.sendBuyOrders(self.longEntry)

            # 止损逻辑
            sellPrice = max(self.longStop, self.exitDown)
            self.sell(sellPrice, abs(self.pos), True)

        elif self.pos < 0:
            # 加仓逻辑
            self.sendShortOrders(self.shortEntry)

            # 止损逻辑
            coverPrice = min(self.shortStop, self.exitUp)
            self.cover(coverPrice, abs(self.pos), True)

        # 同步数据到数据库
        self.saveSyncData()

        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        pass

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        """成交推送"""
        if trade.direction == DIRECTION_LONG:
            self.longEntry = trade.price
            self.longStop = self.longEntry - self.atrVolatility * 2
        else:
            self.shortEntry = trade.price
            self.shortStop = self.shortEntry + self.atrVolatility * 2

        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止单推送"""
        pass

    #----------------------------------------------------------------------
    def sendBuyOrders(self, price):
        """发出一系列的买入停止单"""
        t = self.pos / self.fixedSize

        if t < 1:
            self.buy(price, self.fixedSize, True)

        if t < 2:
            self.buy(price + self.atrVolatility * 0.5, self.fixedSize, True)

        if t < 3:
            self.buy(price + self.atrVolatility, self.fixedSize, True)

        if t < 4:
            self.buy(price + self.atrVolatility * 1.5, self.fixedSize, True)

    #----------------------------------------------------------------------
    def sendShortOrders(self, price):
        """"""
        t = self.pos / self.fixedSize

        if t > -1:
            self.short(price, self.fixedSize, True)

        if t > -2:
            self.short(price - self.atrVolatility * 0.5, self.fixedSize, True)

        if t > -3:
            self.short(price - self.atrVolatility, self.fixedSize, True)

        if t > -4:
            self.short(price - self.atrVolatility * 1.5, self.fixedSize, True)