经典量化模型分享之【海龟交易法】,适用于加密币、期货、外汇(附源码)



  • 导语:

    策略为基本模型,如使用请自行调整策略参数和接口。

    天然的海龟是一个比较成熟而完整的交易系统。构建交易系统的目的就是避免交易员自己做出主观的决策。这样才能真正的让概率发挥作用。海龟的主要捕捉的是趋势。其采用突破法来确定趋势,当价格突破时认为有买入的信号,而随着价格离当初突破的价格越来越远,我们认为趋势成立的概率就越来越高,加仓!那么,这个突破怎么确定呢?我们需要用到唐奇安通道的方法进行处理。
    唐奇安通道
    在海龟的系统的止盈止损中,实际上就是借助了唐奇安通道。那么,这唐奇安通道究竟是个什么东西呢?

    首先引入上线中线下线的概念。上线=Max(前N个交易日的最高价),下线=Min(前N个交易日的最低价),中线=(上线+下线)/2,每个交易日结束之后更新当天的数据。这里N一般默认取20。那么唐奇安通道就是这个上线和下线所形成的走势区间。所谓的突破,也就是指今日盘中股价高过了上线。参见下图:
    0_1530547564093_6.png

    这里有个小插曲,为什么默认的N是20呢?这有个典故——神奇数字。Donchian在开发唐奇安通道的期间,碰巧阅读到整形外科医生Maxwel Maltz博士在1960年所作的“心理控制论”(这本书在1989年被重新发现)。Maltz博士称在整形外科手术过程中,患者最少需要21日来看到自己的新的容颜。这一事实震惊了Donchian,所以他也采用了这个说法。(小编也听说过,养成一个新的习惯需要21天嘛)

    实现这个策略,最好采用按分钟回测,这样可以准确的捕捉日内的买卖点,否则等日线的收盘价出来,说不定已经离突破很远了。同时请注意,在以往国外的实战当中,主要是在纽约和芝加哥的场内期货交易的,期货可以做多也可以做空,但是国内的股票只能买入和卖出,因此我们只能做向上突破。

    止损

    有了唐奇安通道,我们有了买入和卖出的依据了, 那么止损是干什么的呢?其实止损提出的初衷是,如果某笔交易是亏损的交易,造成的损失不要超过总仓位的k%。在完整的海龟系统里面,海龟用了一系列的公式进行仓位比例的计算,具体的内容可以参考下一节。

    完整的海龟交易系统

    完整的海龟交易系统包含以下内容:
    1、市场:原版海龟选择交易纽约和芝加哥的场内期货。筛选标准则是高流动性,我大A股市场当然也符合这个标准啦。

    2、仓位:这可以说是海龟交易系统最核心的部分。Richard Dennis期望通过市场的波动性水平来管理仓位。其构建了指数N来衡量波动性水平。指数的构建为以下四步
    (注:如果暂时不能理解下面的公式,完全不用担心,这些都在代码中体现出来,大家可以在代码的实际使用中搞明白这些麻烦的公式)。

    (1)True Range

    TrueRange=Maximum(H−L,H−PDC,PDC−L)
    TrueRange=Maximum(H−L,H−PDC,PDC−L)
    公式中,True Range表示一天内的波动量,H为当日日内最高价,L为当日日内最低价,PDC为前一日收盘价。

    (2)N

    N=19∗PDN+TR20
    N=19∗PDN+TR20
    公式中,TR为True Range,即一天内波动量,PDN为前一日的N值。此公式的真是含义为计算之前20天(包括今天在内)的N的平均值

    (3)Dollar Volatility

    DollarVolatility=N∗DollarsPerPoint
    DollarVolatility=N∗DollarsPerPoint
    公式中,Dollar Volatility指的是波动的价格,Dollars per Point指的是标的股票每波动一个最小单位,1手股票的总价格变化量。在国内最小变化量是0.01元,1手是100股。所以Dollars per Point就是0.01×100=1

    (4)Unit

    Unit=1%ofAccountMarketDollarVolatility
    Unit=1%ofAccountMarketDollarVolatility
    公式中,Unit即为我们买卖的单位,1% of Account是总资产的1%,Market Dollar Volatility就是我们之前算出的Dollar Volatility,通过此公式计算出的Unit就是我们要买入的单位数量。此公式的意义是在一般情况下(市场波动率不大的时候),如果买入1Unit单位的资产,当天震幅使得总资产的变化不超过1%

    3、入市:海龟将所有资金分为两部分,一部分资金按系统一执行,一部分资金按系统二执行
    系统一
    (1)若当前价格高于过去20日的最高价,则买入一个Unit(注意是分钟回测)
    (2)加仓:若股价在上一次买入(或加仓)的基础上上涨了0.5N,则加仓一个Unit
    系统二
    与系统一相一致,但当如破55日最高价时才购买
    (1)若当前价格高于过去55日的最高价,则买入一个Unit(注意是分钟回测)
    (2)加仓:若股价在上一次买入(或加仓)的基础上上涨了0.5N,则加仓一个Unit
    Example:若某只股票A的N为2,20日最高价为100
    则当股价突破100时买入一个Unit,当股价突破100+0.5×2=101时加仓一个Unit,当股价突破101+0.5×2=102时加仓一个Unit。

    4、止损:即损失达到多少时就一定要卖出现有仓位。海龟交易系统规定,当价格比最后一次买入价格下跌2N时,则卖出全部头寸止损(也就是,在一般情况下,损失不会超过2%)。

    5、止盈:
    系统一
    当股价跌破10日内最低价时(10日唐奇安通道下沿),清空头寸结束本次交易
    系统二
    当股价跌破20日内最低价时(20日唐奇安通道下沿),清空头寸结束本次交易

    6、技巧:资金的调整。开始时设定两个比例:Loss和Adjust。若交易结束后损失的资金占总资金比例大于Loss,则今后只用现有投资资金的Adjust比例。
    Example:若初始资金为100万,设定Loss=80%,Adjust=90%。则当总资产低于100×80%=80万时,进行一次资金调整,以后只使用80×90%=72万的资金用于投资行为

    # coding=utf-8
    from __future__ import print_function, absolute_import, unicode_literals
    import numpy as np
    import pandas as pd
    try:
        import talib
    except:
        print('请安装TA-Lib库')
    from gm.api import *
    '''
    本策略通过计算CZCE.FG801和SHFE.rb1801的ATR.唐奇安通道和MA线,并:
    上穿唐奇安通道且短MA在长MA上方则开多仓,下穿唐奇安通道且短MA在长MA下方则开空仓
    若有 多/空 仓位则分别:
    价格 跌/涨 破唐奇安平仓通道 上/下 轨则全平仓位,否则
    根据 跌/涨 破持仓均价 -/+ x(x=0.5,1,1.5,2)倍ATR把仓位
    回测数据为:CZCE.FG801和SHFE.rb1801的1min数据
    回测时间为:2017-09-15 09:15:00到2017-10-01 15:00:00
    '''
    def init(context):
        # context.parameter分别为唐奇安开仓通道.唐奇安平仓通道.短ma.长ma.ATR的参数
        context.parameter = [55, 20, 10, 60, 20]
        context.tar = context.parameter[4]
        # context.goods交易的品种
        context.goods = ['CZCE.FG801', 'SHFE.rb1801']
        # context.ratio交易最大资金比率
        context.ratio = 0.8
        # 订阅context.goods里面的品种, bar频率为1min
        subscribe(symbols=context.goods, frequency='60s', count=101)
        # 止损的比例区间
    def on_bar(context, bars):
        bar = bars[0]
        symbol = bar['symbol']
        recent_data = context.data(symbol=symbol, frequency='60s', count=101, fields='close,high,low')
        close = recent_data['close'].values[-1]
        # 计算ATR
        atr = talib.ATR(recent_data['high'].values, recent_data['low'].values, recent_data['close'].values,
                        timeperiod=context.tar)[-1]
        # 计算唐奇安开仓和平仓通道
        context.don_open = context.parameter[0] + 1
        upper_band = talib.MAX(recent_data['close'].values[:-1], timeperiod=context.don_open)[-1]
        context.don_close = context.parameter[1] + 1
        lower_band = talib.MIN(recent_data['close'].values[:-1], timeperiod=context.don_close)[-1]
        # 计算开仓的资金比例
        percent = context.ratio / float(len(context.goods))
        # 若没有仓位则开仓
        position_long = context.account().position(symbol=symbol, side=PositionSide_Long)
        position_short = context.account().position(symbol=symbol, side=PositionSide_Short)
        if not position_long and not position_short:
            # 计算长短ma线.DIF
            ma_short = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[2] + 1))[-1]
            ma_long = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[3] + 1))[-1]
            dif = ma_short - ma_long
            # 获取当前价格
            # 上穿唐奇安通道且短ma在长ma上方则开多仓
            if close > upper_band and (dif > 0):
                order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
                                     position_side=PositionSide_Long)
                print(symbol, '市价单开多仓到比例: ', percent)
            # 下穿唐奇安通道且短ma在长ma下方则开空仓
            if close < lower_band and (dif < 0):
                order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
                                     position_side=PositionSide_Short)
                print(symbol, '市价单开空仓到比例: ', percent)
        elif position_long:
            # 价格跌破唐奇安平仓通道全平仓位止损
            if close < lower_band:
                order_close_all()
                print(symbol, '市价单全平仓位')
            else:
                # 获取持仓均价
                vwap = position_long['vwap']
                # 获取持仓的资金
                money = position_long['cost']
                # 获取平仓的区间
                band = vwap - np.array([200, 2, 1.5, 1, 0.5, -100]) * atr
                grid_percent = float(pd.cut([close], band, labels=[0, 0.25, 0.5, 0.75, 1])[0]) * percent
                # 选择现有百分比和区间百分比中较小的值(避免开仓)
                target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)
                if target_percent != 1.0:
                    print(symbol, '市价单平多仓到比例: ', target_percent)
                    order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,
                                         position_side=PositionSide_Long)
        elif position_short:
            # 价格涨破唐奇安平仓通道或价格涨破持仓均价加两倍ATR平空仓
            if close > upper_band:
                order_close_all()
                print(symbol, '市价单全平仓位')
            else:
                # 获取持仓均价
                vwap = position_short['vwap']
                # 获取持仓的资金
                money = position_short['cost']
                # 获取平仓的区间
                band = vwap + np.array([-100, 0.5, 1, 1.5, 2, 200]) * atr
                grid_percent = float(pd.cut([close], band, labels=[1, 0.75, 0.5, 0.25, 0])[0]) * percent
                # 选择现有百分比和区间百分比中较小的值(避免开仓)
                target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)
                if target_percent != 1.0:
                    order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,
                                         position_side=PositionSide_Short)
                    print(symbol, '市价单平空仓到比例: ', target_percent)
    if __name__ == '__main__':
        '''
        strategy_id策略ID,由系统生成
        filename文件名,请与本文件名保持一致
        mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
        token绑定计算机的ID,可在系统设置-密钥管理中生成
        backtest_start_time回测开始时间
        backtest_end_time回测结束时间
        backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
        backtest_initial_cash回测初始资金
        backtest_commission_ratio回测佣金比例
        backtest_slippage_ratio回测滑点比例
        '''
        run(strategy_id='strategy_id',
            filename='main.py',
            mode=MODE_BACKTEST,
            token='token_id',
            backtest_start_time='2017-09-15 09:15:00',
            backtest_end_time='2017-10-01 15:00:00',
            backtest_adjust=ADJUST_PREV,
            backtest_initial_cash=10000000,
            backtest_commission_ratio=0.0001,
            backtest_slippage_ratio=0.0001)
    

 








  • 0_1558330551804_TIM截图20190520133517.png

    点击进入课程地址 适用人群

    面向对数字货币程序化感兴趣的初学者,需要有一定的实盘交易和简单的计算机基础。

    课程概述
    数字货币交易市场由于其特殊性越来越受到量化交易者的关注,实际上程序化交易已经是数字货币的主流,对冲做市等策略无时无刻不在活跃着市场。而编程基础薄弱的初学者想要进入这一领域,面对众多的交易所和多变的API,困难重重。发明者(FMZ)量化平台(原BotV)是目前最大的数字货币量化社区和平台,4年多来帮助成千上万的初学者走向了量化交易之路。
    本课程由发明者量化平台官方提供,将涵盖以下内容:
    1.数字货币量化交易简介(已更新)
    2.JavaScript快速入门(已更新)
    3.发明者量化交易平台使用指南(已更新)
    4.发明者量化交易平台编程指南(已更新)
    5.量化交易策略范例详解(已更新)

    据说后面会更新python 的相关入门教程。课程很便宜,适合对量化不懂想有个概念的群体学习。

    如果要说自己拥有一套盈利的量化策略,还是要走很长的学习路。各位加油!

    讨论群:482548322

    阅读更多
  • FXKUNLUN 昆仑国际操盘团队 2019年3月收益报告ℹ 观摩账户地址 (本观摩账户为FX110监管实盘账户-平台KVB昆仑国际) 💹 KVB开户地址 点击链接 ⏺ 4月份 净值收益 9.9% ⏺ 4月份 资金最大回撤率 0.82% ⏺ 4月份 交易准确率 80.08%

    0_1556673557669_1.png

    0_1556673565305_2.png

    0_1556673571653_3.png

    0_1556673578903_4.png

    阅读更多

暂无主题。