確率のイメージ

確率をイメージしたアニメーション画像を作ってみた。

初めはランダムに見えるが…

最初は散布図に点がランダムにプロットされているだけのように見える。だが、しばらくすると、FX業界では割と有名な画像になる。

試行を繰り返して初めて見えてくる

物理学では二重スリット実験という有名な実験がある。電子を飛ばして写真乾板に当てる。だが、途中を2本のスリットのある板で塞ぐ。普通はスリットの後のところだけにしか電子は当たらないと思うだろう。

ところが、板で邪魔されているところにも電子は当たるのである。初めは電子がランダムに当たっているように見える。だが、電子を飛ばし続けると、電子の到達確率に応じた濃淡が生まれるのである。

今回のアニメーション画像はこの二重スリット実験を参考に作ってみた。色はR(赤)、G(緑)、B(青)をそれぞれ0-255の数値にして表すことができる。今回は元画像からR、G、Bがすべて128未満のピクセルに目がけて点を打ち込んだ。

物事の本質というのはわずかな試行や事例でそう簡単に見い出せるものではない。試行を繰り返し、多くの事例を集めて初めて見えてくるものなのである。

サンプルプログラム

①適当なpngファイルを用意し、「image_of_probability.png」ファイルとして「~/py」フォルダーに保存する。

②以下のプログラムをSpyderの「IPython console」にコピー&ペーストして「Enter」キーを2回押す。

import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

def func(i, x, y, frames):
    size = len(x)
    rng = int(size / frames)
    start = i * rng
    end = start + rng - 1
    plt.scatter(x[start:end], y[start:end], c='dimgray', marker='.')
    plt.title('Image of Probability')
    plt.xlim(0, 1)
    plt.ylim(0, 1)

plt.style.use('dark_background')
fig = plt.figure()
max_size = 100000
frames = 60
interval = 1000

img = Image.open("image_of_probability.png")
width = img.width
height = img.height
adj = np.sqrt(width * height / max_size)
width = int(width / adj)
height = int(height / adj)
img = img.resize((width, height))
size = width * height
x = np.zeros(size)
y = np.zeros(size)
for i in range(height):
    for j in range(width):
        rgb = img.getpixel((j, i))
        if rgb[0] < 128 and rgb[1] < 128 and rgb[2] < 128:
            x[width*i+j] = j / width
            y[width*i+j] = 1 - (i / height)

xy = np.c_[x, y]
np.random.shuffle(xy)
x = xy[:, 0]
y = xy[:, 1]

ani = animation.FuncAnimation(fig, func, fargs=(x, y, frames), frames=frames,
                              interval=interval)
plt.show()
ani.save('image_of_probability.gif', writer='imagemagick')

少し待つ(私の環境では15秒くらい)。設定によっては何も描画されていないウィンドウが表示されるが気にしない。終了すると「~/py」フォルダーに「image_of_probability.gif」ファイルが生成する。

(2017/02/19更新)

通貨の質量

独立した記事にするほどの分量でもないが、とりあえずメモとしてアップしておく。

質量とは動きにくさ

通貨の質量と言っても、500円硬貨は何グラムかという話ではない。物理学では質量とは動きにくさを意味する。ここでは通貨の動きにくさと言う意味で使うこととする。

動きにくさとは動きやすさの逆数

動きにくさとは見方を変えれば動きやすさの逆である。したがって、動きにくさは動きやすさの逆数として数値化することもできるだろう。

動きやすさとはボラティリティ

動きやすさとはつまりボラティリティである。ボラティリティが大きいということは小さな力で動かすことができ、ボラティリティが小さいということは大きな力でなければ動かすことができないということである。力とは例えば資金などであろうか。

つまり、質量とはボラティリティの逆数

以上をまとめると、質量とはボラティリティの逆数だということになる。物理学の運動方程式を用いれば以下のようになるだろう。

\[ \vec{F} = m\vec{a} \] \[ m = \frac {1} {v} \] \[ \vec{F} = \frac {\vec{a}} {v} \]

物理学で「v」としたら速度を意味することが多いので紛らわしいが、ここではボラティリティの意味で使う。ある方向に加速度が生じたら、つまり価格が上昇、または下落したら、その変動幅をボラティリティで除した量が力として働いたと考えることができる。

(2017/02/08更新)

ペアのボラティリティの分離

ペアのボラティリティを分離してベース、クウォートそれぞれのボラティリティを推測してみる。

ペアのボラティリティを計算

先ず、推測に当たって、以下のモデルを使用することとする。

\[ V_{BaseQuote} = \sqrt{V_{Base}^{2} + V_{Quote}^{2}} \]

次にA、B、Cというデータがあって、ボラティリティがそれぞれ1、2、3であるとする。

\[ V_{A} = 1 \] \[ V_{B} = 2 \] \[ V_{C} = 3 \]

そして、AB、BC、CAというペアを作り、モデルに基づいてボラティリティを計算する。

V_AB

\[ V_{AB} = \sqrt{V_{A}^{2} + V_{B}^{2}} \] \[ V_{AB} = \sqrt{1^{2} + 2^{2}} \] \[ V_{AB} = \sqrt{1 + 4} \] \[ V_{AB} = \sqrt{5} \]

V_BC

\[ V_{BC} = \sqrt{V_{B}^{2} + V_{C}^{2}} \] \[ V_{BC} = \sqrt{2^{2} + 3^{2}} \] \[ V_{BC} = \sqrt{4 + 9} \] \[ V_{BC} = \sqrt{13} \]

V_CA

\[ V_{CA} = \sqrt{V_{C}^{2} + V_{A}^{2}} \] \[ V_{CA} = \sqrt{3^{2} + 1^{2}} \] \[ V_{CA} = \sqrt{9 + 1} \] \[ V_{CA} = \sqrt{10} \]

ペアのボラティリティから逆算

各ペアのボラティリティは以下のようである。

\[ V_{AB} = \sqrt{5} \] \[ V_{BC} = \sqrt{13} \] \[ V_{CA} = \sqrt{10} \]

今度は逆算によって、A、B、Cそれぞれのボラティリティを求める。

準備①

\[ V_{AB}^{2} = \sqrt{5}^{2} \] \[ V_{BC}^{2} = \sqrt{13}^{2} \] \[ V_{CA}^{2} = \sqrt{10}^{2} \]

準備②

\[ V_{AB}^{2} = 5 \] \[ V_{BC}^{2} = 13 \] \[ V_{CA}^{2} = 10 \]

準備③

\[ V_{A}^{2} + V_{B}^{2} = 5 \] \[ V_{B}^{2} + V_{C}^{2} = 13 \] \[ V_{C}^{2} + V_{A}^{2} = 10 \]

V_A①

\[ (V_{A}^{2} + V_{B}^{2}) - (V_{B}^{2} + V_{C}^{2}) = 5 - 13 \] \[ V_{A}^{2} + V_{B}^{2} - V_{B}^{2} - V_{C}^{2} = -8 \] \[ V_{A}^{2} - V_{C}^{2} = -8 \]

V_A②

\[ (V_{A}^{2} - V_{C}^{2}) + (V_{C}^{2} + V_{A}^{2}) = -8 + 10 \] \[ (V_{A}^{2} - V_{C}^{2}) + V_{C}^{2} + V_{A}^{2} = 2 \] \[ 2 * V_{A}^{2} = 2 \] \[ V_{A}^{2} = 1 \] \[ V_{A} = \sqrt{1} \] \[ V_{A} = 1 \]

V_B

\[ V_{A}^{2} + V_{B}^{2} = 5 \] \[ 1 + V_{B}^{2} = 5 \] \[ V_{B}^{2} = 4 \] \[ V_{B} = \sqrt{4} \] \[ V_{B} = 2 \]

V_C

\[ V_{C}^{2} + V_{A}^{2} = 10 \] \[ V_{C}^{2} + 1 = 10 \] \[ V_{C}^{2} = 9 \] \[ V_{C} = \sqrt{9} \] \[ V_{B} = 3 \]

以上の計算から、A、B、Cのボラティリティがそれぞれ1、2、3であることが分かる。

EUR、JPY、USDのボラティリティを推測

EURJPY、EURUSD、USDJPYのボラティリティを用いてEUR、JPY、USDのボラティリティを推測してみる。データは2016年の日足を使う。ボラティリティはデータを対数変換してから求める。

先ず、EURJPY、EURUSD、USDJPYそれぞれのボラティリティは以下のようである。

v_ej =  0.008034703792983185
v_eu =  0.005214348106485007
v_uj =  0.007917959753776157

これに対して上の逆算を行うと以下のようになる。

v_e =  0.00381128617097714
v_j =  0.00707322859547864
v_u =  0.00355858453581227

サンプルプログラム

○以下のプログラムをSpyderの「IPython console」にコピー&ペーストして「Enter」キーを2回押す。

# coding: utf-8

import forex_system as fs
from datetime import datetime
from sympy import solve, symbols

start = datetime.strptime('2016.01.01 00:00', '%Y.%m.%d %H:%M')
end = datetime.strptime('2016.12.31 23:59', '%Y.%m.%d %H:%M')

v_ej = fs.i_log_return('EURJPY', 1440, 1, 0)[start:end].std()
v_eu = fs.i_log_return('EURUSD', 1440, 1, 0)[start:end].std()
v_uj = fs.i_log_return('USDJPY', 1440, 1, 0)[start:end].std()

print('v_ej = ', v_ej)
print('v_eu = ', v_eu)
print('v_uj = ', v_uj)

v_e, v_j, v_u = symbols('v_e v_j v_u')
ans = solve([v_e**2 + v_j**2 - v_ej**2, v_e**2 + v_u**2 - v_eu**2, v_u**2 +
             v_j**2 - v_uj**2], [v_e, v_j, v_u])
# 解が8個あるが、ボラティリティは負にならないので最後の解を採用する。
v_e = ans[7][0]
v_j = ans[7][1]
v_u = ans[7][2]

print('v_e = ', v_e)
print('v_j = ', v_j)
print('v_u = ', v_u)
(2017/02/08更新)

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

架空の「シストレ」

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

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