http://stockcharts.com/school/doku.php?id=chart_school:trading_strategies:rsi2
ざっくり説明を読んだところ、200日移動平均のような長いスパンの線に対して、長期の上昇を続けているまたはその逆に下がり続けているような場合に押し目を待って市場に参入する作戦だ。押し目の判定はRSIを使う
「押し目待ちに押し目なし」という格言に逆らっているようだ。
ストップロスをセットしておかないと押し目ではなく本当にブレイクしてしまうことがあるので注意。
サンプルとして掲載されていたオリジナルは2ファイルに分かれていたけど、一つにした。
でもって、ストップロスを入れていない無謀な取引
import matplotlib matplotlib.use('Agg') from pyalgotrade import strategy from pyalgotrade.technical import ma from pyalgotrade.technical import rsi from pyalgotrade.technical import cross from pyalgotrade import plotter from pyalgotrade.tools import yahoofinance from pyalgotrade.stratanalyzer import sharpe class RSI2(strategy.BacktestingStrategy): def __init__(self, feed, instrument, entrySMA, exitSMA, rsiPeriod, overBoughtThreshold, overSoldThreshold): strategy.BacktestingStrategy.__init__(self, feed) self.__instrument = instrument # We'll use adjusted close values, if available, instead of regular close values. if feed.barsHaveAdjClose(): self.setUseAdjustedValues(True) self.__priceDS = feed[instrument].getPriceDataSeries() self.__entrySMA = ma.SMA(self.__priceDS, entrySMA) self.__exitSMA = ma.SMA(self.__priceDS, exitSMA) self.__rsi = rsi.RSI(self.__priceDS, rsiPeriod) self.__overBoughtThreshold = overBoughtThreshold self.__overSoldThreshold = overSoldThreshold self.__longPos = None self.__shortPos = None def getEntrySMA(self): return self.__entrySMA def getExitSMA(self): return self.__exitSMA def getRSI(self): return self.__rsi def onEnterCanceled(self, position): if self.__longPos == position: self.__longPos = None elif self.__shortPos == position: self.__shortPos = None else: assert(False) def onExitOk(self, position): if self.__longPos == position: self.__longPos = None elif self.__shortPos == position: self.__shortPos = None else: assert(False) def onExitCanceled(self, position): # If the exit was canceled, re-submit it. position.exitMarket() def onBars(self, bars): # Wait for enough bars to be available to calculate SMA and RSI. if self.__exitSMA[-1] is None or self.__entrySMA[-1] is None or self.__rsi[-1] is None: return bar = bars[self.__instrument] if self.__longPos is not None: if self.exitLongSignal(): self.__longPos.exitMarket() elif self.__shortPos is not None: if self.exitShortSignal(): self.__shortPos.exitMarket() else: if self.enterLongSignal(bar): shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice()) self.__longPos = self.enterLong(self.__instrument, shares, True) elif self.enterShortSignal(bar): shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice()) self.__shortPos = self.enterShort(self.__instrument, shares, True) def enterLongSignal(self, bar): return bar.getPrice() > self.__entrySMA[-1] and self.__rsi[-1] <= self.__overSoldThreshold def exitLongSignal(self): return cross.cross_above(self.__priceDS, self.__exitSMA) and not self.__longPos.exitActive() def enterShortSignal(self, bar): return bar.getPrice() < self.__entrySMA[-1] and self.__rsi[-1] >= self.__overBoughtThreshold def exitShortSignal(self): return cross.cross_below(self.__priceDS, self.__exitSMA) and not self.__shortPos.exitActive() def main(plot): instrument = "DIA" entrySMA = 200 exitSMA = 5 rsiPeriod = 2 overBoughtThreshold = 90 overSoldThreshold = 10 # Download the bars. feed = yahoofinance.build_feed([instrument], 2009, 2012, ".") strat = RSI2(feed, instrument, entrySMA, exitSMA, rsiPeriod, overBoughtThreshold, overSoldThreshold) sharpeRatioAnalyzer = sharpe.SharpeRatio() strat.attachAnalyzer(sharpeRatioAnalyzer) if plot: plt = plotter.StrategyPlotter(strat, True, True, True) plt.getInstrumentSubplot(instrument).addDataSeries("Entry SMA", strat.getEntrySMA()) plt.getInstrumentSubplot(instrument).addDataSeries("Exit SMA", strat.getExitSMA()) plt.getOrCreateSubplot("rsi").addDataSeries("RSI", strat.getRSI()) plt.getOrCreateSubplot("rsi").addLine("Overbought", overBoughtThreshold) plt.getOrCreateSubplot("rsi").addLine("Oversold", overSoldThreshold) strat.run() print "Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05) if plot: plt.plot(None,None,"output.png") if __name__ == "__main__": main(True)
結果は以下の通り。
シャープレシオは-0.68です。残念。
でも、これは実装に問題があるような気がする。移動平均と株価がクロスするような場所で使ってはいけない戦略なのに単純に平均線の上か下しか見ていないから。
案の定クロス付近で財産を失う。
StockChartsは様々な戦略を紹介している。RSI2はこの中の戦略の一つ。
StockCharts.com - Articles
Trading Strategies and Models
http://stockcharts.com/school/doku.php?id=chart_school:trading_strategies
0 件のコメント:
コメントを投稿