破産確率の計算をしてみましたので、次は期待値を計算してみます。
計算式
計算式は次の通りです。
1ユニット当たりの期待値 = [勝率 × (平均利益 ÷ 平均損失)] - [敗率 × (平均損失 ÷ 平均損失)]
1ユニット当たりの期待値を計算すると次の通りです。
- 勝率: 60%
- 平均利益: $2,000
- 平均損失: $2,000
E(R) = [60% * ($2,000 / $2,000)] - [40% * ($2,000 / $2,000)] = 20%
1トレードにつき$2,000のリスクをとるとして、1トレード当たりの期待値を計算すると次の通りです。
= 20% * $2,000 = $400
1ドルにつき20セントの利益が得られる期待値という意味の20%ですね。
パラメーターは次の通りです。
- 勝率
- 平均利益
- 平均損失
明らかに、売買ルールの開発で勝率はそれほど重要ではない。 重要なのは、かなり確かなプラスの期待値を持つ売買ルールを作ることだ。 期待値は勝率とペイオフレシオから成り立っている。
リスクマネジャーであるあなたは勝率ではなく、期待値を上げるように売買ルールを開発する必要がある。 いったんマーケットに参加したら、勝率ではなく期待値を理由にトレードを行わなければならない。
システムトレード 基本と原則(ウィザードブックシリーズ) : ブレント・ペンフォールド
勝率だけではなく、ペイオフレシオ(リスクリワードレシオ)だけでもなく、期待値を上げるようにしなければいけないのですね。
期待値計算
破産確率の計算に追加する形にしてみました。
ソース
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>期待値計算</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.min.js"></script>
</head>
<body>
<div id="calculation"></div>
<script type="text/babel">
const style = {
number: {
color: "#555",
fontFamily: 'Avenir, "Open Sans", "Helvetica Neue", Helvetica',
fontSize: "14px",
textAlign: "right"
}
};
class Calculation extends React.Component {
constructor(props) {
super(props);
this.state = {
r1: '0.00',
r2: '0.00',
e: '0.00'
};
}
render() {
return (
<div>
<form>
<table>
<tbody>
<tr>
<th width="30%">
資金(A)
</th>
<td width="70%">
<input type="text"
ref={ c => this._A = c }
onFocus={ this.handleFocus.bind(this) }
onBlur={ this.handleBlur.bind(this) }
pattern="\d*"
placeholder="1,000,000"
style={ style.number } />
</td>
</tr>
<tr>
<th>
破産基準(B)
</th>
<td>
<input type="text"
ref={ c => this._B = c }
onFocus={ this.handleFocus.bind(this) }
onBlur={ this.handleBlur.bind(this) }
pattern="\d*"
placeholder="100,000"
style={ style.number } />
</td>
</tr>
<tr>
<th>
賭け金の比率(k)
</th>
<td>
<input type="text"
ref={ c => this._k = c }
onFocus={ this.handleFocus.bind(this) }
onBlur={ this.handleBlur.bind(this) }
pattern="\d*"
placeholder="0.02"
style={ style.number } />
</td>
</tr>
<tr>
<th>
勝率(P)
</th>
<td>
<input type="text"
ref={ c => this._P = c }
onFocus={ this.handleFocus.bind(this) }
onBlur={ this.handleBlur.bind(this) }
pattern="\d*"
placeholder="0.4"
style={ style.number } />
</td>
</tr>
<tr>
<th>
平均利益(a)
</th>
<td>
<input type="text"
ref={ c => this._a = c }
onFocus={ this.handleFocus.bind(this) }
onBlur={ this.handleBlur.bind(this) }
pattern="\d*"
placeholder="30"
style={ style.number } />
</td>
</tr>
<tr>
<th>
平均損失(b)
</th>
<td>
<input type="text"
ref={ c => this._b = c }
onFocus={ this.handleFocus.bind(this) }
onBlur={ this.handleBlur.bind(this) }
pattern="\d*"
placeholder="10"
style={ style.number } />
</td>
</tr>
<tr>
<th>
破産確率
</th>
<td>
<span>{ this.state.r1 }%
〜
{ this.state.r2 }%</span>
</td>
</tr>
<tr>
<th>
期待値
</th>
<td>
<span>{ this.state.e }%</span>
</td>
</tr>
<tr>
<th></th>
<td>
<input type="button" value="計算する" onClick={ this.handleClick.bind(this) } />
</td>
</tr>
</tbody>
</table>
</form>
</div>
);
}
addComma(v) {
return v.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
}
removeComma(v) {
return v.replace(/,/g, '');
}
calculateX(P, R) {
const SCALE = 5;
const xs = Immutable.Range(0, 1, 1 / Math.pow(10, SCALE));
const Ss = xs.map(x => P * Math.pow(x, R + 1) - x + 1 - P);
const min = Ss.sortBy(S => Math.abs(S)).minBy(S => Math.abs(S));
const result = Ss.keyOf(min) / Math.pow(10, SCALE);
return result;
}
calculateR(P, k, R, A, B) {
const a = Math.log(1 + R * k);
const b = Math.abs(Math.log(1 - k));
const n = Math.log(A / B);
const x = this.calculateX(P, a / b);
const result = {
from: Math.pow(x, n / b + 1),
to: Math.pow(x, n / b)
};
return result;
}
calculateE(P, a, b) {
return P * (a / b) - (1 - P) * (b / b);
}
calculate() {
const A = this.removeComma(this._A.value);
const B = this.removeComma(this._B.value);
const k = this.removeComma(this._k.value);
const P = this.removeComma(this._P.value);
const a = this.removeComma(this._a.value);
const b = this.removeComma(this._b.value);
if (!A || isNaN(A)) return;
if (!B || isNaN(B)) return;
if (!k || isNaN(k)) return;
if (!P || isNaN(P)) return;
if (!a || isNaN(a)) return;
if (!b || isNaN(b) || b === 0) return;
const R = a / b;
const r = this.calculateR(P, k , R, A, B);
this.setState({
r1: (r.from * 100).toFixed(2),
r2: (r.to * 100).toFixed(2),
e: (this.calculateE(P, a, b) * 100).toFixed(2)
});
}
handleClick(event) {
this.calculate();
}
handleFocus(event) {
event.target.value = this.removeComma(event.target.value);
}
handleBlur(event) {
event.target.value = this.addComma(event.target.value);
}
};
ReactDOM.render(
<Calculation />,
document.getElementById('calculation')
);
</script>
</body>
</html>
3 November 2016 追記
期待値の表を作成してみました。