AIとファイナンス

AIとファイナンスの架け橋、それがこのブログの目指すところです。兼業投資家向けに、Pythonを駆使して株やFXの分析を「自分で」行えるようになるための情報を提供します。ニューラルネットワークを活用した市場予測から、実証済みの金融理論まで、全てのコードを公開し、誰もが活用できるように!是非色々なコードで遊んでみてください!

【FX】Backtraderを使いこなそう!勝率・取引回数・リスクリワード比の表示方法【テクニカル分析】

以前の記事(【FX】Backtraderで自分の戦略をバックテストしよう!【テクニカル分析】 - AIとファイナンス)でBackdraderの基本的な使い方をマスターしました。前回はバックテスト時の最終的なポートフォリオ残高を表示するだけでしたが、それだけでは本当の分析は出来ないですよね!実際には取引回数や勝率など知りたい情報がたくさんあるはずです。今回は上の二つに加えてリスクリワード比の三つをBacktraderでアウトプットするコードを書いていきます。

TradeAnalyzerの設定

TradeAnalyzerは、バックテスト中に発生した取引に関する詳細な統計情報を提供します。これには、取引の総数、勝ち取引と負け取引の数、勝率、平均利益取引、平均損失取引、最大の利益と最大の損失などが含まれます。全て戦略のパフォーマンス評価に役立つ指標ですよね!以下にコードを書いていきます。

ちなみにTradeAnalyzerに入ってない指標を分析結果として出したいときは’trades’(分析結果の辞書)の中から欲しい情報を抜いて自分で計算をする形になります。

リスクリワード比の計算方法

リスクリワード比は、トレーディング戦略のリスク対報酬の効率性を評価するための指標です。ここでの計算方法は、勝ち取引の平均利益と負け取引の平均損失を比較しています。

# TradeAnalyzerをCerebroに追加

cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")

# 戦略の実行と結果の取得
results = cerebro.run()
first_strategy = results[0]

# 取引統計の取得
trades = first_strategy.analyzers.ta.get_analysis()

# 取引回数
total_trades = trades.total.closed
print(f"Total Trades: {total_trades}")

# 勝率
if total_trades > 0:
    win_rate = trades.won.total / total_trades * 100
else:
    win_rate = 0
print(f"Win Rate: {win_rate:.2f}%")

# リスクリワード比
if trades.lost.total > 0:
    risk_reward_ratio = (trades.won.pnl.total / trades.won.total) / (trades.lost.pnl.total / trades.lost.total)
else:
    risk_reward_ratio = 0
print(f"Risk-Reward Ratio: {risk_reward_ratio:.2f}")

結果

さて、アップル株をSMAのゴールデンクロスで買ってデッドクロスで売る作戦は、この一年の中だと残念ながら勝率5割、リスクリワード比は0.22でした。リスクリワード比と勝率はトレードオフの関係にあり、1を下回ったからと言って悪い作戦とは限りませんが、長期的にプラスにするためには勝率を高くする必要が出てきてしまいます。

以下にデータのダウンロードも含めて今回のコードを全て載せましたので皆様もご自身の環境で好きな銘柄で是非試してください。おすすめはダウンロードや細かい設定不要のGoogle Colabです。

またその前にこちらのクリックをぜひお願いします!

!pip install backtrader
 
import backtrader as bt
import datetime
import yfinance as yf
class MovingAverageCrossStrategy(bt.Strategy):
    params = (
        ('short_window', 10),
        ('long_window', 30),
    )

    def __init__(self):
        self.sma_short = bt.indicators.SimpleMovingAverage(
            self.data.close, period=self.params.short_window, plotname='SMA Short')
        self.sma_long = bt.indicators.SimpleMovingAverage(
            self.data.close, period=self.params.long_window, plotname='SMA Long')

        # 最長の移動平均に合わせてminperiodを設定
        self.sma_long.plotinfo.plotlinelabels = True
        self.sma_short.plotinfo.plotlinelabels = True
        self.buysig = bt.indicators.CrossOver(self.sma_short, self.sma_long)

    def next(self):
        if self.sma_short[0] > self.sma_long[0] and self.sma_short[-1] <= self.sma_long[-1]:
            self.buy()
        # デッドクロス
        elif self.sma_short[0] < self.sma_long[0] and self.sma_short[-1] >= self.sma_long[-1]:
            self.sell()
 
# バックテストする銘柄と期間、足の種類をダウンロード
tickers = ["AAPL"]
df = yf.download(tickers, period="1y")
data = bt.feeds.PandasData(dataname=df)
 
# バックテスト環境の作成
cerebro = bt.Cerebro()

# 戦略の追加
cerebro.addstrategy(MovingAverageCrossStrategy)

# データフィードの追加
cerebro.adddata(data)

# 初期投資金額の設定
cerebro.broker.setcash(100000.0)

# コミッションの設定
cerebro.broker.setcommission(commission=0.001)

# バックテストの実行
cerebro.run()

# 最終的なポートフォリオの価値を出力
print(f'Final Portfolio Value: {cerebro.broker.getvalue()}')
# TradeAnalyzerをCerebroに追加
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")

# 戦略の実行と結果の取得
results = cerebro.run()
first_strategy = results[0]

# 取引統計の取得
trades = first_strategy.analyzers.ta.get_analysis()

# 取引回数
total_trades = trades.total.closed
print(f"Total Trades: {total_trades}")

# 勝率
if total_trades > 0:
    win_rate = trades.won.total / total_trades * 100
else:
    win_rate = 0
print(f"Win Rate: {win_rate:.2f}%")

# リスクリワード比
if trades.lost.total > 0:
    risk_reward_ratio = (trades.won.pnl.total / trades.won.total) / (trades.lost.pnl.total / trades.lost.total)
else:
    risk_reward_ratio = 0
print(f"Risk-Reward Ratio: {risk_reward_ratio:.2f}")