克隆策略

导语:商品期货分钟交易上线啦!听闻这个消息的小编当然坐不住了,决定立刻商品期货走一波! 本文选择实现的是经典的卡夫曼自适应移动均线交易系统,让我们来看看在商品期货中的应用吧!

背景知识

技术分析往往离不开均线系统,它是我们观察价格走势的基础。短期均线贴近价格走势,灵敏度高,但会有很多噪声, 产生虚假信号;长期均线在判断趋势上一般比较准确,但是长期均线有着严重滞后的问题。我们想得到这样的均线, 当价格沿一个方向快速移动时,短期的移动平均线是最合适的;当价格在横盘的过程中,长期移动平均线是合适的。

为了达到上述目的,我们选择了卡夫曼自适应移动均线。

价格方向

价格方向被表示为整个时间段中的净价格变化。比如,使用n天的间隔(或n小时):

$$d_t = p_t – p_{t-n}$$

其中,$d_t$是当前价格差或方向数值,$p_t$是时间t的价格。

波动性

波动性是市场噪音的总数量,它可以用许多不同的方法定义,但是这个计算使用了所有“日到日”或“小时到小时”的价格变化的总和 (每一个都作为一个正数),在同样的n个周期上。如下定义: $$vol = \sum_{t \in \mathcal{W}} |p_t – p_{t-1}|$$ 其中,vol是指波动性数值,$|\cdot|$表示绝对值,$\sum$后面的表示滑动窗口求和。

效率系数(ER)

以上两个成分被组合起来,以表达方向移动对噪音之比,称之为效率系数,ER: $$ER = \frac{d}{vol}$$ 用“方向性”除以“噪音”,该系数的值就从0到1 变化。当市场在全部n日以同一方向移动时,则方向=波动性,效率系数=1。如果波动对于同样的价格移动是增加了,“波动性”就变得较大并且ER往小于1的方向移动。如果价格不变化,则方向=0,ER=0。 这个结果作为一个指数式平滑系数是方便的,它每天改变趋势线的一个百分比,ER=1就等效于100%,对应最快的移动平均线,它应当能有效工作,因为价格在一个方向上移动而没有回撤。当ER=0时,一个非常慢的移动平均值是最好的,可以在市场趋势不明时避免贸然止损离场。

变换上述系数为趋势速度

为了应用于一个指数式移动平均值,比率将被变换为一个平滑系数c,依靠下面的公式,每天的均线速度可以简单地用改变平滑系数来改变,成为自适应性的。该公式如下: $$EXPMA_t = EXPMA_{t-1} + c*(p – EXPMA_{t-1})$$ 测试表明,平方平滑系数的数值大大地改进了结果,这是依靠在一个横盘的市场中阻止了趋势线的移动。 在横盘的市场中这个过程选择了非常慢的趋势,而在高度趋势化的周期中加速至非常快的趋势(但不是100%)。这个平滑系数是: \begin{align*} fastest &= 2/(N_f+1) = 2/(2+1) = 0.6667\\ slowest &= 2/(N_s+1) = 2/(30+1) = 0.0645\\ smooth &= ER \cdot (fastest - slowest) + slowest\\ c &= smooth^2 \end{align*} 平方平滑系数迫使c的数值趋向于零。这意味着较慢的移动平均线将比快速移动平均值用得更多。这和在出现不确定状况时你就更加保守是一样的道理。 于是,我们最终的卡夫曼自适应移动均线AMA如下定义:

$$AMA_t = AMA_{t-1} + c \cdot (p – AMA_{t-1})$$

自调节式过滤器设计

为了与系统的自适应特性相一致,当价格波动变得更多或更少时,过滤器也要相应取较大或较小值。为了完成这点,过滤器被定义为AMA变化的一个小的百分数:

$$filter = percentage \cdot std(AMA_t-AMA_{t-1}, n)$$

其中,std(series, n)是滑动标准差函数。

最小的过滤器百分数0.1可被用于较快的交易,而较大的百分数1.0将可以选择出更有意义的价格移动的交易。 典型例证是:外汇和期货市场交易较快,股票和利率市场交易较慢。通常,过滤器大小是依据20天周期的数据来计算。

交易规则

当AMA - min(AMA, n) > filter,买入;

当max(AMA, n) – AMA > filter,卖出。

In [110]:
import talib as ta
# 1. 策略基本参数

start_date = '2018-04-20 09:01:00'
end_date = '2018-05-30 15:15:00'
benchmark = 'RB1901.SHF'
instruments = 'RB1901.SHF'

# 起始资金
capital_base = 50000

# 回测频率 daily or minute
data_frequency = 'minute'

# 2. 策略主体函数

# 初始化虚拟账户状态,只在第一个交易日运行
def initialize(context):
    
    # 设置手续费,买入时万3,卖出是千分之1.3,不足5元以5元计
    context.set_commission(futures_commission=PerContract(cost={'RB':(0.000045, 0.000045, 0.000045)}))
    context.set_margin('RB', 0.07)
    context.index = 1              #日期记录
    context.set_need_settle(False) #逐日结算开关设置
    
    #设置参数
    context.window = 60
# 策略交易逻辑,handle_data函数会每个周期(日/分)运行一次,可以把行情数据理解成K线,
# 然后handle_data函数会在每个K线上依次运行
def handle_data(context, data):
    today = data.current_dt#.strftime('%Y-%m-%d-%H-%M')
    if context.index < context.window: # 在形成均线后才开始交易
        context.index+=1
        return
    if today.hour > 15:
        return
    
    instrument = context.future_symbol(context.instruments[0]) # 交易标的
    curr_position = context.portfolio.positions[instrument].amount # 持仓数量
    price = data.history(instrument, 'close', context.window, '1m') # 历史价格

    if np.any(np.isnan(price)):
        return

    n=40
    kama = ta.KAMA(price, timeperiod=n)
    ft = 0.8*np.std((kama-kama.shift(1))[-n:])
    
    if kama[-1] - np.min(kama[-n:]) > ft:
        context.order_target(instrument, 3)
    if np.max(kama[-n:]) - kama[-1] > ft:
        context.order_target(instrument, -3) 

# 3. 启动回测
m = M.trade.v4(
    instruments=instruments,
    start_date=start_date,
    end_date=end_date,
    initialize=initialize,
    handle_data=handle_data,
    # 股票买入的时候,假设以次日开盘价成交
    order_price_field_buy='open',
    # 股票卖出的时候,假设以次日开盘价成交
    order_price_field_sell='open',
    capital_base=capital_base,
    benchmark=benchmark,
    volume_limit=0,
    data_frequency=data_frequency,
    product_type='future',
    m_deps=np.random.rand()
)
[2018-09-05 01:59:19.423564] INFO: bigquant: backtest.v8 开始运行..
[2018-09-05 01:59:19.425709] INFO: bigquant: biglearning backtest:V8.0.7
[2018-09-05 01:59:19.426363] INFO: bigquant: product_type:future by specified
[2018-09-05 01:59:29.549358] INFO: bigquant: reading settle price
[2018-09-05 01:59:32.179507] INFO: algo: TradingAlgorithm V1.2.8
[2018-09-05 02:00:30.851244] INFO: Performance: Simulated 27 trading days out of 27.
[2018-09-05 02:00:30.852173] INFO: Performance: first open: 2018-04-20 09:01:00+00:00
[2018-09-05 02:00:30.852787] INFO: Performance: last close: 2018-05-30 15:00:00+00:00
  • 收益率14.76%
  • 年化收益率261.4%
  • 基准收益率3.63%
  • 阿尔法1.23
  • 贝塔0.14
  • 夏普比率6.66
  • 胜率0.37
  • 盈亏比1.36
  • 收益波动率19.15%
  • 信息比率0.24
  • 最大回撤2.18%
[2018-09-05 02:00:38.696703] INFO: bigquant: backtest.v8 运行完成[79.273106s].
In [ ]:
 
In [ ]: