BOLL指標是美國股市分析家約翰·布林根據統計學中的標準差原理設計出來的一種非常簡單實用的技術分析指標。一般而言,股價的運動總是圍繞某一價值中樞(如均線、成本線等)在一定的範圍內變動,布林線指標正是在上述條件的基礎上,引進了“股價通道”的概念,其認爲股價通道的寬窄隨着股價波動幅度的大小而變化,而且股價通道又具有變異性,它會隨着股價的變化而自動調整。由於之前大部分交易策略都是選股或者趨勢追蹤的擇時,所以基於這一指標我們設計了一個均值迴歸的交易策略。
策略邏輯:行情大部分時候都在震盪,所以均值迴歸可以盈利。
策略內容:當價格觸及布林線上軌的時候進行賣出,當觸及下軌的時候,進行買入。
資金管理:每次100股
源代碼:
# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *
"""
本策略採用布林線進行均值迴歸交易。當價格觸及布林線上軌的時候進行賣出,當觸及下軌的時候,進行買入。
使用600004在 2009-09-17 13:00:00 到 2020-03-21 15:00:00 進行了回測。
注意:
1:實盤中,如果在收盤的那一根bar或tick觸發交易信號,需要自行處理,實盤可能不會成交。
"""
# 策略中必須有init方法
def init(context):
""" init函數是在策略開始運行時被調用,進行初始化工作的函數"""
# 設置布林線的三個參數
context.maPeriod = 26 # 計算BOLL布林線中軌的參數
context.stdPeriod = 26 # 計算BOLL 標準差的參數
context.stdRange = 1 # 計算BOLL 上下軌和中軌距離的參數
# 設置要進行回測的合約 合約名稱寫法詳見 https://www.myquant.cn/docs/python/python_concept#44e233ec21d880c2
# 或者可以在掘金終端的仿真交易中輸入這個代碼看是否查詢的是需要的標的
context.symbol = 'SHSE.600004' # 訂閱&交易標的, 此處訂閱的是600004
context.period = max(context.maPeriod, context.stdPeriod, context.stdRange) + 1 # 訂閱數據滑窗長度
# 滑窗指的是每次從最新的行情往回取一定週期的數據, 相當於行情軟件中k線圖一個屏所容納的k線
# 訂閱行情 第一個參數是標的, 第二個是時間週期,表示日線,第三個指指定設置count參數,表示需要的滑窗大
# 詳見 https://www.myquant.cn/docs/python/python_subscribe#15ad56f8be8519c0
subscribe(symbols= context.symbol, frequency='1d', count=context.period)
def on_bar(context, bars):
"""
當init中subscribe訂閱過的標的的k線完成的時候,on_bar 會被調用,用來處理計算和交易下單邏輯
詳見 https://www.myquant.cn/docs/python/python_data_event#b198d6b609adb1d4
"""
# 獲取數據滑窗,只要在init裏面有訂閱,在這裏就可以取的到, 返回值是pandas.DataFrame的數據結構
data = context.data(symbol=context.symbol, frequency='1d', count=context.period, fields='close')
# 計算boll的上下界
bollUpper = data.close.rolling(context.maPeriod).mean() \
+ context.stdRange * data.close.rolling(context.stdPeriod).std()
bollBottom = data.close.rolling(context.maPeriod).mean() \
- context.stdRange * data.close.rolling(context.stdPeriod).std()
# 獲取現有持倉
pos = context.account().position(symbol=context.symbol, side=PositionSide_Long)
# 交易邏輯與下單
# 當有持倉,且股價穿過BOLL上界的時候賣出股票。
if data.close.values[-1] > bollUpper.values[-1] and data.close.values[-2] < bollUpper.values[-2]:
if pos: # 有持倉就市價賣出股票。
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Sell,
order_type=OrderType_Market, position_effect=PositionEffect_Close)
print('以市價單賣出一手')
# 當沒有持倉,且股價穿過BOLL下界的時候買出股票。
elif data.close.values[-1] < bollBottom.values[-1] and data.close.values[-2] > bollBottom.values[-2]:
if not pos: # 沒有持倉就買入一百股。
order_volume(symbol=context.symbol, volume=100, side=OrderSide_Buy,
order_type=OrderType_Market, position_effect=PositionEffect_Open)
print('以市價單買入一手')
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='2009-09-17 13:00:00',
backtest_end_time='2020-03-21 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=1000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001)
最終回測結果:
迴歸策略最終也跑贏了指數,但是需要注意,這只是在現在沒用什麼大行情的情況下適用,如果出現了大牛市,還是需要小心使用爲好。
聲明:本文僅供交流與探討,不夠成任何投資建議,否則後果自負!