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

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

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

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

\[ 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更新)