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 件のコメント:
コメントを投稿