ランダムウォークのバンドウォークと計算期間の関係

バンドウォークとは

ここにおけるバンドウォークとは終値の移動平均を安値が連続して上回る、または高値が連続して下回る期間とする。符号は上回る場合はプラス、下回る場合はマイナスとしている。今回、ランダムウォークのデータにおいて、ある計算期間のバンドウォークがどのくらいかになるかを調べてみる。これを第1のパターンとする。

また、終値の移動平均を終値が連続して上回る、または終値が連続して下回る期間というパターンでも調べてみた。これを第2のパターンとする。

第一感としてはバンドウォークとその計算期間は比例するのではないかと思われる。そこで、計算期間を説明変数、バンドウォークの標準偏差を目的変数とする線形モデルを想定した。モデルは具体的には以下のようである。

バンドウォークの標準偏差 = 傾き * 計算期間 + 切片

バンドウォークと計算期間は比例関係

検証の結果は以下のグラフの通りである。

先ず、第1のパターンでは、

バンドウォークの標準偏差(高値・安値ベース) = 0.608286152451 * 計算期間 + (-1.1255204743)

という関係にあるようである。もちろん、乱数を用いているので、結果は毎回わずかな違いがある。

次に、第2のパターンでは、

バンドウォークの標準偏差(終値ベース) = 0.641485021915 * 計算期間 + 2.75461596213

という関係にあるようである。

第1のパターン、第2のパターンともにバンドウォークと計算期間は比例関係にあるようである。また、第1のパターンのほうが第2のパターンよりいくらか傾きがゆるやかである。これは高値や安値のほうが終値より先に移動平均線にタッチするため、バンドウォークが短くなるからで、容易に理解できるだろう。

ただ、なぜ傾き、切片がこのような数値となるのか、その数学的根拠は分からない。今回はシミュレーションによって経験的には大体以上のような関係にあるということを確認したことで満足することとする。

サンプルプログラム

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

import forex_system as fs
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit

def func(period, slope, intercept):
    return slope * period + intercept

fs.remove_temp_folder()

timeframe = 5

actual_value = np.empty(50)
plt.figure(figsize=(6, 8))
period = np.array(range(5, 255, 5))
for i in range(50):
    actual_value[i] = fs.i_bandwalk('RANDOM', timeframe, period[i],
    'MODE_SMA', 0).std()
popt, pcov = curve_fit(func, period, actual_value)
slope = popt[0]
intercept = popt[1]
predicted_value = slope * period + intercept
rmse = np.std(actual_value - predicted_value)
ax=plt.subplot(2, 1, 1)
plt.plot(period, actual_value, label='Actual Value')
plt.plot(period, predicted_value, label='Predicted Value')
plt.title('Bandwalk(High&Low) and Period')
plt.xlabel('Period')
plt.ylabel('Bandwalk')
plt.xlim(50, 250)
plt.text(0.05, 0.9, 'Slope = ' + str(slope), transform=ax.transAxes)
plt.text(0.05, 0.85, 'Intercept = ' + str(intercept), transform=ax.transAxes)
plt.text(0.05, 0.8, 'RMSE = ' + str(rmse), transform=ax.transAxes)
plt.legend(loc="lower right")
print('Slope = ', slope)
print('Intercept = ', intercept)
print('RMSE = ', rmse)

actual_value = np.empty(50)
period = np.array(range(5, 255, 5))
for i in range(50):
    actual_value[i] = fs.i_bandwalk_cl('RANDOM', timeframe, period[i],
    'MODE_SMA', 0).std()
popt, pcov = curve_fit(func, period, actual_value)
slope = popt[0]
intercept = popt[1]
predicted_value = slope * period + intercept
rmse = np.std(actual_value - predicted_value)
ax=plt.subplot(2, 1, 2)
plt.plot(period, actual_value, label='Actual Value')
plt.plot(period, predicted_value, label='Predicted Value')
plt.title('Bandwalk(Close) and Period')
plt.xlabel('Period')
plt.ylabel('Bandwalk')
plt.xlim(50, 250)
plt.text(0.05, 0.9, 'Slope = ' + str(slope), transform=ax.transAxes)
plt.text(0.05, 0.85, 'Intercept = ' + str(intercept), transform=ax.transAxes)
plt.text(0.05, 0.8, 'RMSE = ' + str(rmse), transform=ax.transAxes)
plt.legend(loc="lower right")
print('Slope = ', slope)
print('Intercept = ', intercept)
print('RMSE = ', rmse)
plt.tight_layout()
plt.subplots_adjust(hspace=0.3)
plt.savefig('bandwalk_period.png', dpi=150)
plt.show()

fs.remove_temp_folder()
(2017/01/30更新)