こんな「シストレ」は嫌だ

架空の「シストレ」

ちょっとふざけたタイトルにしてみたが、内容もちょっとふざげている。この記事では「シストレ」を「業者が提供するストラテジーを選択し、自動で売買させること」という意味で使うことにする。

ここに5000のストラテジーを持つ架空のシストレ業者があるとしよう。ストラテジーには0から4999までのナンバーが付いている。そして、各ストラテジーを収益率でランキング付けたところ、ある年の上位10位のパフォーマンスは以下のようであった。

     Rank  Profit(%)
821     1     287.63
1641    2     266.44
44      3     254.50
412     4     254.12
4838    5     240.87
39      6     239.94
4353    7     238.15
1010    8     234.44
3915    9     232.49
4991   10     228.95

収益率が100%であれば資金を倍にしたことになる。ランキング1位の収益率は287.63%であるから4倍近くにまで増やしたことになる。10位でも228.95%であるから3倍以上である。

さて、翌年の上位10位のパフォーマンスは以下のようであった。

     Rank  Profit(%)
4087    1     299.07
4272    2     279.69
2574    3     270.01
1       4     267.88
3086    5     265.18
4394    6     261.54
964     7     252.25
2713    8     249.55
304     9     249.28
3662   10     246.18

さらに翌々年の上位10位のパフォーマンスは以下のようであった。

     Rank  Profit(%)
1734    1     317.56
2894    2     277.21
3771    3     265.88
1104    4     255.95
3438    5     253.59
2925    6     250.31
2800    7     232.86
1377    8     231.03
3779    9     229.89
961    10     229.67

やはり1位なら4倍前後、10位でも3倍以上となっている。だがストラテジーのナンバーを見ると分かるように3年間を通して上位に入ったストラテジーはない。

実はすべて乱数

察しのいい人は気付いているだろうが、いや、すでに見出しでバレている。これは期待収益率が0%になるように乱数を発生させ、5000回シミュレーションを繰り返して、収益率の上位10位をピックアップしたものである。期待収益率が0%でも5000回のうちの上位10位となると200%を超えるのである。ちなみに各年の平均収益率はそれぞれ-1.61%、0.44%、-1.30%であった。

どこそこのシストレ業者もこれと同じ、などというつもりはない。だが乱数でもこれくらいのことはできると知っておけば、誇大広告に踊らされることもなくなるだろう。

サンプルプログラム

1年を260営業日、毎日1回トレードするという設定でシミュレーションした。1日のボラティリティを1%とし、レバレッジ5倍でトレードしている。

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

import numpy as np
import pandas as pd

strategy = np.empty([5000, 2])
strategy = pd.DataFrame(strategy,
                        columns=['Rank', 'Profit(%)'])
n_strategies = 5000
n_trades = 260
n_year = 3
volatility = 0.01
leverage = 5
for i in range(n_year):
    for j in range(n_strategies):
        ret = np.random.randn(n_trades) * volatility * leverage
        ret = pd.Series(ret)
        cumret = ret.cumsum()
        strategy.iloc[j, 1] = cumret.iloc[n_trades-1] * 100
    strategy = np.round(strategy.sort_values(by='Profit(%)',
                                             ascending=False), 2)
    for j in range(n_strategies):
        strategy.iloc[j, 0] = str(int(j + 1))
    print(strategy.head(10))
    print('mean = ', np.round(strategy['Profit(%)'].mean(), 2))
    print('\n')
(2017/01/28更新)