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

架空の「シストレ」

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

ここに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更新)

Ku-Chartとは何か②

Ku-Powerに通貨の近似値としての性質はないのかというとそうでもない。こんなことを考えてみた。

EURがJPYに対して1%上昇したとする。つまりEUR/JPYが1%上昇したのである。ではEURが1%上昇したのか、JPYが1%下落したのか。あるいはEURは2%上昇して、JPYが1%上昇したとか、EURは1%下落して、JPYが2%下落したとかいうことはないか。

「EURがJPYに対して1%上昇した」といっても、その内訳には無数の可能性がある。EURから見ると、EURは上昇する可能性と同じくらいに下落する可能性がある。他に情報がないなら、その平均をとって、EURは変化率0%とするべきだろう。とすればJPYが1%下落したのである。

だが、JPYから見ると、同様にJPYは上昇する可能性と同じくらいに下落する可能性がある。他に情報がないなら、その平均をとって、JPYも変化率0%とするべきだろう。とすればEURが1%上昇したのである。

ではEURとJPYのどちらから見るのが正しいのだろうか。他に情報がないなら、その平均をとるしかない。つまり、EURは0.5%上昇し、JPYは0.5%下落したのである。もし世界に通貨がEURとJPYしかないとすれば、このように解するべきだろう。

ここでUSDも加えてみる。

もし、EURがJPYに対して1%、USDに対して3%上昇したとする。

EURはEURから見ると0%、JPYから見ると+1%、USDから見ると+3%であるから、平均して1.33%上昇したと考える。

JPYはEURから見ると-1%、JPYから見ると0%、USDから見ると+2%であるから、平均して0.33%上昇したと考える。

USDはEURから見ると-3%、JPYから見ると-2%、USDから見ると0%であるから、平均して1.67%下落したと考える。

もし世界に通貨がEUR、JPY、USDしかないとすれば、このように解するべきだろう。そして、これがEUR、JPY、USDの3通貨モデルによるKu-Chartと同じであることが分かる。

つまり、モデルを構成する通貨の変化率以外に情報はない、モデルを構成する通貨以外の通貨は存在しないと仮定すれば、「EUR = Ku-EUR」、「JPY = Ku-JPY」、「USD = Ku-USD」と見なすことができ、Ku-Powerに通貨の近似値としての性質があることになる。

とまあ、理屈をこねても、トレードに資するとは限らないけどね。

(2017/01/01更新)

Ku-Chartとは何か①

Ku-Chart自体は有名なので、定義について議論するようなことはせず、ここではKu-Chartが表している価値が実質的に何であるのかということを考えてみる。

豪ドル、ユーロ、ポンド、円、米ドルの5通貨モデルで、ドルストレートのデータを材料にしてKu-Chartを作成した場合、以下のような計算式になる。

a = (log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY)) / 5
Ku-AUD = log(AUDUSD) - a
Ku-EUR = log(EURUSD) - a
Ku-GBP = log(GBPUSD) - a
Ku-JPY = -log(USDJPY) - a
Ku-USD = -a

これをさらに分解して計算してみる。

なお、計算過程がくどいが、私は計算過程を省略するのがあまり好きではないので(一歩一歩進めないと自分でも理解できない)、目をつぶっていただきたい。

a = (log(AUD/USD) + log(EUR/USD) + log(GBP/USD) - log(USD/JPY)) / 5
Ku-AUD = log(AUD/USD) - a
Ku-EUR = log(EUR/USD) - a
Ku-GBP = log(GBP/USD) - a
Ku-JPY = -log(USD/JPY) - a
Ku-USD = -a

a = (log(AUD) - log(USD) + log(EUR) - log(USD) + log(GBP) - log(USD) - log(USD) + log(JPY)) / 5
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = -log(USD) + log(JPY) - a
Ku-USD = -a

a = (log(AUD) + log(EUR) + log(GBP) + log(JPY) - log(USD) - log(USD) - log(USD) - log(USD)) / 5
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

a = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + {log(USD) - log(USD)} - log(USD) - log(USD) - log(USD) - log(USD)) / 5
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

a = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD) - log(USD) - log(USD) - log(USD) - log(USD) - log(USD)) / 5
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

a = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD) - (5 * log(USD))) / 5
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

a = ((log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD)) / 5) - (5 * log(USD)) / 5
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

a = ((log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD)) / 5) - log(USD)
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

mean = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD)) / 5
a = mean - log(USD)
Ku-AUD = log(AUD) - log(USD) - a
Ku-EUR = log(EUR) - log(USD) - a
Ku-GBP = log(GBP) - log(USD) - a
Ku-JPY = log(JPY) - log(USD) - a
Ku-USD = -a

mean = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD)) / 5
Ku-AUD = log(AUD) - log(USD) - (mean - log(USD))
Ku-EUR = log(EUR) - log(USD) - (mean - log(USD))
Ku-GBP = log(GBP) - log(USD) - (mean - log(USD))
Ku-JPY = log(JPY) - log(USD) - (mean - log(USD))
Ku-USD = -(mean - log(USD))

mean = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD)) / 5
Ku-AUD = log(AUD) - log(USD) - mean + log(USD)
Ku-EUR = log(EUR) - log(USD) - mean + log(USD)
Ku-GBP = log(GBP) - log(USD) - mean + log(USD)
Ku-JPY = log(JPY) - log(USD) - mean + log(USD)
Ku-USD = -mean + log(USD)

mean = (log(AUD) + log(EUR) + log(GBP) + log(JPY) + log(USD)) / 5
Ku-AUD = log(AUD) - mean
Ku-EUR = log(EUR) - mean
Ku-GBP = log(GBP) - mean
Ku-JPY = log(JPY) - mean
Ku-USD = log(USD) - mean

お疲れ様でした。

私たちは例えば「Ku-AUD」なら「AUD」、あるいは「log(AUD)」そのものではないにしても、その近似値のつもりで使っていると思う。だが、実際には少し違う。

「Ku-AUD = log(AUD)」となるためには「mean = 0」とならなければならないが、もちろん、そのようなことは保証されない。

ところで、「log(AUDUSD) = log(AUD) - log(USD)」であることを考えると

mean = log(MEAN)
Ku-AUD = log(AUD) - mean
Ku-AUD = log(AUD) - log(MEAN)
Ku-AUD = log(AUDMEAN)

となる。

つまり、構成する通貨の平均をクウォート通貨と見なす一種の通貨ペアと考えたほうが実態に近いかと思う。あるいは通貨平均乖離率と考えるほうが分かりやすいかもしれない。

どうでもいいことだが、常に「mean = 0」となるためには「log(1) = 0」であるから常に「MEAN = 1」である必要がある。

それはさて、例えばKu-Powerを組み合わせて

Ku-AUD - Ku-USD = log(AUDUSD)

とすることができるが、こういう性質もあたかも「Ku-AUD = log(AUD)」、あるいは「Ku-USD = log(USD)」であるかのような錯覚を起こしやすい。

だが、これは

Ku-AUD - Ku-USD = log(AUDUSD)
log(AUD) - log(MEAN) - (log(USD) - log(MEAN)) = log(AUDUSD)
log(AUD) - log(MEAN) - log(USD) + log(MEAN) = log(AUDUSD)
log(AUD) - log(USD) - log(MEAN) + log(MEAN) = log(AUDUSD)
log(AUD) - log(USD) = log(AUDUSD)

となって、余計な「log(MEAN)」を相殺してくれるからである。

Ku-Chartの有用性についてどうこう言うつもりはない。有用だと言う人はそれをうまく使っており、有用でないと言う人はそれをうまく使えていないだけのことだ。だが、Ku-Chartが表している価値は実質的にはこういうものであるということは頭に入れておいて損はないだろう。

(2016/12/28更新)

Ku-Chartの簡単な計算方法

Ku-Chartは計算が面倒臭い、プログラムの処理が重いと思っていたのは私だけだろうか。とっくに気付いている人もいると思うが、ふと簡単な計算方法があったことに気付いたので、私と同じ悩みを持つ人のために(笑)紹介する。ちょっと説明がくどいが、計算自体は簡単である。

例としてAUD、EUR、GBP、JPY、USDの5通貨モデルの計算方法を考えてみる。ドルストレートの通貨ペアのみを材料として使うと、

AUDUSD = AUD / USD
EURUSD = EUR / USD
GBPUSD = AUD / USD
USDJPY = USD / JPY

だから、

AUD / USD = AUDUSD
EUR / USD = EURUSD
GBP / USD = GBUSD
JPY / USD = 1 / USDJPY

となる。

さて、USDはどうするかだが、これは

USD / USD = 1

でいい。

まとめると

AUD / USD = AUDUSD
EUR / USD = EURUSD
GBP / USD = GBUSD
JPY / USD = 1 / USDJPY
USD / USD = 1

これを対数に変換すると、

log(AUD / USD) = log(AUDUSD)
log(EUR / USD) = log(EURUSD)
log(GBP / USD) = log(GBUSD)
log(JPY / USD) = log(1 / USDJPY)
log(USD / USD) = log(1) = 0

となる。

式を変形すると、

log(AUD) - log(USD) = log(AUDUSD)
log(EUR) - log(USD) = log(EURUSD)
log(GBP) - log(USD) = log(GBUSD)
log(JPY) - log(USD) = log(1) - log(USDJPY) = 0 - log(USDJPY) = -log(USDJPY)
log(USD) - log(USD) = 0

となり、さらに、

log(AUD) = log(AUDUSD) + log(USD)
log(EUR) = log(EURUSD) + log(USD)
log(GBP) = log(GBUSD) + log(USD)
log(JPY) = -log(USDJPY) + log(USD)
log(USD) = log(USD)

となる。

次に、合計が0になるように先ず平均を求める。

mean = (log(AUD) + log(EUR) + log(GB) + log(JPY) + log(USD)) / 5
     = (log(AUDUSD) + log(USD) + log(EURUSD) + log(USD) + log(GBUSD) + log(USD) - log(USDJPY) + log(USD) + log(USD)) / 5
     = (log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY) + log(USD) * 5) / 5
     = (log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY)) / 5 + log(USD)

「(log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY)) / 5」を「a」としておくと

mean = a + log(usd)

となる。

これを減じて合計を0にする。

log(AUD) - mean = log(AUDUSD) + log(USD) - mean = log(AUDUSD) + log(USD) - (a + log(USD)) = log(AUDUSD) - a
log(EUR) - mean = log(EURUSD) + log(USD) - mean = log(EURUSD) + log(USD) - (a + log(USD)) = log(EURUSD) - a
log(GBP) - mean = log(GBUSD) + log(USD) - mean = log(GBPUSD) + log(USD) - (a + log(USD)) = log(GBPUSD) - a
log(JPY) - mean = -log(USDJPY) + log(USD) - mean = -log(USDJPY) + log(USD) - (a + log(USD)) = -log(USDJPY) - a
log(USD) - mean = log(USD) - mean = log(USD) - (a + log(USD)) = - a

これをKu-Powerとすると

a = (log(AUDUSD) + log(EURUSD) + log(GBPUSD) - log(USDJPY)) / 5
Ku-AUD = log(AUDUSD) - a
Ku-EUR = log(EURUSD) - a
Ku-GBP = log(GBPUSD) - a
Ku-JPY = -log(USDJPY) - a
Ku-USD = -a

となる。

一々説明するとかえって複雑な感じもするが、理屈はどうあれ、Ku-Chartの計算をするときは最後の式を使えばいいわけで、簡単だ。「今ごろ気が付いたのか」と笑われるかもしれないが...。

(補足)

あまりいないと思うが、USDを除いたモデルを作りたい場合、どうするか。ドルストレートを材料にする場合、USDを除くことはできるのか。

実はUSDを除いたモデルでも計算方法は同じである。例としてAUD、EUR、GBP、JPYの4通貨モデルの計算方法を考えてみる。ドルストレートの通貨ペアのみを材料として使うと、

AUDUSD = AUD / USD
EURUSD = EUR / USD
GBPUSD = AUD / USD
USDJPY = USD / JPY

だから、

AUD / USD = AUDUSD
EUR / USD = EURUSD
GBP / USD = GBUSD
JPY / USD = 1 / USDJPY

となる。

これを対数に変換すると、

log(AUD / USD) = log(AUDUSD)
log(EUR / USD) = log(EURUSD)
log(GBP / USD) = log(GBUSD)
log(JPY / USD) = log(1 / USDJPY)

となる。

式を変形すると、

log(AUD) - log(USD) = log(AUDUSD)
log(EUR) - log(USD) = log(EURUSD)
log(GBP) - log(USD) = log(GBUSD)
log(JPY) - log(USD) = log(1) - log(USDJPY) = 0 - log(USDJPY) = -log(USDJPY)

となり、さらに、

log(AUD) = log(AUDUSD) + log(USD)
log(EUR) = log(EURUSD) + log(USD)
log(GBP) = log(GBUSD) + log(USD)
log(JPY) = -log(USDJPY) + log(USD)

となる。

次に、合計が0になるように先ず平均を求める。

mean = (log(AUD) + log(EUR) + log(GB) + log(JPY)) / 4
     = (log(AUDUSD) + log(USD) + log(EURUSD) + log(USD) + log(GBUSD) + log(USD) - log(USDJPY) + log(USD)) / 4
     = (log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY) + log(USD) * 4) / 4
     = (log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY)) / 4 + log(USD)

「(log(AUDUSD) + log(EURUSD + log(GBUSD) - log(USDJPY)) / 4」を「a」としておくと

mean = a + log(usd)

となる。

これを減じて合計を0にする。

log(AUD) - mean = log(AUDUSD) + log(USD) - mean = log(AUDUSD) + log(USD) - (a + log(USD)) = log(AUDUSD) - a
log(EUR) - mean = log(EURUSD) + log(USD) - mean = log(EURUSD) + log(USD) - (a + log(USD)) = log(EURUSD) - a
log(GBP) - mean = log(GBUSD) + log(USD) - mean = log(GBPUSD) + log(USD) - (a + log(USD)) = log(GBPUSD) - a
log(JPY) - mean = -log(USDJPY) + log(USD) - mean = -log(USDJPY) + log(USD) - (a + log(USD)) = -log(USDJPY) - a

これをKu-Powerとすると

a = (log(AUDUSD) + log(EURUSD) + log(GBPUSD) - log(USDJPY)) / 4
Ku-AUD = log(AUDUSD) - a
Ku-EUR = log(EURUSD) - a
Ku-GBP = log(GBPUSD) - a
Ku-JPY = -log(USDJPY) - a

となる。

要するに、USDを含めた5通貨モデルでは5で除していたところを4で除するように変更するだけである。こうすればドルストレートを材料にして、任意の組み合わせのKu-Chartを作成できる。

(2016/12/15更新)