1. # coding=utf-8
      2. from __future__ import print_function, absolute_import, unicode_literals
      3. import numpy as np
      4. import pandas as pd
      5. try:
      6. import talib
      7. except:
      8. print('请安装TA-Lib库')
      9. from gm.api import *
      10. '''
      11. 本策略通过计算CZCE.FG801和SHFE.rb1801的ATR.唐奇安通道和MA线,并:
      12. 上穿唐奇安通道且短MA在长MA上方则开多仓,下穿唐奇安通道且短MA在长MA下方则开空仓
      13. 若有 多/空 仓位则分别:
      14. 价格 跌/涨 破唐奇安平仓通道 上/下 轨则全平仓位,否则
      15. 根据 跌/涨 破持仓均价 -/+ x(x=0.5,1,1.5,2)倍ATR把仓位
      16. 回测数据为:CZCE.FG801和SHFE.rb1801的1min数据
      17. 回测时间为:2017-09-15 09:15:00到2017-10-01 15:00:00
      18. '''
      19. def init(context):
      20. # context.parameter分别为唐奇安开仓通道.唐奇安平仓通道.短ma.长ma.ATR的参数
      21. context.parameter = [55, 20, 10, 60, 20]
      22. context.tar = context.parameter[4]
      23. # context.goods交易的品种
      24. context.goods = ['CZCE.FG801', 'SHFE.rb1801']
      25. # context.ratio交易最大资金比率
      26. context.ratio = 0.8
      27. # 订阅context.goods里面的品种, bar频率为1min
      28. subscribe(symbols=context.goods, frequency='60s', count=101)
      29. # 止损的比例区间
      30. def on_bar(context, bars):
      31. bar = bars[0]
      32. symbol = bar['symbol']
      33. recent_data = context.data(symbol=symbol, frequency='60s', count=101, fields='close,high,low')
      34. close = recent_data['close'].values[-1]
      35. # 计算ATR
      36. atr = talib.ATR(recent_data['high'].values, recent_data['low'].values, recent_data['close'].values,
      37. timeperiod=context.tar)[-1]
      38. # 计算唐奇安开仓和平仓通道
      39. context.don_open = context.parameter[0] + 1
      40. upper_band = talib.MAX(recent_data['close'].values[:-1], timeperiod=context.don_open)[-1]
      41. context.don_close = context.parameter[1] + 1
      42. lower_band = talib.MIN(recent_data['close'].values[:-1], timeperiod=context.don_close)[-1]
      43. # 计算开仓的资金比例
      44. percent = context.ratio / float(len(context.goods))
      45. # 若没有仓位则开仓
      46. position_long = context.account().position(symbol=symbol, side=PositionSide_Long)
      47. position_short = context.account().position(symbol=symbol, side=PositionSide_Short)
      48. if not position_long and not position_short:
      49. # 计算长短ma线.DIF
      50. ma_short = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[2] + 1))[-1]
      51. ma_long = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[3] + 1))[-1]
      52. dif = ma_short - ma_long
      53. # 获取当前价格
      54. # 上穿唐奇安通道且短ma在长ma上方则开多仓
      55. if close > upper_band and (dif > 0):
      56. order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
      57. position_side=PositionSide_Long)
      58. print(symbol, '市价单开多仓到比例: ', percent)
      59. # 下穿唐奇安通道且短ma在长ma下方则开空仓
      60. if close < lower_band and (dif < 0):
      61. order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
      62. position_side=PositionSide_Short)
      63. print(symbol, '市价单开空仓到比例: ', percent)
      64. elif position_long:
      65. # 价格跌破唐奇安平仓通道全平仓位止损
      66. if close < lower_band:
      67. order_close_all()
      68. print(symbol, '市价单全平仓位')
      69. else:
      70. # 获取持仓均价
      71. vwap = position_long['vwap']
      72. # 获取持仓的资金
      73. money = position_long['cost']
      74. # 获取平仓的区间
      75. band = vwap - np.array([200, 2, 1.5, 1, 0.5, -100]) * atr
      76. grid_percent = float(pd.cut([close], band, labels=[0, 0.25, 0.5, 0.75, 1])[0]) * percent
      77. # 选择现有百分比和区间百分比中较小的值(避免开仓)
      78. target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)
      79. if target_percent != 1.0:
      80. print(symbol, '市价单平多仓到比例: ', target_percent)
      81. order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,
      82. position_side=PositionSide_Long)
      83. elif position_short:
      84. # 价格涨破唐奇安平仓通道或价格涨破持仓均价加两倍ATR平空仓
      85. if close > upper_band:
      86. order_close_all()
      87. print(symbol, '市价单全平仓位')
      88. else:
      89. # 获取持仓均价
      90. vwap = position_short['vwap']
      91. # 获取持仓的资金
      92. money = position_short['cost']
      93. # 获取平仓的区间
      94. band = vwap + np.array([-100, 0.5, 1, 1.5, 2, 200]) * atr
      95. grid_percent = float(pd.cut([close], band, labels=[1, 0.75, 0.5, 0.25, 0])[0]) * percent
      96. # 选择现有百分比和区间百分比中较小的值(避免开仓)
      97. target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)
      98. if target_percent != 1.0:
      99. order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,
      100. position_side=PositionSide_Short)
      101. print(symbol, '市价单平空仓到比例: ', target_percent)
      102. if __name__ == '__main__':
      103. '''
      104. strategy_id策略ID,由系统生成
      105. filename文件名,请与本文件名保持一致
      106. mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
      107. token绑定计算机的ID,可在系统设置-密钥管理中生成
      108. backtest_start_time回测开始时间
      109. backtest_end_time回测结束时间
      110. backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
      111. backtest_initial_cash回测初始资金
      112. backtest_commission_ratio回测佣金比例
      113. backtest_slippage_ratio回测滑点比例
      114. '''
      115. run(strategy_id='strategy_id',
      116. filename='main.py',
      117. mode=MODE_BACKTEST,
      118. token='token_id',
      119. backtest_start_time='2017-09-15 09:15:00',
      120. backtest_end_time='2017-10-01 15:00:00',
      121. backtest_adjust=ADJUST_PREV,
      122. backtest_initial_cash=10000000,
      123. backtest_commission_ratio=0.0001,
      124. backtest_slippage_ratio=0.0001)

    海龟交易法(股票)

    原文: https://www.myquant.cn/docs/python_strategyies/110