【Python量化】布林带策略
文章目錄
- 一、計算布林帶
- 三、構建策略,計算持倉頭寸序列和買賣信號序列
- 四、計算策略收益
- 五、繪制交易信號
布林帶(BOLL)指標是美國股市分析家約翰·布林根據統計學中的標準差原理設計出來的一種非常簡單實用的技術分析指標。一般而言,股價的運動總是圍繞某一價值中樞(如均線、成本線等)在一定的范圍內變動,布林線指標正是在上述條件的基礎上,引進了“股價通道”的概念,其認為股價通道的寬窄隨著股價波動幅度的大小而變化,而且股價通道又具有變異性,它會隨著股價的變化而自動調整。
一、計算布林帶
首先我們導入相關庫。
import pandas as pd import numpy as np from matplotlib import pyplot as plt接下來編寫一個函數來計算我們的布林帶。
- 中軌:股價的平均成本,N時間段的簡單移動平均
- 上軌:壓力線,上軌 = 中軌 + K × N時間段的標準差
- 下軌:支撐線,下軌 = 中軌 ? K × N時間段的標準差
我們以SPY數據為例,csv文件地址如下:鏈接:https://pan.baidu.com/s/1uqX_F07q28SaYMtosque3w ,提取碼:vwi2。
我們讀取SPY價格數據。
df = pd.read_csv(r'C:\Users\mi\Desktop\SPY.csv') df = df.set_index('Date')數據如下:
>>>dfOpen High ... Adj Close Volume Date ... 2021-08-10 442.609985 443.440002 ... 436.474243 43339300 2021-08-11 443.820007 443.880005 ... 437.558807 44034300 2021-08-12 443.619995 445.260010 ... 438.870117 38909400 2021-08-13 445.589996 445.940002 ... 439.668823 39470300 2021-08-16 444.529999 447.109985 ... 440.704102 73740000... ... ... ... ... 2022-08-04 414.369995 415.089996 ... 414.170013 45656600 2022-08-05 409.660004 414.149994 ... 413.470001 56755600 2022-08-08 415.250000 417.619995 ... 412.989990 53886100 2022-08-09 412.220001 412.750000 ... 411.350006 44840500 2022-08-10 418.779999 420.040009 ... 419.276886 30838744[253 rows x 6 columns]我們以SPY數據為例,計算其布林帶。
df = calculate_bollinger_bands(df, 10, 2, 'Adj Close') #計算布林帶數據如下:
>>>dfOpen High ... UpperBound LowerBound Date ... 2021-08-10 442.609985 443.440002 ... NaN NaN 2021-08-11 443.820007 443.880005 ... NaN NaN 2021-08-12 443.619995 445.260010 ... NaN NaN 2021-08-13 445.589996 445.940002 ... NaN NaN 2021-08-16 444.529999 447.109985 ... NaN NaN... ... ... ... ... 2022-08-04 414.369995 415.089996 ... 421.151341 388.468666 2022-08-05 409.660004 414.149994 ... 422.323881 390.972127 2022-08-08 415.250000 417.619995 ... 422.553138 394.226867 2022-08-09 412.220001 412.750000 ... 418.489248 402.382755 2022-08-10 418.779999 420.040009 ... 419.151863 405.367516[253 rows x 10 columns]繪制的布林帶圖形如下:
三、構建策略,計算持倉頭寸序列和買賣信號序列
策略的關鍵是得到持倉頭寸序列和買賣信號序列。
布林帶策略有多種。
(1)均值回歸策略
布林線均值回歸策略認為,標的價格在上軌線和下軌線圍成的范圍內浮動,即使短期內突破上下軌,但長期內仍然會回歸到布林帶之中。因此,一旦突破上下軌,即形成買賣信號。
我們可構建策略1:
當股價由下向上穿過上軌的時候,做空;然后由上向下穿過中軌的時候,平倉。
當股價由上向下穿過下軌的時候,做多;然后由下向上穿過中軌的時候,平倉。
def calculate_strategy1_position(df): '''策略1:均值回歸策略當收盤價由下向上穿過上軌的時候,做空;然后由上向下穿過中軌的時候,平倉。當收盤價由上向下穿過下軌的時候,做多;然后由下向上穿過中軌的時候,平倉。''' xs = (df.Observation - df.RollingMean) / (df.Observation.shift(1) - df.RollingMean.shift(1))df['position'] = np.nan df['position'] = np.where(df.Observation<df.LowerBound, 1,df['position']) df['position'] = np.where(df.Observation>df.UpperBound ,-1,df['position']) df['position'] = np.where(xs<0, 0, df['position'])df['position'] = df['position'].ffill().fillna(0) #買入開倉long_entry_condition = (df['position']==1) & (df['position'].shift(1)!=1)df.loc[long_entry_condition,'signal_long'] = 1#賣出平倉long_exit_condition = (df['position']!=1) &(df['position'].shift(1)==1)df.loc[long_exit_condition,'signal_long'] = 0#賣出開倉short_entry_condition = (df['position']==-1) & (df['position'].shift(1)!=-1)df.loc[short_entry_condition,'signal_short'] = -1#買入平倉short_exit_condition = (df['position']!=-1) & (df['position'].shift(1)==-1)df.loc[short_exit_condition,'signal_short'] = 0return df(2)趨勢性交易策略
布林線趨勢性交易策略略認為,標的價格在上軌線和下軌線圍成的范圍內浮動,如果突破上軌,通常認為產生上漲趨勢,做多;如果突破下軌,通常認為產生下跌趨勢,做空。因此,一旦突破上下軌,即形成買賣信號。
我們可構建策略2:
當股價由下向上穿過上軌的時候,做多;然后由上向下穿過上軌的時候,平倉。
當股價由上向下穿過下軌的時候,做空;然后由下向上穿過下軌的時候,平倉。
策略3:
當股價由下向上穿過上軌的時候,做多;然后由上向下穿過中軌的時候,平倉。
當股價由上向下穿過下軌的時候,做空;然后由下向上穿過中軌的時候,平倉。
def calculate_strategy2_position(df): '''-------策略2:當收盤價由下向上穿過上軌的時候,做多;然后由上向下穿過上軌的時候,平倉。當收盤價由上向下穿過下軌的時候,做空;然后由下向上穿過下軌的時候,平倉。'''#position : 持倉頭寸,多倉為1,不持倉為0,空倉為-1#siganal : 交易信號,做多為1,平倉為0,做空為-1df['position'] = np.where(df.Observation > df.UpperBound, 1, 0) df['position'] = np.where(df.Observation < df.LowerBound, -1, df['position']) #買入開倉long_entry_condition = (df['position']==1) & (df['position'].shift(1)!=1)df.loc[long_entry_condition,'signal_long'] = 1#賣出平倉long_exit_condition = (df['position']!=1) &(df['position'].shift(1)==1)df.loc[long_exit_condition,'signal_long'] = 0#賣出開倉short_entry_condition = (df['position']==-1) & (df['position'].shift(1)!=-1)df.loc[short_entry_condition,'signal_short'] = -1#買入平倉short_exit_condition = (df['position']!=-1) & (df['position'].shift(1)==-1)df.loc[short_exit_condition,'signal_short'] = 0return dfdef calculate_strategy3_position(df): '''策略3:當收盤價由下向上穿過上軌的時候,做多;然后由上向下穿過中軌的時候,平倉。當收盤價由上向下穿過下軌的時候,做空;然后由下向上穿過中軌的時候,平倉。''' xs = (df.Observation - df.RollingMean) / (df.Observation.shift(1) - df.RollingMean.shift(1))df['position'] = np.nan df['position'] = np.where(df.Observation>df.UpperBound, 1,df['position']) #做多 df['position'] = np.where(df.Observation<df.LowerBound ,-1,df['position']) #做空 df['position'] = np.where(xs<0, 0, df['position']) #平倉df['position'] = df['position'].ffill().fillna(0) #買入開倉long_entry_condition = (df['position']==1) & (df['position'].shift(1)!=1)df.loc[long_entry_condition,'signal_long'] = 1#賣出平倉long_exit_condition = (df['position']!=1) &(df['position'].shift(1)==1)df.loc[long_exit_condition,'signal_long'] = 0#賣出開倉short_entry_condition = (df['position']==-1) & (df['position'].shift(1)!=-1)df.loc[short_entry_condition,'signal_short'] = -1#買入平倉short_exit_condition = (df['position']!=-1) & (df['position'].shift(1)==-1)df.loc[short_exit_condition,'signal_short'] = 0return df四、計算策略收益
我們可編制函數,計算市場收益率、策略收益率及策略超常收益率。注意我們的買賣信號出現后,第二天才能進行交易。
def calculate_returns(df):# 計算市場對數收益率、策略對數收益率、策略超常收益率df['market_log_returns'] = np.log(df['Observation']/df['Observation'].shift(1))df['strat_log_returns'] = df['position'].shift(1)* df['market_log_returns'] #交易信號出現后第二天交易df['abnormal_returns'] = df['strat_log_returns'] - df['market_log_returns']# 計算市場累積收益率、策略累積收益率、策略累積超常收益率df['market_cum_returns'] = np.exp(df['market_log_returns'].cumsum()) - 1df['strat_cum_returns'] = np.exp(df['strat_log_returns'].cumsum()) - 1df['abnormal_cum_returns'] = df['strat_cum_returns'] - df['market_cum_returns']# 繪圖ret = df[['market_log_returns','strat_log_returns','abnormal_returns']]ret.plot(title='Market,Strategy,and Abnormal Returns')cum_returns = df[['market_cum_returns','strat_cum_returns','abnormal_cum_returns']]cum_returns.plot(title='Cumulative Returns')return df五、繪制交易信號
我們可編制函數,將買賣信號標注在布林帶中。
def plot_bands_with_signal(df):# 繪制交易圖表#買入開倉long_entry = df.loc[df['signal_long']==1]['Observation']#賣出平倉long_exit = df.loc[df['signal_long']==0]['Observation']#賣出開倉short_entry = df.loc[df['signal_short']==-1]['Observation']#賣出平倉short_exit = df.loc[df['signal_short']==0]['Observation']fig, ax = plt.subplots(1, figsize=(15, 10), sharex=True) ax.plot(df['Observation'], label='Observation')ax.plot(df['RollingMean'], label='RollingMean')ax.plot(df['UpperBound'])ax.plot(df['LowerBound'])ax.fill_between(df.index, df['UpperBound'], df['LowerBound'],alpha=0.3, label='Bollinger Band')ax.scatter(long_entry.index, long_entry, color='r', s=100, marker='^', label='Long Entry',zorder=10)ax.scatter(long_exit.index, long_exit, color='r',s=100, marker='x', label='Long Exit',zorder=10)ax.scatter(short_entry.index, short_entry, color='b', s=100, marker='^', label='Short Entry',zorder=10)ax.scatter(short_exit.index, short_exit, color='b',s=100, marker='x', label='Short Exit',zorder=10)ax.set_title('Bollinger Band Strategy Trading Signals')ax.legend()plt.show()我們以SPY數據為例,調用上述函數。
df = pd.read_csv(r'C:\Users\mi\Desktop\SPY.csv') df = df.set_index('Date') df = calculate_bollinger_bands(df, 10, 2, 'Adj Close') #計算布林帶 # 策略1 df1 = calculate_strategy1_position(df.copy()) df1 = calculate_returns(df1) plot_bands_with_signal(df1) # 策略2 df2 = calculate_strategy2_position(df.copy()) df2 = calculate_returns(df2) plot_bands_with_signal(df2) # 策略3 df3 = calculate_strategy3_position(df.copy()) df3 = calculate_returns(df3) plot_bands_with_signal(df3)可得到策略1的收益率、累積收益率、交易信號如下圖所示:
可得到策略2的收益率、累積收益率、交易信號如下圖所示:
可得到策略3的收益率、累積收益率、交易信號如下圖所示:
歡迎關注:
Python for Finance微信公眾號
總結
以上是生活随笔為你收集整理的【Python量化】布林带策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于mysql本地计算机上的MySQL服
- 下一篇: 大厂面试干货:面试官最喜欢pick什么样