期待利益がマイナスの戦略は捨てるべきか

本題に入る前に基本的なことを確認しておく。

期待利益とシャープレシオの関係

ここに1年当たり100トレード、1トレード当たりの期待利益が0.1%、リスクが1.0%の戦略があるとする。単純化して考えると、1年当たりの期待利益は0.1% * 100 = 10.0%、リスクは√Tルールに基づけば1.0% * sqrt(100) = 10.0%となる。したがって、シャープレシオは10.0 / 10.0 = 1.0となる。これを戦略Aとする。

一方、1年当たり100トレード、1トレード当たりの期待利益が0.2%、リスクが4.0%の戦略があるとする。同様に考えて、1年当たりの期待利益は0.2% * 100 = 20.0%、リスクは4.0% * sqrt(100) = 40.0%となる。したがって、シャープレシオは20.0 / 40.0 = 0.5となる。これを戦略Bとする。

戦略Bの期待利益は戦略Aの2倍である。では戦略Bのほうが優れているかといえばそういうわけではない。1年後の利益はリスクも考慮すると1年当たりの期待利益 ± 1年当たりのリスクであるから、戦略Aは10% ± 10%、つまり0%〜20%となる。一方、戦略Bは20% ± 40%、つまり-20%〜60%となる。

都合よく考えると、戦略Aは20%、戦略Bは60%の利益だから戦略Bのほうがいいということになるが、果たしてそうか。逆に都合悪く考えると、戦略Aは0%、戦略Bは-20%となり、戦略Aは単に利益が出ないだけだが、戦略Bは-20%の損失である。だが、リスクを等しくしないと比較できないのである。

戦略Aで戦略Bと同じ4.0%のリスクを覚悟できるなら、投資額を4倍にすればいい(資金があればだが)。すると、期待利益も4倍になり、1年当たりの期待利益は0.4% * 100 = 40%、リスクは4.0% *sqrt(100) = 40%となる。1年後のリスクは40% ± 40%、つまり0〜80%となり、都合よく考えても、都合悪く考えても戦略Aは戦略Bより優れている。

つまり、期待利益が大きいかどうかが大事なのではなく、期待利益とリスクの比、つまりシャープレシオが大きいかどうかが大事なのである。期待利益は小さいがシャープレシオが大きい戦略は、期待利益は大きいがシャープレシオが小さい戦略と同じリスクを負うことで後者より大きい利益を生むことができるのである(机上の計算では)。

期待利益がマイナスの戦略でも役に立つ場合がある

さて、期待利益とシャープレシオの関係を確認したところで本題に入る。

ここに勝つ場合は+1、負ける場合は-1で一定で、1年当たり12回勝ち、8回負けるという戦略Aがあるとする。計算すると、期待利益は0.2、リスクは0.98、シャープレシオは0.91となる。

一方、勝つ場合は+0.5、負ける場合は-0.5で一定で、戦略Aが勝てば必ず負け、負ければ必ず勝つという戦略Bがあるとする。計算すると、期待利益は-0.1、リスクは0.49、シャープレシオは-0.91となる。

戦略Aと戦略Bの相関係数を求めると-1.0となる。勝敗が正反対なのであるから当然である。

ここで戦略Aと戦略Bを合わせた戦略Cを考えてみる。計算すると、期待利益は0.1、リスクは0.49、シャープレシオは0.91となる。戦略Aと比べると、期待利益は半減したが、リスクも半減したのでシャープレシオは変わらない。したがって、戦略Cはシャープレシオにおいて戦略Aと同等である。戦略Cが投資額を倍にして戦略Aと同じリスクを負うなら、期待利益も同じになる(資金の使い方としては非効率だが)。

ところで、戦略Bの負けを1つだけ勝ちだったことにしてみる。再計算すると、期待利益は-0.05、リスクは0.49、シャープレシオは-0.45となる。元の戦略と比べると、期待利益は半減したが、リスクはそのままなので、シャープレシオも半減する。ただし、期待利益はマイナスなので、これは改善である。

戦略Aと新しい戦略Bの相関係数を求めると-0.91となる。勝敗が完全には反対でないので、これも当然である。

そして、戦略Aにこの新しい戦略Bを合わせて新しい戦略Cを考えてみる。再計算すると、期待利益は0.15、リスクは0.57、シャープレシオは1.17となる。戦略Aと比べると、期待利益は減少しているが、リスクはそれ以上に減少しているので、シャープレシオは大きくなっている。したがって、新しい戦略Cはシャープレシオにおいて戦略Aより優れている。

つまり、新しい戦略Bを加えることによって戦略Aは改善されたのである。だが、新しい戦略Bの期待利益は-0.05であり、マイナスである。にもかかわらず、戦略Aを改善したのだ。

したがって、期待利益がマイナスの戦略でも役に立つ場合があると言える。ならば、いきなり捨てたりはせずに使い道がないか考えてみてもいいのではないだろうか。

a =  [ 1  1  1  1  1  1  1  1  1  1  1  1 -1 -1 -1 -1 -1 -1 -1 -1]
mean_a =  0.2
std_a =  0.979795897113
sharpe_a =  0.912870929175
b =  [-0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5  0.5  0.5  0.5
  0.5  0.5  0.5  0.5  0.5]
mean_b =  -0.1
std_b =  0.489897948557
sharpe_b =  -0.912870929175
cor_ab =  -1.0
c =  [ 0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5 -0.5 -0.5 -0.5
 -0.5 -0.5 -0.5 -0.5 -0.5]
mean_c =  0.1
std_c =  0.489897948557
sharpe_c =  0.912870929175
b2 =  [ 0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 -0.5  0.5  0.5  0.5
  0.5  0.5  0.5  0.5  0.5]
mean_b2 =  -0.05
std_b2 =  0.497493718553
sharpe_b2 =  -0.449466574975
cor_ab2 =  -0.902670933848
c2 =  [ 1.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5  0.5 -0.5 -0.5 -0.5
 -0.5 -0.5 -0.5 -0.5 -0.5]
mean_c2 =  0.15
std_c2 =  0.572276157113
sharpe_c2 =  1.17219699775

サンプルプログラム

○以下のコマンドをSpyderの「IPython console」にコピー&ペーストして「Enter」キーを2回押す。

# coding: utf-8

import numpy as np

a = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
              1, 1, -1, -1, -1, -1, -1, -1, -1, -1])
print('a = ', a)
mean_a = np.mean(a)
print('mean_a = ', mean_a)
std_a = np.std(a)
print('std_a = ', std_a)
sharpe_a = mean_a / std_a * np.sqrt(20)
print('sharpe_a = ', sharpe_a)

b = np.array([-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
              -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
print('b = ', b)
mean_b = np.mean(b)
print('mean_b = ', mean_b)
std_b = np.std(b)
print('std_b = ', std_b)
sharpe_b = mean_b / std_b * np.sqrt(20)
print('sharpe_b = ', sharpe_b)

cor_ab = np.corrcoef(a, b)[0][1]
print('cor_ab = ', cor_ab)

c = a + b
print('c = ', c)
mean_c = np.mean(c)
print('mean_c = ', mean_c)
std_c = np.std(c)
print('std_c = ', std_c)
sharpe_c = mean_c / std_c * np.sqrt(20)
print('sharpe_c = ', sharpe_c)

b[0] = 0.5
b2 = b
print('b2 = ', b2)
mean_b2 = np.mean(b2)
print('mean_b2 = ', mean_b2)
std_b2 = np.std(b2)
print('std_b2 = ', std_b2)
sharpe_b2 = mean_b2 / std_b2 * np.sqrt(20)
print('sharpe_b2 = ', sharpe_b2)

cor_ab2 = np.corrcoef(a, b2)[0][1]
print('cor_ab2 = ', cor_ab2)

c2 = a + b2
print('c2 = ', c2)
mean_c2 = np.mean(c2)
print('mean_c2 = ', mean_c2)
std_c2 = np.std(c2)
print('std_c2 = ', std_c2)
sharpe_c2 = mean_c2 / std_c2 * np.sqrt(20)
print('sharpe_c2 = ', sharpe_c2)
(2016/11/15更新)

コメント

非公開コメント