成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用 Python 實現隨機相對強弱指數 StochRSI

開發 后端
隨機相對強弱指數簡稱為StochRSI,是一種技術分析指標,用于確定資產是否處于超買或超賣狀態,也用于確定當前市場的態勢。

[[424742]]

 Python中文社區(ID:python-china)

隨機相對強弱指數簡稱為StochRSI,是一種技術分析指標,用于確定資產是否處于超買或超賣狀態,也用于確定當前市場的態勢。顧名思義,StochRSI是標準相對強弱指數(RSI)的衍生,因此被視為是一種能夠衡量指數的指數。它是一種振蕩器,在中心線的上方和下方波動。

StochRSI最初是在1994年由Stanley Kroll和Tushar Chande撰寫的題為《The NewTechnical Trader》的書中描述。它經常被股票交易者使用。

StochRSI如何運作?

通過應用隨機振蕩器生成公式,從標準RSI生成StochRSI。其生成結果是單個數字評級,圍繞中心線(0.5)在0-1的值域范圍內上下擺動。但是,StochRSI的修改版本將結果乘以100,因此該值是介于0和100之間而不是0和1之間。通常還會參考3天內的簡單移動平均線(SMA)以及StochRSI趨勢,作為信號線,旨在降低虛假信號交易的風險。

標準隨機震蕩指數公式取決于資產的收盤價以及設定周期內的最高價和最低價。但是,當使用公式計算StochRSI時,它直接使用RSI數據(不考慮價格)。

Stoch RSI = (Current RSI - Lowest RSI)/(Highest RSI - Lowest RSI)

與標準RSI一樣,StochRSI使用的最常見時間周期為14。StochRSI計算中涉及的14個周期基于圖表時間范圍。因此,每日圖表會顯示過去14天(K線圖),每小時圖表會顯示過去14小時生成的StochRSI。

周期可以設置為幾天、幾小時甚至幾分鐘,并且它們的使用方式也因交易者而異(根據他們的情況和策略而定)。還可以向上或向下調整周期數,以確定長期或短期趨勢。將周期值設置為20,是StochRSI指標一個相當受歡迎的選擇。

如上所述,某些StochRSI圖表模式指定的范圍值為0到100而不是0到1。在這些圖表中,中心線為50而不是0.5。因此,通常在0.8處出現的超買信號將表示為80,而超賣信號表示為20而不是0.2。具有0-100設置的圖表可能看起來略有不同,但實際原理解釋是基本相同的。

如何使用StochRSI?

StochRSI指數如果出現在其范圍的上限和下限附近,此時的意義是最重大的。因此,該指標的主要用途是確定潛在的買入和賣出點,以及價格發生的逆轉。因此,0.2或以下的數值,會表明資產可能發生超賣,而0.8或以上的數值則表明該資產可能會發生超買。

此外,更接近中心線的數值也可以為交易者提供有關市場趨勢的信息。例如,當中心線作為支撐線并且StochRSI線穩定移動到0.5以上時,尤其是數值趨近于0.8,則可能表明其繼續看漲或呈上升趨勢。同樣,當數值始終低于0.5,趨近于0.2時,則表明下跌或呈下降趨勢趨勢。

我們將通過 Python 中的回測來介紹 RSI 和 StochRSI 這兩種方法。

基于均值回歸的StochRSI 策略

最常見的 StochRSI 策略基于均值回歸。與 RSI 一樣,StochRSI 通常使用 80 來表示做空的超買水平,使用 20 來表示要買入的超賣水平。此外,14 天的回顧和平滑期很常見。出于我們的目的,我們將堅持使用這些標準值。

現在編寫代碼,讓我們在 Python 中導入一些標準包。 

  1. import numpy as np  
  2. import pandas as pd  
  3. import matplotlib.pyplot as plt  
  4. import yfinance as yf 

接下來,我們將構建一個函數來計算我們的指標。我們將其稱為 calcStochRSI(),它將依靠一些函數來計算 RSI 和隨機振蕩器,以獲得我們選擇的指標。 

  1. def calcRSI(data, P=14):  
  2.   # Calculate gains and losses  
  3.   data['diff_close'] = data['Close'] - data['Close'].shift(1)  
  4.   data['gain'] = np.where(data['diff_close']>0,  
  5.     data['diff_close'], 0)  
  6.   data['loss'] = np.where(data['diff_close']<0,   
  7.     np.abs(data['diff_close']), 0)  
  8.   # Get initial values  
  9.   data[['init_avg_gain', 'init_avg_loss']] = data[  
  10.     ['gain', 'loss']].rolling(P)   
  11.   # Calculate smoothed avg gains and losses for all t > P  
  12.   avg_gain = np.zeros(len(data))  
  13.   avg_loss = np.zeros(len(data)) 
  14.   for i, _row in enumerate(data.iterrows()):  
  15.     row = _row[1]  
  16.     if i < P - 1:  
  17.       last_row = row.copy()  
  18.       continue  
  19.     elif i == P-1:  
  20.       avg_gain[i] += row['init_avg_gain']  
  21.       avg_loss[i] += row['init_avg_loss']  
  22.     else:  
  23.       avg_gain[i] += ((P - 1) * avg_gain[i] +  
  24.             row['gain']) / P  
  25.       avg_loss[i] += ((P - 1) * avg_loss[i] +  
  26.             row['loss']) / P          
  27.     last_row = row.copy()  
  28.   data['avg_gain'] = avg_gain  
  29.   data['avg_loss'] = avg_loss  
  30.   # Calculate RS and RSI  
  31.   data['RS'] = data['avg_gain'] / data['avg_loss']  
  32.   data['RSI'] = 100 - 100 / (1 + data['RS'])  
  33.   return data  
  34. def calcStochOscillator(data):  
  35.   data['low_N'] = data['RSI'].rolling(N).min()  
  36.   data['high_N'] = data['RSI'].rolling(N).max()  
  37.   data['StochRSI'] = 100 * (data['RSI'] - data['low_N']) / \  
  38.     (data['high_N'] - data['low_N'])  
  39.   return data  
  40. def calcStochRSI(data, P=14N=14):  
  41.   data = calcRSI(data)  
  42.   data = calcStochOscillator(data)  
  43.   return data  
  44. def calcReturns(df):  
  45.   # Helper function to avoid repeating too much code  
  46.   df['returns'] = df['Close'] / df['Close'].shift(1)  
  47.   df['log_returns'] = np.log(df['returns'])  
  48.   df['strat_returns'] = df['position'].shift(1) * df['returns']  
  49.   df['strat_log_returns'] = df['position'].shift(1) * df['log_returns']  
  50.   df['cum_returns'] = np.exp(df['log_returns'].cumsum()) - 1  
  51.   df['strat_cum_returns'] = np.exp(df['strat_log_returns'].cumsum()) - 1  
  52.   df['peak'] = df['cum_returns'].cummax()  
  53.   df['strat_peak'] = df['strat_cum_returns'].cummax()  
  54.   return df 

有了這些功能,我們只需要為我們的策略構建邏輯就可以了。還要注意,我們有一個名為 calcReturns 的輔助函數,我們可以快速將其應用于回測的結果以從中獲取所有返回值。

這意味著回歸模型將在 StochRSI 高于 80 時做空或賣出,并在低于 20 時買入。 

  1. def StochRSIReversionStrategy(data, P=14N=14short_level=80,   
  2.   buy_level=20shorts=True):  
  3.   '''Buys when the StochRSI is oversold and sells when it's overbought'''  
  4.   df = calcStochRSI(data, P, N)  
  5.   df['position'] = np  
  6.   df['position'] = np.where(df['StochRSI']<buy_level, 1, df['position'])  
  7.   if shorts:  
  8.     df['position'] = np.where(df['StochRSI']>short_level, -1, df['position'])  
  9.   else:  
  10.     df['position'] = np.where(df['StochRSI']>short_level, 0, df['position'])  
  11.   df['position'] = df['position'].ffill()  
  12.   return calcReturns(df)  
  13. table = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')  
  14. df = table[0]  
  15. syms = df['Symbol']  
  16. # Sample symbols  
  17. ticker = np.random.choice(syms.values)  
  18. ticker = "BSX"  
  19. print(f"Ticker Symbol: {ticker}")  
  20. start = '2000-01-01'  
  21. end = '2020-12-31'  
  22. # Get Data  
  23. yfyfObj = yf.Ticker(ticker)  
  24. data = yfObj.history(startstart=start, endend=end)  
  25. data.drop(['Open', 'High', 'Low', 'Volume', 'Dividends',   
  26.     'Stock Splits'], inplace=Trueaxis=1 
  27. # Run test  
  28. df_rev = StochRSIReversionStrategy(data.copy())  
  29. # Plot results  
  30. colors = plt.rcParams['axes.prop_cycle'].by_key()['color']  
  31. fig, ax = plt.subplots(2, figsize=(12, 8))  
  32. ax[0].plot(df_rev['strat_cum_returns']*100, label='Mean Reversion' 
  33. ax[0].plot(df_rev['cum_returns']*100, label='Buy and Hold' 
  34. ax[0].set_ylabel('Returns (%)')  
  35. ax[0].set_title('Cumulative Returns for Mean Reversion and' +  
  36.                 f' Buy and Hold Strategies for {ticker}')  
  37. ax[0].legend(bbox_to_anchor=[1, 0.6])  
  38. ax[1].plot(df_rev['StochRSI'], label='StochRSI'linewidth=0.5)  
  39. ax[1].plot(df_rev['RSI'], label='RSI'linewidth=1 
  40. ax[1].axhline(80, label='Over Bought'color=colors[1], linestyle=':' 
  41. ax[1].axhline(20, label='Over Sold'color=colors[2], linestyle=':' 
  42. ax[1].axhline(50, label='Centerline'color='k'linestyle=':' 
  43. ax[1].set_ylabel('Stochastic RSI')  
  44. ax[1].set_xlabel('Date')  
  45. ax[1].set_title(f'Stochastic RSI for {ticker}')  
  46. ax[1].legend(bbox_to_anchor=[1, 0.75])  
  47. plt.tight_layout()  
  48. plt.show() 

在我們研究的 21 年期間,均值回歸策略擊敗了Boston Scientific(BSX)的買入和持有策略,回報率為 28 倍,而后者為 2 倍。

在第二個圖中顯示了 StochRSI 和一些關鍵指標。我還添加了 RSI 以與更不穩定的 StochRSI 進行比較。這導致交易頻繁,如果您的賬戶較小且交易成本相對較高,這可能會嚴重影響您的實際回報。我們只是在一個工具上運行它,所以最終進行了 443 筆交易,或者每 12 天交易一次,這看起來并不多。但是,如果我們要使用該指標管理適當的工具組合并頻繁進行交易,我們每天可能會進出多筆交易,交易成本會變得很高。 

  1. # Get trades  
  2. diff = df_rev['position'].diff().dropna()  
  3. trade_idx = diff.index[np.where(diff!=0)]  
  4. fig, ax = plt.subplots(figsize=(12, 8))  
  5. ax.plot(df_rev['Close'], linewidth=1label=f'{ticker}' 
  6. ax.scatter(trade_idx, df_rev[trade_idx]['Close'], c=colors[1],   
  7.            marker='^'label='Trade' 
  8. ax.set_ylabel('Price')  
  9. ax.set_title(f'{ticker} Price Chart and Trades for' +  
  10.              'StochRSI Mean Reversion Strategy')  
  11. ax.legend()  
  12. plt.show() 

要查看整體策略的一些關鍵指標,讓我們看看使用以下 getStratStats 函數。 

  1. def getStratStats(log_returns: pd.Series, risk_free_rate: float = 0.02):  
  2.   stats = {}  
  3.   # Total Returns  
  4.   stats['tot_returns'] = np.exp(log_returns.sum()) - 1  
  5.   # Mean Annual Returns  
  6.   stats['annual_returns'] = np.exp(log_returns.mean() * 252) - 1  
  7.   # Annual Volatility  
  8.   stats['annual_volatility'] = log_returns * np.sqrt(252)  
  9.   # Sortino Ratio  
  10.   annualized_downside = log_returns.loc[log_returns<0].std() * np.sqrt(252)  
  11.   stats['sortino_ratio'] = (stats['annual_returns'] - risk_free_rate) \  
  12.     / annualized_downside  
  13.   # Sharpe Ratio  
  14.   stats['sharpe_ratio'] = (stats['annual_returns'] - risk_free_rate) \  
  15.     / stats['annual_volatility']  
  16.   # Max Drawdown  
  17.   cum_returns = log_returns.cumsum() - 1  
  18.   peak = cum_returns.cummax()  
  19.   drawdown = peak - cum_returns  
  20.   stats['max_drawdown'] = drawdown.max()  
  21.   # Max Drawdown Duration  
  22.   strat_dd = drawdown[drawdown==0]  
  23.   strat_ddstrat_dd_diff = strat_dd.index[1:] - strat_dd.index[:-1]  
  24.   strat_dd_days = strat_dd_diff.map(lambda x: x.days)  
  25.   strat_dd_days = np.hstack([strat_dd_days,   
  26.       (drawdown.index[-1] - strat_dd.index[-1]).days])  
  27.   stats['max_drawdown_duration'] = strat_dd_days.max()  
  28.   return stats  
  29. rev_stats = getStratStats(df_rev['strat_log_returns'])  
  30. bh_stats = getStratStats(df_rev['log_returns'])  
  31. pd.concat([pd.DataFrame(rev_stats, index=['Mean Reversion']),  
  32.            pd.DataFrame(bh_stats, index=['Buy and Hold'])]) 

在這里,我們看到該策略的回報率為 28 倍,而基礎資產的年度波動率大致相同。此外,根據 Sortino 和 Sharpe Ratios 衡量,我們有更好的風險調整回報。

在 2020 年的新冠疫情中,我們確實看到了均值回歸策略的潛在問題之一。該策略的總回報大幅下降,因為該策略的定位是向上回歸,但市場繼續低迷,該模型只是保持不變 . 它恢復了其中的一部分,但在這次測試中從未達到過疫情之前的高點。正確使用止損有助于限制這些巨大的損失,并有可能增加整體回報。

StochRSI 和動量策略

我們之前提到的另一個基本策略是使用 StochRSI 作為動量指標。當指標穿過中心線時,我們會根據其方向買入或做空股票。 

  1. def StochRSIMomentumStrategy(data, P=14N=14 
  2.   centerline=50shorts=True):  
  3.   '''  
  4.   Buys when the StochRSI moves above the centerline,   
  5.   sells when it moves below  
  6.   '''  
  7.   df = calcStochRSI(data, P) 
  8.   df['position'] = np.nan  
  9.   df['position'] = np.where(df['StochRSI']>50, 1, df['position'])  
  10.   if shorts: 
  11.      df['position'] = np.where(df['StochRSI']<50, -1, df['position'])  
  12.   else:  
  13.     df['position'] = np.where(df['StochRSI']<50, 0, df['position'])  
  14.   df['position'] = df['position'].ffill()  
  15.   return calcReturns(df) 

運行我們的回測: 

  1. # Run test  
  2. df_mom = StochRSIMomentumStrategy(data.copy())  
  3. # Plot results  
  4. colors = plt.rcParams['axes.prop_cycle'].by_key()['color']  
  5. fig, ax = plt.subplots(2, figsize=(12, 8))  
  6. ax[0].plot(df_mom['strat_cum_returns']*100, label='Momentum' 
  7. ax[0].plot(df_mom['cum_returns']*100, label='Buy and Hold' 
  8. ax[0].set_ylabel('Returns (%)')  
  9. ax[0].set_title('Cumulative Returns for Momentum and' +  
  10.                 f' Buy and Hold Strategies for {ticker}')  
  11. ax[0].legend(bbox_to_anchor=[1, 0.6])  
  12. ax[1].plot(df_mom['StochRSI'], label='StochRSI'linewidth=0.5)  
  13. ax[1].plot(df_mom['RSI'], label='RSI'linewidth=1 
  14. ax[1].axhline(50, label='Centerline'color='k'linestyle=':' 
  15. ax[1].set_ylabel('Stochastic RSI')  
  16. ax[1].set_xlabel('Date')  
  17. ax[1].set_title(f'Stochastic RSI for {ticker}')  
  18. ax[1].legend(bbox_to_anchor=[1, 0.75])  
  19. plt.tight_layout()  
  20. plt.show() 

在這種情況下,我們的動量策略表現非常糟糕,在我們假設的時間段內幾乎損失了我們所有的初始投資。

查看我們策略的統計數據,該模型的唯一優勢是比買入并持有方法的回撤時間略短。 

  1. mom_stats = getStratStats(df_mom['strat_log_returns'])  
  2. bh_stats = getStratStats(df_mom['log_returns'])  
  3. pd.concat([pd.DataFrame(mom_stats, index=['Momentum']),  
  4.            pd.DataFrame(rev_stats, index=['Mean Reversion']),  
  5.            pd.DataFrame(bh_stats, index=['Buy and Hold'])]) 

這并不意味著StochRSI 不適合此類應用。一次糟糕的回測并不意味著該策略毫無價值。相反,一個很好的回測并不意味著你有一些你應該立即開始交易的東西。我們需要與其他指標結合使用以改善結果。 

 

責任編輯:龐桂玉 來源: Python中文社區
相關推薦

2021-09-13 11:59:30

Python股票代碼

2017-08-28 18:41:34

PythonLogistic回歸隨機梯度下降

2016-09-12 14:05:27

PythonPython解釋器Web

2009-06-29 17:10:24

什么是JSP

2019-01-24 09:00:00

PythonAutoML機器學習

2021-07-29 13:06:29

Python機器學習編程語言

2021-03-01 08:33:39

插件庫弱符號程序

2017-03-24 08:10:01

微信指數公關媒體

2022-01-26 07:25:09

PythonRSA加解密

2021-11-01 11:15:28

Python資產代碼

2010-11-25 14:52:35

MySQL隨機查詢

2022-08-11 08:03:43

隊列

2022-07-27 08:24:44

數據庫RTOSQL

2024-08-14 14:06:01

2022-03-03 10:49:46

Python自動追蹤代碼

2022-07-27 10:39:27

Python打包工具

2023-03-09 08:12:08

免登錄實Python腳本

2019-11-06 10:56:59

Python數據分析TGI

2010-03-23 09:47:38

Python隨機數Python隨機字符串

2020-09-16 14:09:34

編程語言JavaPython
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 婷婷桃色网 | 国产一级在线视频 | 狠狠操狠狠操 | 国产伦精品一区二区三区照片91 | 在线观看免费av网站 | 午夜看电影在线观看 | 久久久久久国产精品mv | 精品国产一区久久 | 亚洲人在线| 99久久免费精品国产男女高不卡 | av免费网址 | 国产最新精品视频 | www.操com| 国产婷婷色综合av蜜臀av | 羞羞视频在线观看 | 日韩中文在线视频 | 亚洲影音先锋 | 成人激情视频免费观看 | 亚洲一区二区三区久久 | 一级片视频免费观看 | 欧美日韩一区二区在线观看 | 成人深夜小视频 | 天天射影院| 免费精品 | 日韩欧美天堂 | 午夜视频在线 | 91综合在线观看 | 精品国产91乱码一区二区三区 | 欧美视频精品 | 亚洲高清在线观看 | 亚洲三区在线观看 | 久久国产区 | 亚洲一区二区三区高清 | 欧美人妇做爰xxxⅹ性高电影 | 国产亚洲欧美另类一区二区三区 | 精品中文字幕一区二区三区 | 国产黄色网址在线观看 | 亚洲成人精品 | 亚洲一区二区在线播放 | 日本高清中文字幕 | 中文字幕一区二区三区不卡 |