BTCFXの破産確率とドローダウンの発生率を口座リスク別にpythonで計算しよう!

さて、前回の3記事で「破産確率の公式」については理解できたと思います!長かったので読むのが大変だったと思います。お疲れ様でした。

破産確率の公式を理解するにはどうしても数学が必要です。ここを面倒だからと飛ばそうとすると、つい何を計算しているのかわからないまま「破産確率は1%を超えてはいけない!」などの数値目標だけを鵜呑みにしがちになります。

そのため少し難しい内容でしたが、敢えて本編で丁寧に解説させていただきました。

1.高校数学で正しいFXの破産確率を理解しよう(1)
2.高校数学で正しいFXの破産確率を理解しよう(2)
3.高校数学で正しいFXの破産確率を理解しよう(3)

今回の記事では、いよいよ自作BOTの破産確率(ドローダウン発生率)を計算し、それを口座リスク別に集計して「実用的な破産確率表」を作成する方法を紹介します!

1.実用的な破産確率表の作り方

すでに説明したように、破産確率を計算するためには以下の情報が必要です。

1)損益レシオ
2)勝率
3)口座のリスク率
4)初期資金
5)撤退ライン(破産ライン)

破産確率表というと、一般的には、損益レシオと勝率で表にすることが多いです。しかしこれらの数字は、売買ロジックの検証の時点ですでに決定されています。

勝率や損益レシオの数値は、トレーダーの意思で自由に調整できる数字ではないので、表にしても具体的な意思決定にはあまり役に立ちません。「期待値は高ければ高いほどいい」という当たり前の事実を確認するだけで終わってしまいます。

売買ルールを決める ⇒ 資金管理方法を決める

△ 破産確率は後者の意思決定に関する問題

本来、期待値が0円を超えていれば、破産確率は単に資金管理上の問題にすぎないことを思い出してください。期待値がプラスの場合、ロット数を十分に下げれば破産することは絶対にありません。

そのため、ここでは「すでに損益レシオと勝率がわかっているBOT」を運用する際に「口座のリスク率を決定する」ための判断材料として、破産確率表を使うことを想定します。

具体的には、縦(行)に口座のリスク率(X%)、横(列)にドローダウン率(Y%)をとり、特定のドローダウンが生じる確率(=破産確率)を示した表を作ります。

2.損益レシオを計算するコード

損益レシオを計算するコードだけ、まだ過去記事では作ったことがなかったので、一応、作り方を紹介しておきます。やり方は、pandasの記事で紹介しています。

▽ 損益レシオの計算コード

# バックテストの集計用の関数
def backtest(flag):
	print("バックテストの結果")
	print("-----------------------------------")
	print("平均利益率         :  {}%".format(round(records[records.Profit>0].Rate.mean(),2)))
	print("平均損失率         :  {}%".format(round(records[records.Profit<0].Rate.mean(),2)))
	print("損益レシオ         :  {}".format(round( records[records.Profit>0].Rate.mean()/abs(records[records.Profit<0].Rate.mean()) ,2)))

試しに、前回の章で作ったドンチャン・チャネルブレイクアウトBOTの平均利益率と損益レシオを確認しておきましょう。

・1時間足を使用(2017/8~2018/5)
・上値ブレイクアウト判定期間 30期間
・下値ブレイクアウト判定期間 30期間
・平均ボラティリティ計算期間 30期間
・ブレイクアウトの判定基準(高値/安値)
・損切りレンジ 2ATR

-----------------------------------
総合の成績
-----------------------------------
全トレード数       :  111回
勝率               :  38.7%
平均リターン       :  1.7%
平均利益率         :  9.39%
平均損失率         :  -3.16%
損益レシオ         :  2.97
平均保有期間       :  45.0足分
損切りの回数       :  54回

なお、この破産確率の計算の元となる「損益レシオ」の計算には、分割エントリー(増し玉)を使わないように注意してください。

ポジションの積み増しを有りでシミュレーションすると、勝率や平均利益率などが歪むため、正しい破産確率を計算できなくなります。詳しくは分割エントリーの記事を参考にしてください。

3.破産確率表を作るコード

破産確率表を作るコードは、前回の記事の「破産確率を計算するコード」を応用して作成します。まずは最初にコードを確認しておきましょう。


import numpy as np
import pandas as pd
from datetime import datetime


# 設定値
winning_percentage = 0.387     # 勝率
payoff_ratio = 2.97            # 損益レシオ
funds = 1000000                # 初期資金

drawdown_rate_list = np.arange(10,100,10) # ドローダウン率 10~90%の配列
risk_rate_list = np.arange(0.5,10,0.5)    # 口座のリスク率 0.5~9.5%の配列


# 特性方程式の関数
def equation(x):

	k = payoff_ratio
	p = winning_percentage
	return p * x**(k+1) + (1-p) - x


# 特定方程式の解を探す
def solve_equation():
	
	R = 0
	while equation(R) > 0:
		R += 1e-4
	if R>=1:
		print("期待値が0を下回っています")
		R=1
	print("特性方程式の解は{}です".format(R))
	return R


# 破産確率を計算する公式
def calculate_ruin_rate( R, risk_rate, drawdown_rate ):
	
	bankrupt_line = int(round(funds * (1 - drawdown_rate / 100)))
	risk_rate = risk_rate / 100
	print("破産ライン : {}円".format(bankrupt_line))
	unit = (np.log(funds) - np.log(bankrupt_line)) / abs(np.log( 1-risk_rate ))
	unit = int(np.floor(unit))
	return R ** unit


# メイン処理
result = [] 

for risk_rate in risk_rate_list:
	temp = []
	for drawdown_rate in drawdown_rate_list:
		print("口座のリスク率:{}%".format(risk_rate))
		print("ドローダウン率:{}%".format(drawdown_rate))
		R = solve_equation()
		ruin_rate = calculate_ruin_rate(R,risk_rate,drawdown_rate)
		ruin_rate = round(ruin_rate * 100,2)
		
		print("破産確率は{}%です".format( ruin_rate ))
		temp.append(ruin_rate)
		print("------------------------------------------")
	result.append(temp)

# pandasで表に集計する
df = pd.DataFrame(result)
df.index = [str(i)+"%" for i in risk_rate_list]
df.columns = [str(i)+"%" for i in drawdown_rate_list]
print(df)

# 最終結果をcsvファイルに出力
df.to_csv("RuinTable-{}.csv".format(datetime.now().strftime("%Y-%m-%d-%H-%M")) )

縦(行)に口座のリスク率を0.5%刻みで配列にし、横(列)にドローダウン率を10%刻みで配列にします。基本的な手順は、以前にバックテスト編で解説した「for文の総当たり探索の方法」と同じです。

・参考記事
for文での総当たりで最適なパラメーターを探索する方法

それでは実行結果を確認しておきましょう!

実行結果

以下のようなCSVファイルが出力されます。

検証結果

上記のチャネルブレイクアウトBOTの破産確率表(ドローダウンの発生確率表)は以下のようになりました。この表は左の「口座のリスク率」を取った場合に、右の「ドローダウン率」がおこる確率を示しています。

このBOTはそれなりにバックテスト上の成績がいいため、口座資金が0円になるという意味での「破産確率」はほとんどありません。

しかし例えば、このBOTを「口座のリスク5%」で運用した場合、13%の確率で30%以上のドローダウンに見舞われ、1.2%の確率で50%以上のドローダウンに見舞われることになります。それが許容できる確率であれば、5%での運用は十分に選択肢に入ります。

一方、50%のドローダウンがおこる確率(破産確率)を完全に0%におさえたいなら、口座のリスク率は2%で運用するのが適切ということになります。

確率の考え方の注意点

「5%以上の確率」は実現する可能性があると覚悟しておいた方がいいでしょう。絶対におこって欲しくない水準のドローダウン確率は、1~2%以下になるように、口座のリスク率を設定しましょう。

また上記の破産確率表は、あくまで過去のバックテスト上の「勝率」「損益レシオ」を将来にも再現できた場合の破産確率である点に注意してください。もし勝率や損益レシオが悪化すれば、この表よりも実際の破産確率は高くなります。

またここで使った勝率や損益レシオはあくまで「平均値」であることも忘れないでください。月単位などの局所的なドローダウン発生率にはもっとバラつきがあるため、余裕を持ってリスク率を決めてください。

途中時点での再計算

また「破産確率は資金量の関数である」ことを忘れないようにしましょう。資金の量が変われば破産確率は常に変動します。

例えば、口座リスク5%で運用した場合、上記の表では100万円の時点で資金が50万円にまで減る確率(50%のドローダウンがおこるリスク)は1.3%しかありません。しかし資金が70万円まで目減りした時点での「資金が50万円にまで減る確率」は13%と飛躍的に高くなります。

▽ 初期資金からのドローダウン確率を、資金70万円(-30%)の時点で再計算した場合

そのため、「初期資金を絶対に50%以下に減らしたくない」のであれば、資金が70万円まで減った時点で「口座のリスク率」を2.5%以下に再調整しなければなりません。

繰り返しますが、破産確率(ドローダウン確率)は資金量の関数です。そのため、常に破産確率を一定水準以下におさえるためには、資金が減るたびに破産確率を再計算して、それに合わせて口座のリスク率を引き下げる必要があります。

興味がある方は、現在の証拠金残高と許容できるドローダウン率から、注文前に自動的に「口座リスク率」を再計算して調整するようなBOTを作ってもいいでしょう。

練習問題

本文の途中に出てきた、「初期資金からのドローダウンが生じる確率を途中資金の時点で再計算した場合」の破産確率表のコードを作ってみましょう! 以下にそのまま正解例のコードを記載しておきます。


import numpy as np
import pandas as pd
from datetime import datetime


# 設定値
winning_percentage = 0.387     # 勝率
payoff_ratio = 2.97            # 損益レシオ
funds = 1000000                # 初期資金
funds2 = 700000                # 途中経過時点での資金

drawdown_rate_list = np.arange(10,100,10) # ドローダウン率 10~90%
risk_rate_list = np.arange(0.5,10,0.5)    # 口座のリスク率 0.5~9.5%


# 特性方程式の関数
def equation(x):

	k = payoff_ratio
	p = winning_percentage
	return p * x**(k+1) + (1-p) - x


# 特定方程式の解を探す
def solve_equation():
	
	R = 0
	while equation(R) > 0:
		R += 1e-4
	if R>=1:
		R=1
	return R


# 破産確率を計算する公式
def calculate_ruin_rate( R, risk_rate, bankrupt_line ):
	
	risk_rate = risk_rate / 100
	unit = (np.log(funds2) - np.log(bankrupt_line)) / abs(np.log( 1-risk_rate ))
	unit = int(np.floor(unit))
	return R ** unit


# メイン処理

result = []

bankrupt_line_list = []
for drawdown_rate in drawdown_rate_list:
	bankrupt_line_list.append(int(round(funds * (1 - drawdown_rate / 100))))

for risk_rate in risk_rate_list:
	temp = []
	for bankrupt_line in bankrupt_line_list:
		R = solve_equation()
		ruin_rate = calculate_ruin_rate(R,risk_rate,bankrupt_line)
		ruin_rate = round(ruin_rate * 100,2)
		if ruin_rate > 100:
			ruin_rate = 100.0
		temp.append(ruin_rate)
	result.append(temp)

df = pd.DataFrame(result)
df.index = [str(i)+"%" for i in risk_rate_list]
df.columns = [str(i)+"%" for i in drawdown_rate_list]
print("初期資金{}円からのドローダウン確率を、{}円の時点で再計算した表\n".format(funds,funds2))
print(df)

# 最終結果をcsvファイルに出力
df.to_csv("RuinTable-{}.csv".format(datetime.now().strftime("%Y-%m-%d-%H-%M")) )

FXトレードの破産確率を文系でもわかる高校数学で理解してみよう!(3)

前回の記事では、以下のような破産確率の公式を紹介しました。また実際にpythonを使ってこの方程式を解いて、破産確率を計算する方法を解説しました。

前回学習した破産確率の公式

・勝率をP、損益レシオをkとするとき、

$$\begin{array}{l}
Px^{k+1} +( 1-P) -x=0\ \ \ の方程式の解で\ 、\\
\ 0< x< 1\ の範囲の\ x\ を\ x=R\ とする。 \end{array}$$ $${\Large 破産確率\ =\ R^{\frac{資金額}{1回あたりの損失} \ }}$$

上記の方程式の解Rは、トレードの期待値が0円を上回るとき、必ず0<R<1の範囲に1つ存在し、かつ勝率や損益レシオが高ければ高いほど小さい数字になることも学習しました。詳しくは、前回の2記事を確認してください。

FXトレードの破産確率を高校数学で理解しよう!(1)
FXトレードの破産確率を高校数学で理解しよう!(2)

さて今回はこの公式を前提として、最終的に実践のトレードで使える破産確率の公式を作り、実際にpythonでBOTの破産確率を計算してみます!

1回の損失額が定まらない場合

前回の最後でも説明しましたが、上記の公式のままでは残念ながらまだ実践のトレードでは使えません。なぜなら、実践では1回のトレードの損失額を一定額に固定できないからです。

例えば、第7回の「資金管理編」では、毎回、口座残高のX%だけリスクを取り、そのリスクの範囲内でポジションサイズを計算する方法を紹介しました。この方法の場合、毎回の賭け金(トレードでリスクに晒す金額)は、そのときの口座残高に応じて毎回変動します。

「毎回1万円を賭ける」と決まっているゲームであれば、上記の公式をそのまま使うことができます。ですが、トレードのように毎回の損失額を固定できないゲームでは、上記の公式を使って破産確率を計算することはできません。

1.「資金量」の意味

では、もう少し踏み込んで考えてみましょう。前々回の記事で紹介した一番簡単な基本公式を思い出してください。以下のような公式でしたね。

基本の公式

・勝ったら1円の利益、負けたら1円の損失、というトレードで、勝率と資金量の2つの値から破産確率を計算する公式

$${\Large 破産確率\ =\ \left( \ \frac{負ける確率}{勝つ確率} \ \right)^{資金の量}}$$

ここでいう「資金量」とは何でしょうか?

「勝ったら1円貰える」「負けたら1円失う」という前提のゲームですから、資金量とは、言い換えれば「何回まで負けることができるか?」という最大負け回数に置き換えて考えることができます。必ずしも単位は円でなくてもいいのです。

この回数のことをトレードの世界では「ユニット数」と表現することがあります。要するに、資金量から考えて「何回トレードできるのか?」という回数がユニット数です。

$${\Large 破産確率\ =\ \left( \ \frac{負ける確率}{勝つ確率} \ \right)^{ユニット数}}$$

また前回の記事で解説しましたが、破産確率の公式はすべてこの基本公式から派生しています。損益レシオが異なる場合や、1回の損失額が大きい場合も、すべて「1円ゲームに換算して考える」と言ったのを思い出してください。

つまり最初の公式も全く同じように資金量のところを「ユニット数」に置き換えることができます。

2.トレードできる最大回数がわかる場合の公式

・勝率をP、損益レシオをkとし、
・資金からトレードできる最大回数を「ユニット数」とするとき、

$$\begin{array}{l}
Px^{k+1} +( 1-P) -x=0\ \ \ の方程式の解で\ 、\\
\ 0< x< 1\ の範囲の\ x\ を\ x=R\ とする。 \end{array}$$ $${\Large 破産確率\ =\ R^{ユニット数}}$$

例えば、初期資金が100万円で、「毎回のトレードでは1万円のリスクと取る」と決めて、そこから逆算して損切り幅やポジションサイズを設計している方であれば、ユニット数は100とすれば、上記の公式で破産確率を計算できることになります。

(例)BOTの成績と破産確率

・勝率 31.5%
・損益レシオ 2.99
・初期資金 100万円
・1回のトレードリスク 5万円
・ユニット数 20回

破産確率 = 3.76%

※ 計算方法は、前回の記事 を参照

要するに「資金からトレードできる最大回数」さえわかれば、そこから上記の公式で破産確率を計算できるのです。

3.口座の一定率のリスクを取る場合

ここで私たちが知りたい問題は、「毎回のトレードで口座の3%のリスクを取った場合の最大トレード回数(ユニット数)はいくつか?」という数学の問題だということに気付くことができました。

ではこのユニット数はいくつでしょうか?

鋭い方はすぐにわかるかもしれませんが、この問題は「いくらを撤退のラインとするか?」を決めないと決まりません。なぜなら「口座のX%のリスクでトレードする」というルールだけだと、口座資金がどれだけ減っても永久にトレードを続けることができるからです。

(例)口座の50%のリスクでトレード

100万円 ⇒ 50万円 ⇒ 25万円 ⇒ 12.5万円 ⇒ 6.25万円 ⇒ 3.125万円 ⇒ 1.5625万円 ⇒ 7812円 ⇒ 3906円・・・

そこで、まず先に「n円以下を破産とみなす」という実質的な撤退ラインを決めなければなりません。今回は以下のような例題を考えましょう。

例題

以下の場合のユニット数はいくつか?

1)初期資金100万円
2)資金10万円以下になったら撤退(破産とする)
3)口座の3%を賭けてトレードする

この問題は、実は対数(log)という考え方を使うと簡単に解くことができます。対数がわかる方は読み飛ばして構いませんが、対数を忘れている方もいるかもしれないので、対数について解説します。

4.対数(log)って何だっけ?

対数をズバリ一言で説明すると、「掛け算を足し算に変換するための数学ツール」です。

私と同じように高校数学が苦手だった方でも、FXを始めてから「対数チャート」というのを見たことがあると思います。例えば、以下はビットコイン現物価格の対数チャートです。

わかりやすい例なので、BTC現物価格の2013年~2018年3月の価格チャートと対数チャートを見てみましょう!

▽ 価格チャート

▽ 対数チャート

出典「CoinMarketCap

上記の2つのチャートは全く同じ期間のものですが、全く別物のように見えます。その理由は以下です。

BTC価格が10万円から20万円になるのと100万円から200万円になるのとでは、同じ2倍でも価格チャート上の目盛りは大きく異なります。前者は10万円しか上がっていない一方、後者は100万円上がっています。そのため、価格チャートでは直近に極端に大きな値動きがあったように見えてしまいます。

しかし対数チャートでは、「2倍は同じ2倍」として扱います。つまり10万円が20万円になった場合と、100万円が200万円になった場合とを、y軸上で同じ目盛り幅(間隔)で表示します。そのため、「何倍になったか?」という視点で長い期間のチャートを見るときには、対数チャートを見たほうがわかりやすい、と言われます。

ここまでが一般的な説明です。

1)数式で理解してみよう!

では、これを数学的に理解してみましょう!
上記の説明をそのまま数式にすると以下のようになります。

▽ 価格チャートの場合

$$\begin{array}{l}
値動きA\ =\ 20万円-10万円\ =\ 10万円\\
値動きB\ =\ 200万円-\ 100万円\ =\ 100万円\\
\\
値動きB\ >\ 値動きA
\end{array}$$

▽ 対数チャートの場合

$$\begin{array}{l}
対数価格の差A\ =\ log20万-log10万\ =\ log( \ 20万\ /\ 10万) \ =\ log2\\
対数価格の差B\ =\ log200万-\ log100万\ =\ log( \ 200万/100万) \ =\ log2\\
\\
対数価格の差B\ =\ 対数価格の差A
\end{array}$$

後者の場合は、どちらも対数差分が log2 になるのがわかります。ちなみに、このことは高校で勉強する対数の「基本公式」から導き出せます。詳しくは以下のリンクを参考にしてください。

▽ 対数の基本公式

$$\begin{array}{l}
log_{a} M\ +\ log_{a} N\ =\ log_{a} MN\\
log_{a} M\ -\ log_{a} N\ =\ log_{a}\frac{M}{N} \
\end{array}$$

参考:「対数の基本的な性質と証明

2)対数は掛け算を足し算に、割り算を引き算にする

上記の公式を見るとわかりますが、これは逆にいうと「対数を取れば掛け算を足し算に(割り算を引き算に)できる」ということだとわかります。例えば、「価格が2倍になった」という数式の対数を取ってみましょう。

$$\begin{array}{l}
100000\ \times \ 2\ =\ 200000\\
\\
両辺の対数を取ると\\
\\
log( 100000\ \times 2) \ =\ log200000\ \\
\\
左辺に公式を使うと\\
\\
log100000\ +\ log2\ =\ log200000=\ 12.2060726…
\end{array}$$

これが、「掛け算は対数を取ると足し算にできる」という意味です。なお、上記の式が本当にそうなるのか気になる方は、pythonで以下を実行してみてください。

▽ pythonで計算して確認してみよう!

import numpy as np

print(np.log(2) + np.log(100000))
print(np.log(2 * 100000))
print(np.log(200000))

3)口座の一定率をリスクに晒す場合のトレード回数

本題に戻りましょう!

この考え方を利用すると「1回のトレードで口座の3%を失う」という状態を引き算(または足し算)で表すことができます。
以下のような具合です。

$$\begin{array}{l}
口座残高\ =\ 100万\ \times \ 0.97\ \times \ 0.97\ \times \ 0.97\ \times \ 0.97\ …..\\
口座残高の対数\ =\ log100万\ +\ log0.97\ +\ log0.97\ +\ log0.97…..
\end{array}$$

これが成り立つということが、あまりピンと来ない方は、ぜひpythonでlog0.97を計算してみてください。log0.97 = -0.0304592…となり、マイナスの数字であることがわかります。

ということは、口座の残高の対数を log0.97 で割れば、定率3%で何回トレードできるか数えることができそうですね! 実際にやってみましょう!

定率の場合の公式

$${\large ユニット数U\ =\frac{log資金\ -\ log撤退ライン}{| log( 1-リスク率)| }}$$

$${\large 破産確率\ =\ R^{U}}$$

できました!
実際の数字を入れてみた方がイメージが湧きやすいので、本当にこれでユニット数が計算できるのかどうか、やってみましょう!

4)定率のユニット数を計算するコード


import numpy as np

funds = 1000000           # 初期資金
risk_rate = 0.1           # 1回のトレードで取るリスク率
bankrupt_line = 200000    # 撤退ライン(破産)

unit = (np.log(funds) - np.log(bankrupt_line)) / abs(np.log( 1-risk_rate ))
unit = int(np.floor(unit)) # 切り捨て

print("最大{}回までトレードできます".format(unit))


先ほども説明したように、口座の一定率のリスクを取る場合は撤退ラインを決めておかないと、永遠にトレードができてしまいます。必ず撤退ラインを入力するようにしてください。

では、試しに以下のようなテストしやすい例を考えてみましょう。

(テスト条件)

・初期資金 100万円
・撤退ライン 20万円
・口座のリスク 10%

100万円から始めて、毎回のトレードで口座の10%までリスクを取った場合です。これは実際に電卓で計算してみると以下のようになります。

100万円 ⇒ 90万円 ⇒ 81万円 ⇒ 72.9万円 ⇒ 65.6万円 ⇒ 59万円 ⇒ 53万円 ⇒ 47.8万円 ⇒ 43万円 ⇒ 38.7万 ⇒ 34.8万円 ⇒ 31.3万円 ⇒ 28.2万円 ⇒ 25.4万円 ⇒ 22.8万円 ⇒ 20.5万円 ⇒ 18.5万円

つまり撤退ラインに達する(破産する)までに最大15回トレードできることがわかります。ユニット数は15です。

では上記のコードを実行してみましょう。

ちゃんと最大トレード回数を計算できています。
これで「口座のX%のリスクを取ってトレードする場合」でもユニット数を計算して、破産確率を算出できるようになりました。

4.破産確率を計算するpythonコード

では、前回の記事で作成した「特性方程式を解いて破産確率を計算するpythonコード」に、今回のユニット数を計算する箇所を付け足しましょう!

これで破産確率の計算コードは完成です!


import numpy as np

# 設定値
winning_percentage = 0.375     # 勝率
payoff_ratio = 2.09            # 損益レシオ
funds = 1000000                # 初期資金
risk_rate = 0.05               # 1回のトレードで取るリスク率
bankrupt_line = 200000         # 撤退ライン(破産)


# 特性方程式の関数
def equation(x):

	k = payoff_ratio
	p = winning_percentage
	return p * x**(k+1) + (1-p) - x


# 特定方程式の解を探す
def solve_equation():
	
	R = 0
	while equation(R) > 0:
		R += 1e-4
	if R>=1:
		print("期待値が0を下回っています")
		R=1
	print("特性方程式の解は{}です".format(R))
	return R


# 破産確率を計算する公式
def calculate_ruin_rate( R ):
	
	unit = (np.log(funds) - np.log(bankrupt_line)) / abs(np.log( 1-risk_rate ))
	unit = int(np.floor(unit))
	return R ** unit


# メイン処理
R = solve_equation()
ruin_rate = calculate_ruin_rate(R)
print("破産確率は{}%です".format( round(ruin_rate * 100,2) ))


5.練習~破産確率からリスク率を考えよう

では試しに以下のような、チャネルブレイクアウトBOTを考えてみましょう。

BOTの成績と資金条件

・勝率 37.5%
・平均利益率 8.21%
・平均損失率 3.92%
・損益レシオ 2.09
・初期資金 100万円
・撤退ライン 20万円

一応、期待値はプラスなので運用すること自体は可能なBOTです。では1トレードで取る口座のリスクは何%で運用するのが適切でしょうか?

試しに口座のリスク率を1%から順番に計算してみると以下のようになります。

口座のリスク率 破産確率
1% 0.0%
2% 0.0%
3% 0.04%
4% 0.31%
5% 1.01%
6% 2.11%
7% 3.82%
8% 5.96%
9% 8.03%
10% 10.8%

 
上記のBOTはそれほど成績が優秀なわけではありませんが、それでも教科書通り、口座のリスクを1~3%の範囲におさえて運用していれば、破産リスクはほとんどないことがわかります。

逆に口座リスクが5%を超えたあたりから、急激に破産リスクが上がっています。実際に上記の破産確率の公式で、0.1%刻みで破産確率を計算した結果をプロットすると以下のようになりました。

以前にこちらの記事でも解説したように、口座の5%以上のリスクを取ると、うまくいけば高い運用パフォーマンスを手にすることができます。しかし逆に失敗したときの破産確率も、急速に「現実におこりうる数字」に近づくのがわかります。

どの程度までリスクを許容するかは、運用資金の大きさにもよりますが、教科書的には1~2%未満におさえるのが良いとされています。

6.許容ドローダウンから考える

「破産確率」という名前こそ付いていますが、実際には上記の計算式は「許容ドローダウン」を考えるのに活用した方が実用的です。

例えば、さきほどは撤退ライン(破産ライン)を20万円としましたが、数百万円以上の資金を運用している人からすると、実際には50%すら失いたくない人が大半でしょう。つまり撤退ライン(破産ライン)を50万円で計算する必要がありますが、この場合の計算結果はもっとシビアになります。

許容ドローダウンが50%の場合

・勝率 37.5%
・平均利益率 8.21%
・平均損失率 3.92%
・損益レシオ 2.09
・初期資金 100万円
・破産ライン 50万円

口座のリスク率 破産確率
1% 0.0%
2% 0.64%
3% 3.82%
4% 9.31%
5% 14.53%
6% 19.55%
7% 26.3%
8% 30.51%
9% 35.39%
10% 41.05%

この成績のBOTで1回のトレードで口座の5%のリスクを取った場合、約1/10の確率で50%のドローダウンに見舞われることになります。口座の10%のリスクを取ると、なんと40%の確率で半分の資金を失うことになるのです。これを許容できる人は少ないでしょう。

一方、こちらの場合でも口座リスク2%までであれば、50%のドローダウンがおこる確率はほとんど無いことがわかります。多くのトレードの教科書で「2%ルール」が推奨されるのは、この辺りの特徴にも理由があるのかもしれません。

なお、ここまでの数式を追っていただいた方ならわかると思いますが、上記の破産確率の公式は、初期資金200万円、撤退ライン100万円で試しても、初期資金2000万円、撤退ライン1000万円で試しても全く同じです。要するに、ドローダウン率50%の確率表です。

次回

次回は、前章までで作成した「すでに損益レシオと勝率がわかっているBOT」について、許容ドローダウン率と口座のリスク率をそれぞれ縦軸と横軸に取った破産確率表をCSVで出力する方法を紹介して、最後の記事とする予定です。個人的にはそれが最も実用的な破産確率表の使い方ではないかと思います。

FXトレードの破産確率を文系でもわかる高校数学で理解してみよう!(2)

前回の記事の続きです。

今回はより実践的なFXトレードでの破産確率の公式を紹介し、さらにpythonを使って実際に破産確率を計算します。 なお今回の内容は、前回の「基本公式」が前提となっているため、なぜ以下の式が導き出せるのかわからない方は、先に前回の記事を読むことを推奨します。

基本の公式

・勝ったら1円の利益、負けたら1円の損失、というトレードで、勝率と資金量の2つの値から破産確率を計算する公式

$${\Large 破産確率\ =\ \left( \ \frac{負ける確率}{勝つ確率} \ \right)^{資金の量}}$$

 
前回の記事:
FXの破産確率を高校数学で理解しよう!(1)

では始めましょう!

1回の賭け金を増やした場合の公式

前回の記事では、「勝ったら1円の利益」「負けたら1円の損失」というトレードを無限に繰り返した場合に、勝率(P)と資金(N)がどのように破産確率に影響を与えるか、を確認しました。

しかし実際のトレードでは、当然、賭け金は1円ではありません。そこで、まずは以下のような条件での破産確率の公式を考えてみましょう。

前提条件

1)勝ったら1000円の利益、負けたら1000円の損失というトレード
2)市場の資金は無限と仮定する
3)勝率は50%を超えていると仮定する

実はこの場合の破産確率の公式は「めちゃめちゃ簡単」です。
以下のように変形するだけでいいのです。

$${\Large 破産確率\ =\ \left(\frac{負ける確率}{勝つ確率} \ \right)^{\frac{資金の額\ }{1000円\ }}}$$

要するに、右上の指数の「資金量」を「1トレードあたりの損失額」で割ればOKです。なぜそうなるかは後述します。

公式からわかること

上記の公式から、同じ勝率でも1トレードあたりの損失額(=賭け金)が大きければ大きいほど、破産確率は大きくなることがわかります。

勝率が50%を超えるという前提条件があるため、()の中身は必ず1未満の数字になります。そのため、右上の指数は大きければ大きいほど、破産確率は小さくなります。例えば、資金量が多ければ多いほど、同じ勝率でも破産確率は低くなります。

逆に右上の指数が小さくなると、破産確率は大きくなってしまいます。そのため、1回のトレードの賭け金の額を増やすと、破産確率は大きくなります。

賭け金の定義

ちなみにトレードにおける「賭け金」の定義をここで整理しておいてください。賭け金はエントリー価格やサイズのことではありません。最終的に1回のトレードで失う証拠金(例えば、損切り幅)のことです。「ポジションを持つために投入した金額」ではないので注意してください。

上記の式になる理由

初期資金10万円で「勝ったら1000円の利益」「負けたら1000円の損失」のトレードをすることは、初期資金100円で「勝ったら1円の利益」「負けたら1円の損失」のトレードの破産確率を計算するのと全く同じです。

つまり賭け金の額が大きい場合は、その分だけ口座資金を小さくして考えれば、前回に学習したのと同じ「勝ったら+1円」「負けたら-1円」のゲームに変換することができます。この考え方は、これから先の破産確率の公式でも全て同じです。

どんな条件でも、基本的には「資金額」の方をうまく調整して、すべて「1円ゲーム」に換算して考えます。例えば、以下のような条件を考えてみてください。

・初期資金100万円
・1回のトレードでの損失 1万円
・破産ラインを0円ではなく20万円と定義する

この場合は、以下のような式を計算します。

$${\Large 破産確率\ =\ \left(\frac{負ける確率}{勝つ確率} \ \right)^{\frac{資金額\ -\ 撤退ライン\ }{1回あたりの損失\ }}}$$

つまり以下です。

$${\Large 破産確率\ =\ \left(\frac{負ける確率}{勝つ確率} \ \right)^{\frac{100万円\ -\ 20万円\ }{1万円\ }}}$$

要するに、破産のラインを20万円と考えたい(資金が20万円に減る前には撤退したい)という場合は、最初の初期資金を 100万円 – 20万円 = 80万円 で考えればいいだけです。

2.利益と損失の割合が違う場合の公式

もちろん実際のトレードでは、1回の利益と損失の額は同じではありません。そこで、以下のような利益と損失の割合が異なる場合を考えてみましょう。

1)平均利益2万円 / 平均損失1万円
2)平均利益率 3.8% / 平均損失率 1.9%

これはどちらの数字を使っても構いません。さきほども説明したように、どちらにしても「1円ゲーム」に換算して考えるので同じです。つまり、以下のような条件で破産確率を考えます。

1)前提条件

1)損益レシオK = 平均利益 ÷ 平均損失
2)勝ったら K円の利益、負けたら1円の損失というトレード
3)市場の資金は無限と仮定する
4)期待値が0円を超えている

最初の2つのどちらを使っても、損益レシオKは同じになります。
なので、どちらを使っても構いません。

2)「平均利益」と「損益レシオ」に注意

ここでの平均利益を平均リターンと混同しないよう注意してください。一般的にいう平均リターン(期待値)は、すべての平均利益と平均損失を通算した平均値です。一方、ここでいう「平均利益」は、純粋に利益が出た場合のみの平均値です。

また損益レシオとプロフィットファクター(PF)を混同しないでください。PFは「総利益 ÷ 総損失」ですが、この数字にはすでに勝率が含まれています。損益レシオは、勝率とは関係のない数字です。

3)具体的な公式

「1円ゲームに換算するのは同じ」といいましたが、公式はかなり違った姿になります。結論からいうと、この場合の公式は以下になります。

・勝率 P
・損益レシオ k のとき

 
$$\begin{array}{l}
Px^{k+1} +( 1-P) -x=0\ \ \ を満たすような\\
\ 0< x< 1\ の範囲の\ x\ を\ x=R\ とすると \end{array}$$ $${\Large 破産確率\ =\ R^{\frac{資金額}{1回あたりの損失} \ }}$$  

この記事から読み始めてくださった方は、「いきなり難しそうな方程式が….」と思ったかもしれませんね(笑)

しかし前回の記事を読んでくださった方であれば、何となく見覚えがあるのではないかと思います。この式は、実は前回の記事で出てきた「特性方程式」と(k+1)の部分以外は全く同じです。

注意

なお、上記の公式の「1回あたりの損失額」は、実際のトレードではなかなか定義できません。具体的な損失額はそのときのBTC価格やロット数によって変動するからです。ですが、ここは後ほど説明するので今は気にしないでください。

4)上記の式になる理由

では本当に上記のような公式になるのか確認していきましょう。なお、途中までは前回の記事と全く同じ流れなので、重複する箇所は説明を端折ります。わからない方は、前回の記事を読んでください。

まず、ある資金額n円で破産する確率をQ(n)とします。そして現在の資金額を100円とします。このとき、現在の破産確率 Q(100)は以下のような確率の合計で表すことができます。

1)資金100円で将来的に破産する確率 Q(100)
2)次に勝って資金がn+k円 になり、将来的に破産する確率 P × Q(n+k)
3)次に負けて資金がn-1円 になり、将来的に破産する確率 (1-P) × Q(n-1)

$${\small Q( 100) \ =\ P\times Q( 100-k) \ +\ ( 1-P) \times Q( 100-1) \ }$$

これを前回と同様に一般化して漸化式にします。

(漸化式)
$${\small Q( n) \ =\ P\cdotp Q( n+k) \ +\ ( 1-P) \cdotp Q( n-1) \ }$$

さらに特性方程式を作ります。

(特性方程式)
$${\small \begin{array}{l}
x\ =\ Px^{k+1} +( 1-P)\\
\\
より、Px^{k+1} +( 1-P) -x\ =0\
\end{array}}$$

前回はこの方程式を解くと、たまたま綺麗に解が X=1,(1-P)/P になりました。だから (勝つ確率 ÷ 負ける確率)をベースにした公式になったわけですね。

・前回は特性方程式の解が P(1-P) だったので
$${\large 破産確率\ =\ \left(\frac{1-P}{P}\right)^{資金量\ }}$$

なぜ特性方程式の解からこの式が導き出せるのかは(しつこいですが)前回の記事で長々と説明しているので、そちらを参考にしてください><

全く同じ理由で、この方程式を解いてその解をRとしたときも、「Rの資金乗」が、そのまま破産確率になります。

・上記の特性方程式の解がRのとき、

$${\Large 破産確率\ =\ R^{資金量\ }}$$

4)この方程式の解き方

ただし前回の式は、x の2次方程式だったので、解は2つしかありませんでした。今回はk+1次の方程式なので解は2つとは限りません。そこで、以下のような2つの前提条件を思い出してください。

1)破産確率は、確率の関数である
2)「期待値は0を超えている」という前提がある

Q(n)は、破産する確率を計算する関数です。

確率は0~1までの範囲に必ず収まらなければなりません。そのため、Rは必ず 0≦R≦1の範囲でなければなりません。Rがマイナスの値や1を超える値を取ると、上記の公式では確率が0%を下回ったり、100%を超えてしまうからです。

また「期待値が0を超えている」という条件を満たす場合、解のRは必ず0~1の範囲に1つ存在します。これは色々説明するよりも、実際に上記の方程式をpythonで描画してみた方がイメージが湧きやすいでしょう。

このブログはpythonの実践ブログなので、実際に上記の方程式をpythonで解いてみましょう!

3.Pythonコードで方程式を解こう!

今回は以下のようなBOTの破産確率を考えます。
「1回あたりの損失額」以外は、すべて実際のドンチャン・チャネルブレイクアウトBOTの成績をそのまま使います。

成績

・勝率 41.5%
・平均利益率 8.52%
・平均損失率 2.85%
・損益レシオ 2.99

仮定条件

・初期資金 100万円
・1回の負けトレードの損失額1万円

まずは先ほどの漸化式から導いた特性方程式をpythonで関数にしてみましょう。


#---設定値---

winning_percentage = 0.415
payoff_ratio = 2.99

# 特定方程式の関数
def equation(x):

	p = winning_percentage
	k = payoff_ratio
	return p * x**(k+1) + (1-p) - x

これは先ほどの特性方程式の左辺をそのまま書いただけです。この関数に適当なxの値を渡せば、以下の式の計算結果を返します。

$$Px^{k+1} +( 1-P) -x$$

特性方程式を解くためには、この関数から「0」が返ってくるような0≦x≦1の範囲内のxを探し出せばいいわけです。しかしその前に、本当に0~1の間に解が1つだけ存在するのか、この関数をプロットして確認してみましょう。

2)グラフで描画する

pythonでは、matplotlibというライブラリを使って関数を描画することができます。以下のようなコードを書いて、上記の特性方程式の関数を描画してみましょう。


import matplotlib.pyplot as plt
import numpy as np

# 設定値
winning_percentage = 0.415
payoff_ratio = 2.99


# 特性方程式の関数
def equation(x):
	k = payoff_ratio
	p = winning_percentage
	return p * x**(k+1) + (1-p) - x

# グラフで描画する
x = np.linspace(0, 1.2, 100) 
plt.plot( x,equation(x) )
plt.axhline( y=0,linestyle="dashed" )
plt.axvline( x=1,linestyle="dashed" )
plt.show()


上記のコードでやっていることは、以下です。

1)np.linespace()で、0~1.2の範囲で等間隔な100個の数字を作る
2)それをxとして片っ端から特性方程式の関数に与える
3)返ってきた値をyとして、plt.plot(x,y)をグラフに描画する

つまり0~1.2の範囲の100コの数字をxとし、それに対応する100コの計算結果をyとし、xとyを描画したらグラフの形状がわかるわけです。さらに見やすいように、axvhline()でy=1の水平線、axvline()でx=1の垂直線をセットで描画しています。

では、実行してみましょう!

実行結果

勝率41.5%、損益レシオ2.99 の場合の特性方程式は、上記のような形状になることがわかりました。

この方程式を解くということは、y=0と交わるxを探すということです。ちゃんと0≦x≦1の範囲に、X=1と0<R<1を満たす2つの解が存在していることがわかります。

期待値が0円を下回る場合

では、次に期待値が0円を下回る場合を考えてみましょう。
ちなみに期待値が0を下回るかどうかは、以下のような式を満たすかどうかで確認できます。

 
$${\large \frac{平均損失率}{平均利益率\ +\ 平均損失率} \ > \ 勝率}$$

 

これは以下の期待値の計算式を展開すればわかります。気になる方は自身で確認してみてください。

$${\small 1\times 平均利益率\times P\ -\ 1\times 平均損失率\times ( 1-P) < 0}$$

では、以下のような期待値が0を下回るケースを考えてみましょう。

・勝率 31.0%
・平均利益率 8.52%
・平均損失率 3.85%
・損益レシオ 2.21

このケースは、計算してみるとわかりますが、ぎりぎり期待値が0を下回ります。これで特性方程式の関数のグラフの形状を確認してみましょう。

解Rがかなり1に接近して0<R<1の範囲におさまるか怪しくなってきました。実際にこの方程式を解いてみると、解Rは、R=1.0044999 となり、1以下におさまっていません(解き方は後述します)。

では、もっと成績を悪化させてみるとどうでしょうか?

・勝率 28.7%
・平均利益率 8.52%
・平均損失率 4.86%
・損益レシオ 1.75

これは明らかに期待値がマイナスですが、グラフを確認してみましょう。

このように解Rは1とは反対側にいってしまい、0<R<1を満たす解Rは存在しないことがわかります。ちなみにこのときの解R=1.2851999です。これで、さきほどの確率の公式に「期待値が0を上回るとき」という条件が付いている理由が理解できたと思います。

特定方程式の意味

これで特性方程式の解が何を意味する数字なのか、少しイメージできたのではないでしょうか?

要するに特定方程式の解Rは、損益レシオと勝率という2つの成績指標を加味して0~1の範囲の数値に換算したものなのです(小さければ小さいほど良い数値で、1を超えると期待値が0円を下回ります)。そこに資金量を乗じることで破産確率が計算できます。

3)方程式を解く

では次に実際に、この特性方程式を解いて破産確率を計算してみましょう!
さきほどのコードに2つほど関数を付け加えます。


import matplotlib.pyplot as plt
import numpy as np

# 設定値
winning_percentage = 0.415
payoff_ratio = 2.99
loss_per_trade = 10000 # トレード1回の損失(仮定)
funds = 1000000


# 特性方程式の関数
def equation(x):

	k = payoff_ratio
	p = winning_percentage
	return p * x**(k+1) + (1-p) - x


# 特定方程式の解を探す
def solve_equation():
	
	R = 0
	while equation(R) > 0:
		R += 1e-4
	if R>=1:
		print("期待値が0を下回っています")
		R=1
	print("特性方程式の解は{}です".format(R))
	return R


# 破産確率を計算する公式
def calculate_ruin_rate( R ):
	
	e = funds / loss_per_trade
	return R ** e

pythonのようなプログラムが方程式を解く場合、人間のように因数分解や微分をしてスマートに解くよりも、ゴリゴリと片っ端から数字を代入しまくって近い数字を探すほうが得意です。

特に今回のように、解が0<R<1の範囲とわかっているような場合は尚更です。そのため上記のプログラムでは、0から順番に0.0001単位で数字を代入しまくって、最もy=0に近い数を返すようにしています。

このときのxは、ピッタリ厳密なy=0ではありませんが、どのみち、実際にトレードで何らかの指標として使う際には四捨五入しますので、近似値で問題ありません。無理数(ルートなど)で答えを返されても使えないからです。

▽ 解を探す箇所

R = 0
while equation(R) > 0:
	R += 1e-4   #「1e-4」は「0.0001」と同じ意味

さきほどの説明の通り、0≦x≦1 の範囲に必ず解は存在することがわかっています。そのため、0からスタートして +0.0001 ずつ加算していき、計算結(y)が0を下回った時点でループを止めます。

もし期待値が0を下回っている場合は、解Rに辿り着くよりも前に x=1 にぶつかります。そのときは「期待値が0以下です」と表示して、R=1 を返します。

※ R=1 のときの破産確率は必ず100%です。1は何乗してもずっと1だからです。

実行結果

では以下のようなメイン処理を書いて実行してみましょう!
今度は確認のために、解Rもグラフ上にプロットしてみます。


# メイン処理
R = solve_equation()
ruin_rate = calculate_ruin_rate(R)
print("破産確率は{}%です".format( round(ruin_rate * 100,2) ))

最初の勝率・損益レシオの条件では以下のような結果になりました。

破産確率は0%です。

念のため、以下のようなコードを追記して解Rが正しいかどうかグラフにプロットしてみましょう。


# グラフを描画
x = np.linspace(0, 1.2, 100)
plt.plot( x,equation(x) )
plt.axhline( y=0,linestyle="dashed" )
plt.axvline( x=1,linestyle="dashed" )
plt.axvline( R, color="gray" )
plt.show()

以下のグレーの線が、x=Rの位置を垂直線でプロットしたものです。ちゃんと正しい箇所を求めることができています。

資金の条件を変えてみた場合

ではBOTの成績は同じまま、初期資金を10万円に変えてテストしてみましょう。

成績

・勝率 41.5%
・平均利益率 8.52%
・平均損失率 2.85%
・損益レシオ 2.99

仮定条件

・初期資金 10万円
・1回の負けトレードの損失額1万円

この場合の破産確率は以下のようになります。

特性方程式の解Rは変わっていませんが、破産確率は 1.77%に上昇しています。

同じように1回の負けトレードの損失額(=1回の賭け金)を上げた場合も、破産確率は上昇します。全く同じ損益レシオや勝率のBOTを使っても、初期資金や毎回のトレードで取るリスク額によって、破産確率が変動することがわかります。

これが前回の記事で、「損益レシオと勝率だけのバルサラ破産確率表を使ってもあまり意味がない」と説明した理由です。

次回

さて、今回はより実践的なトレードで「平均利益と平均損失の割合が異なる場合」の破産確率の計算方法を解説しました!

しかし残念ながら、あと1つだけどうしても簡単に設定できない数値があります。それが「1回の負けトレードの損失額」(=賭け金)です。

1)1回の損失額の定義

トレードにおける賭け金とは、この記事の定義でも確認したように1回のトレードで実際に損する金額のことです。しかし実践のトレードでは、この「1回のトレードの損失額」は一定額に固定することができません。

例えば、第7回の「資金管理編」では、毎回、口座残高のX%だけリスクを取り、そのリスクの範囲内でポジションサイズを計算する方法を紹介しました。この方法の場合、毎回の賭け金(トレードでリスクに晒す金額)は、そのときの口座残高に応じて毎回変動します。

「毎回1万円を賭ける」と決まっているゲームであれば、上記の公式をそのまま使うことができます。ですが、トレードのように毎回の損失額を固定できないゲームでは、上記の公式を使って破産確率を計算することはできません。

2)対数(log)に変換する

最後の検証で確認したように、上記の公式の「1回のトレードの損失額」は、それ自体が破産確率に影響します。そのため、平均損失率(%)などの割合ではなく、何らかの具体的な金額(絶対値)を使わなければなりません。

しかしこれを割合で置き換える方法が1つあります。それが、初期資金や損失額などのお金の単位を「円」ではなく「log(対数)」に変換する方法です。この方法を使えば、「毎回のトレードで口座の一定率(3%等)のリスクを取った場合」などの破産確率をシミュレーションできるようになります。

次回の記事は、高校数学のlogを忘れた方でもわかるように、これについて詳しく解説します。

次回:
FXトレードの破産確率を高校数学で理解しよう(3)

FXトレードの破産確率を文系でもわかる高校数学で理解してみよう!

はじめにお断りしておくと、私自身が私大文系の出身で数学はもともと苦手です。

社会人になってから興味をもって少しだけ勉強するようになりましたが、それでも高校数学の範囲も復習しないと自信がありません。この記事は、同じレベルの方でも何となく破産確率を理解できることを目指します。

バルサラの破産確率表

よく「FX 破産確率」などで検索すると、バルサラ破産確率表なるものがズラっと出てきます。列に「損益レシオ」、行に「勝率」が記載された表で、見たことがある方もいるかもしれません。

▽ Google検索の「バルサラ破産確率表」

検索結果のリンク

しかしその多くは前提条件や計算根拠が不明なまま転載されている表で、あまり役に立ちません。破産確率は「資金の量」によって決まる関数なので、資金の量を聞かれてないのに破産確率だけわかる、ということは基本的にありえません。

おそらく出回っているバルサラ破産確率表は、「口座のn%を毎回トレードで賭ける」「口座がk%まで減ったら破産とみなす」という前提条件があるはずで、それこそが知りたい数字なのですが、そこまで記載されていることも少ないです。

前提

私は以下のページを参考にさせて貰い、熟読してやっと破産確率の正しい計算方法を何となく理解することができました。数学が得意な方は、おそらく直接以下のページを読んだ方が理解が早いと思います。

破産確率について

「チンプンカンプンだ….」という方は、私と同じなので安心してください。私もわざわざ「漸化式って何….?」「等比数列の和の公式って何だっけ?」というレベルから復習してやっとわかりました(笑)

この記事では、最低限、高校数学Bの確率と数列(等比数列の公式など)が登場します。ただそれがわからない方でも、破産確率の式が何を意味しているのか、何となくわかるように説明したいと思います。

勝率についての公式

まず最初にもっとも簡単な公式から確認していきましょう。
以下の前提条件を満たすとき、この公式が成り立ちます。

前提条件

1)勝ったら1円の利益、負けたら1円の損失というトレード
2)市場の資金は無限と仮定する
3)勝率は50%を超えていると仮定する

公式

$${\Large 破産確率\ =\ \left( \ \frac{負ける確率}{勝つ確率} \ \right)^{資金の量}}$$

 

この条件では、勝率が50%以下のときに期待値が0円を下回ります。そのため、半永久的にトレードを繰り返すといつか必ず破産します。この「期待値が0円を下回る場合、ずっとトレードを繰り返すといつか必ず破産する」という考え方は、今後も使うので覚えておいてください。

この公式からわかること

この時点でわかることは、「言われなくても知ってるよ!」という当たり前のことばかりですが、一応、数式で確認しておきましょう。

勝率が50%を超えるという前提ですから、()の中の数字は必ず1未満になります。そして勝率が大きければ大きいほど、中身は小さな数字になります。つまり勝率が高いほど、破産確率は小さくなります。

また「勝つと1円儲かる」「負けると1円損する」というのが前提ルールですから、資金が多ければ多いほど破産確率は低くなるはずですし、実際、そうなっています。()の中の数字は必ず1未満の数字ですから、乗数は大きければ大きいほど、破産確率は小さくなります。

例)
$$0.8\ >\ 0.8^{2} \ >\ 0.8^{3} \ >\ 0.8^{4} \ ….$$

この最初の公式だけでも、「資金量を聞かれてないのに破産確率がわかるのはおかしい」と判断できますね。この公式は、今後のさらに実践的な公式の基礎となる部分なので、ぜひ押さえておいてください。

1)高校数学の「確率」から考える

では、なぜ上記のような式になるのか確認しておきましょう。まずはスタートとして、高校数学の「確率」から考えます。資金がn円のときに破産する確率をQ(n)とします。

例えば、現在の所持金を100円だと仮定しましょう。今が何回目のトレードかはわかりません。わかりませんが、とにかく何回目かのトレードの時点で所持金が100円になりました。所持金100円なので、もちろんまだ破産していません。

所持金100円の時点から将来的に破産する確率は、Q(100)です。ここまでは問題ないと思います。

では、さらに所持金100円の次に取りうる状態を考えてみましょう。「勝ったら1円儲かる」「負けたら1円失う」というトレードですから、次の所持金は、勝って101円になるか、負けて99円になるか、の2通りしかありません。

つまり「所持金100円で破産する確率」というのは、以下の2つの確率の合計で表すことができます。(Pは勝率)

1)所持金100円で将来的に破産する確率 Q(100)
2)次に所持金101円になって将来的に破産する確率 Q(101) × P
3)次に所持金99円になって将来的に破産する確率 Q(99) × (1-P)

(数式)
$${\small Q( 100) \ =\ Q( 101) \times P\ +\ Q( 99) \times ( 1-P) \ }$$

ここまでは大丈夫でしょうか?

2)漸化式にする

上記の式は、どの資金額の時点でも同じですから、以下のように一般化することができます。

 
$$Q( n) \ =\ Q( n+1) \times P\ +\ Q( n-1) \times ( 1-P) \ $$

 
これは私と違って高校時代にちゃんと数学を勉強していた方なら、見覚えがあるかもしれません(笑)。「漸化式」というやつですね。もっと具体的にいうと、3項間漸化式(特性方程式)というジャンルの問題です。

さすがにここで漸化式の解き方を0から解説すると終わらなくなるので、もし漸化式がわからない方は以下のYouTube講義動画を見てください。めちゃくちゃわかりやすいです。私の高校時代もこうやって教えて欲しかった…。

とある男が授業してみた 【高校数学】数B-93漸化式7

では同じやり方で解いてみましょう。

3)特性方程式を解く

$${\small Q( n) \ =\ P\cdotp Q( n+1) \ +\ ( 1-P) \cdotp Q( n-1)}$$

まずは高校数学の教科書と同じ感じになるように、Q(n-1) を an に置き換えましょう。

$$a_{n+1} \ =\ P\cdotp a_{n+2} \ +\ ( 1-P) \cdotp a_{n}$$

するとこれは高校で習う三項間漸化式の問題なので、以下のような特性方程式を考えます。この特性方程式の解を使うと、上記の式を綺麗に変形することができるからです。

(特性方程式)
$$x\ =\ P\cdotp x^{2} \ +\ ( 1-P)$$

この方程式を因数分解すると以下のようになります。

$${\small P( x-1)\left( x-\frac{1-P}{P}\right) \ =\ 0}$$
$$よって解は、\ x\ =\ \ 1,\ \frac{1-P}{P}$$

このことから、特性方程式の性質(二次方程式の「解と係数の関係」)を使って、最初の式は以下のように変形できます。

$$a_{n+2} \ -\ a_{n+1} \ =\ \frac{1-P\ }{P}( a_{n+1} \ -\ a_{n})$$

これは、公比が (1-P)/P の階差数列です。

階差数列というのは、各項目の間隔が等比数列や等差数列になっている順列のことです。つまり、破産確率の関数Q(n)は、資金が1円ずつ増えるたびに、どんどん破産の可能性が低くなるものの、その減り幅は ×(1-p)/P ずつ狭くなる関数だということがわかります。

さて、上記は階差数列なので、以下の公式を使うと a(n) の一般項を求めることができます。(階差数列の公式

$$\begin{array}{l}
a_{n+1} -a_{n} \ の部分を\ b_{n} とおくと、\\
\\
b_{n+1} =\left(\frac{1-P}{P}\right) b_{n} \ \ となるので、\ b_{n} は公比数列です。\\
\\
公比数列の公式により、b_{n} \ の一般項は、\\
\\
b_{n} =b_{1} \ \cdotp \left(\frac{1-P}{P}\right)^{n-1} となります。\\
\\
\\
そのため、n\ \geq 2\ のときの\ a_{n} の一般項は、\\
\\
a_{n} \ =\ a_{1} +{\displaystyle \sum ^{n-1}_{k=1} b_{k}}\\
\\
=a_{1} +{\displaystyle \sum ^{n-1}_{k=1} \ ( a_{2} \ -\ a_{1}) \cdotp \ \left(\frac{1-P}{P}\right)^{k-1} \ }\\
\\
=a_{1} +( a_{2} -a_{1}){\displaystyle \sum\limits ^{n-1}_{k=1}\left(\frac{1-P}{P}\right)^{k-1}}\\
\\
となります\\
\
\end{array}$$

では、これを最初の破産確率の Q(n) に戻してみましょう。
すると以下のようになりますね。

$$Q( n) =Q( 0) +( Q( 1) -Q( 0)) \cdotp {\displaystyle \sum ^{n}_{k=1}} \ \left(\frac{1-P}{P}\right)^{k-1}$$

また資金が0円のときの破産確率 Q(0) は当然、100%(=1)です。そのため、Q(0) には1を代入していきます。ついでに見やすいように、(1-P)/P はいったん、rと置き換えましょう。

$$Q( n) =1+( Q( 1) -1) \cdotp {\displaystyle \sum ^{n}_{k=1}} \ r^{k-1}$$

数列の和の公式」を使えば、シグマも外すことができますね。
これも外しておきましょう。

$$Q( n) =1+( Q( 1) -1) \cdotp \left(\frac{r^{n} -1\ }{r-1}\right)$$

これでいったん完成です。

ですが、まだ最初のシンプルな公式からは程遠いですね。破産確率 Q(1)の正体がわかれば、一気に公式に辿り着けるのですが、この時点ではまだQ(1)が何かはわかりません。

・Q(1) ⇒ 資金が1円のときに将来破産する確率

例えば、資金が1円で勝率が80%の場合、破産確率 Q(1) は、パッと考えると 20%のような気もしますが、そう簡単ではありません。もし次のトレードで勝って破産を免れたとしても、その後に2連敗すれば破産します。もし次とその次のトレードに勝っても、その後に3連敗すれば破産します。

つまり勝率80%の中に、まだ将来破産する確率 Q(2) が含まれていて、資金2円の時点での勝率には 将来破産する確率Q(3)が含まれているので、結局、堂々巡りになるわけです。

実は、この資金が1円のときの破産確率 Q(1) は、負けのオッズ比 、つまり (1-P)/P にピッタリ一致するのですが、そのことは違うアプローチから証明することになります。

4)相手の資金量から破産確率を考える

現実的には、FXのトレードで世界中の資金を奪いつくすことはできません。ですが、数学はただの想像の世界なので、自由な仮定を置くことができます。例えば、相対取引でトレードの相手方の資金がX円であるような場合を考えましょう

「勝ったら1円貰える」「負けたら1円失う」というトレード勝負は、前提として勝率が50%以上という偏りがある以上、半永久的に繰り返せば必ずいつか終わります。つまり、相手の資金を奪いつくしたら終わるわけです。

この相手の資金を奪いつくした時点での自分の資金量を、仮に m円 とします。すると、m円の時点での破産確率は、Q(m)=0 となります。もう破産する可能性が無くなったからです。

 
$${\large Q( m) \ \ =\ 0\ }$$

 
これを先ほどの公式に当てはめると、以下のような方程式を作ることができます。

(方程式)
$$Q( m) =1+( Q( 1) -1) \cdotp \left(\frac{r^{m} -1\ }{r-1}\right) \ =0$$

これを頑張って展開すると、さっき未知数だった Q(1) を 相手の資金量 m円 を使って式に表すことができます。具体的にやってみるとわかりますが、以下のような式にできます。

※ 展開した後、分母と分子の両方に-1を掛けています。

$$Q( 1) \ =\ \frac{r-r^{m}}{1-r^{m}} \ $$

 
さて、現実の世界に戻りましょう。

実際のトレードの世界では、私のような普通の一般人が取引所や市場の資金を奪いつくすことはありえません。つまり、「相手の資金を奪いつくした時点での資金 m円」というのは、現実には辿り着けるはずのない、非常に大きい数字だと考えることができます。

さらに、r というのは何だったかを思い出してみましょう。

rで置き換えたのは、(1-P)/P で、これは「負ける確率 ÷ 勝つ確率」でしたね。これは勝率が50%を超えるとき、必ず1より小さい数になります。

以下の式を見てみると、rのm乗というのは、この1よりも小さい数をとてつもなく大きい指数で乗じたものです。

そのため、こちらの自己資金よりも相手の資金(市場の資金)がとてつもなく大きいときには、この「rのm乗」は無視していいほど小さな数字になります。

結果、さきほどわからないといった 資金1円のときの破産確率 Q(1) は、「市場の資金がとてつもなく大きい」という前提のもとでは、以下のようになるのです。

$$Q( 1) =\frac{r-r^{m}}{1-r^{m}} =r=\ \left(\frac{1-P}{P}\right)$$

例えば、勝率80%、負率20%のトレードを資金1円でスタートしたら、1/4の確率(25%)で破産するということですね。

では、ここで Q(1)=r とわかったので、さきほど「いったん完成」と言っていた式に代入してみましょう。

$$\begin{array}{l}
Q( n) =1+( Q( 1) -1) \cdotp \left(\frac{r^{n} -1\ }{r-1}\right)\\
\\
=\ 1+( r-1) \cdotp \left(\frac{r^{n} -1}{r-1}\right)\\
=1+\left( r^{n} -1\right)\\
=r^{n}\\
\\
=\left(\frac{1-P}{P}\right)^{n}
\end{array}$$

驚くほど気持ちよく消えてシンプルな式になります。
これで最初の公式に辿り着くことができました!
お疲れ様でした!

$${\large 破産する確率\ Q( n) \ =\ \left(\frac{1-P}{P}\right)^{n}}$$

次回

この公式だけでは、実際のトレードではあまり役に立ちません。実際のトレードでは、勝率が50%以上とは限りませんし、平均利益と平均損失の割合も違いますし、さらに毎回のエントリー価格やロット数(賭け金)も異なります。

次回の記事は、この続きで「平均利益と平均損失が異なる場合」について解説します。さらに「口座の一定率をリスクに晒す場合(毎回の賭け金が異なる場合)」について解説し、最終的にはpythonを使って、口座のリスク割合ごとの破産確率をシミュレーションできるようにする予定です。

すべての指標やツールは、何らかの具体的な意思決定に役立ってはじめて意味があります。「へぇ、私のBOTの破産確率は〇%なんだ」という感想で終わったら実用性はありません。実際に口座のリスク率を決定するときの判断材料として役立つようなpythonコードを作っていきましょう。

次回の記事:
FXの破産確率を高校数学で理解しよう!(2)

追記

その後さらに調べたところ、巷に出回っているバルサラ破産確率表は、ナウザー氏の著書から転載されていたようです。原著を確認したところ、前提条件は「所持金1円の状態で1円を賭けてトレードした場合」と「所持金2円の状態で1円を賭けてトレードした場合」の破産確率でした。

▽ 原著の破産確率表

出典「Money Management Strategies for Futures Traders

これは「1回のトレードですべての資金を失うようなリスクを取った場合」の破産確率なので、実際のトレードでは少し考えにくい資金条件ですが、これを正しく転載していれば、数字自体は一致することが確認できました。