turtlechanのブログ

無知の私がLinuxをいじりながら書いていくブログ

【Python】ランダムウォークを再現してみる

先日ランダムウォーク(ブラウン運動)について調べたので、今回はPythonを使って(単純)ランダムウォークを再現してみようと思う。

turtlechan.hatenablog.com

※python2で書いてます。

計算式の確認

・ランダム

[X_n]_{ n = 0 }^{ infinity } = [x_0, x_1, x_2, ..., x_{ infinity  - 1 }, x_infinity]

規則性のない数字の羅列。

・(単純)ランダムウォーク

S_{ 0 } = a, S_{ n } = a + sum from{ i = 0 } to{ n - 1 } X_{ i }

P( X_n = d )=p, P( X_n = -d ) = q = 1 - p

ランダムをその都度加えていったものがランダムウォーク。ちなみに、ある値d が + か - の二択の場合は単純ランダムウォークでしたね。

ランダムウォークを再現する

ここからPythonを使って(単純)ランダムウォークをしてみたいと思います。
配列を使うので numpy とグラフ化が楽なので pandas を使います。

処理の流れは
ランダムの配列作成 → スタート地点(a)を決めて順に足し算
で良いでしょう。

ランダム と (単純)ランダムウォーク の違いを視覚的に確認・比較したい(私が)ので見出しを分けます。

ランダム

単純ランダムウォークにする前提なので -1 か +1 の二択の配列を作成して表示したいと思います。
とりあえず250個生成してます。また、値が一定になるように今回は seed(0) にしています。実行ごとで異なるとランダムウォークと比較できないので。

rnd.py
#! /usr/bin/env python
# coding: utf-8

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


def rnd():
    np.random.seed(0)
    return np.random.choice((-1, 1), 250)


if __name__ == '__main__':
    s = pd.Series(rnd())
    plt.show(s.plot(ylim=(-2, 2)))

実行結果

ランダムのグラフ

折れ線グラフなので分かりにくいかもしれませんが、y軸が不規則に -1 か +1 で変動しています。

(単純)ランダムウォーク

上記で作成したランダムな配列を np.cumsum() で足していけば良さそうです。
別ファイルを作って先程のスクリプトをインポートして利用する形で作ります。

rnd_walk.py
#! /usr/bin/env python
# coding: utf-8

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import rnd


if __name__ == '__main__':
    a = 0
    rndArr = np.hstack((a, np.cumsum(rnd.rnd()) + a))
    s = pd.Series(rndArr)
    plt.show(s.plot())

実行結果

単純ランダムウォークのグラフ

単純ランダムウォークのグラフが表示できたかと思います。ちなみに今回スタート地点(a)は 0 にしました。

おまけ

単純ランダムウォークをグラフ化してみましたが、株価の推移に似ていますよね。

この後の動き予測できますか?

-1 と +1 の確率がそれぞれ 1/2 でプラスに偏りすぎているので、下がると思いますか?
それとも、-5 で底を付いたので上昇トレンドでしょうか?

多分どちらも正しいのでしょう。ただし結果を見ればどちらかが間違っていることでしょう。不思議ですね。

答え

上昇してますね。。。

単純ランダムウォークのグラフ続き

seed の値を 0 にしたままランダムを250個から500個に拡張してランダムウォークにした。そして 250 ~ 500 までをグラフ化したものです。

ランダムなものを予測すること自体間違ってる?

ランダムは予測できないからランダムな訳で、予測できたらランダムではなくなります。そう考えれば、ランダムを予測するのは間違ったことでしょう。
けれど、人って無意識に予測しようとしますし、予測を立ててからでないと行動に移すのが難しいですよね。

株やFXではなおさらです。

おわりに

今回グラフを見て、-1 と +1 の確率が等しくてもかなり偏りが出ることが分かりました。確率は大数でないとあまり意味がないのは知っていましたが。。。
あと、話がそれるけど基本的に「勝ち」か「負け」のゲームでは手数料があるし、投資関係で言えば利益が出れば税金が掛かる。
何が言いたいかというと例えば 負けが -1 だとすれば 勝ちは +0.8 とかアンフェアなゲームじゃないですか。。。正規分布で言うと頂点がマイナス側にあるんですよ。恐ろしい。

何かの参考になれば幸いです。

【Python】matplotlibでローソク足を描画してみる

今回は、Python の matplotlib ライブラリを使ってローソク足のグラフを表示したいと思います。
私にとって matplotlib は奥が深すぎるので、単純にローソク足を表示するだけにします。

※python2で書いてます。

ライブラリのインストール

先に必要なライブラリをインストールしておきます。すでにインストール済の場合は必要ないです。
また、matplotlib.finance を使用する予定だったが ver 2.0 から非推奨となって使えなくなっていた。mpl_finance モジュールを使用してくれとのことだったので mpl_finance もインストールします。

 

matplotlib ライブラリのインストール

~$ sudo pip install matplotlib

mpl_finance モジュールのインストール

~$ sudo pip install mpl_finance

※仮想環境をホームディレクトリ下に配置している場合には'sudo'は不要。

ローソク足でグラフを描画

先に今回書いたPythonスクリプトを記述します。

以下の過去記事同様、元データは 汲めども尽きない 無尽蔵さん の過去データ、2015年度の日経225年間データを使用してます。

turtlechan.hatenablog.com

candle.py
#! /usr/bin/env python
# coding: utf-8

import codecs
import matplotlib.pyplot as plt
import mpl_finance as mpf


def line_graph(openList, highList, lowList, closeList):
    '''折れ線グラフの描画処理'''
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.plot(openList, label='open')
    ax.plot(highList, label='high')
    ax.plot(lowList, label='low')
    ax.plot(closeList, label='close')
    ax.legend()
    plt.show()


def candle_graph(openList, highList, lowList, closeList):
    '''ローソク足グラフの描画処理'''
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    mpf.candlestick2_ohlc(ax, openList, highList, lowList, closeList, width=1)
    ax.legend()
    plt.show()


def main():
    with codecs.open('./nikkei_225.csv', 'r', encoding='utf-8') as f:
        [next(f).encode('utf-8') for _ in range(2)]
        text = f.read().encode('utf-8')
        a = text.replace('\n', ',').split(',')
        openList = list(map(float, a[1::6]))
        highList = list(map(float, a[2::6]))
        lowList = list(map(float, a[3::6]))
        closeList = list(map(float, a[4::6]))
    # 折れ線グラフ
    line_graph(openList, highList, lowList, closeList)
    # ローソク足グラフ
    candle_graph(openList, highList, lowList, closeList)


if __name__ == '__main__':
    main()

違いが分かりやすいように、折れ線グラフで表示した後 ローソク足のグラフを表示するようにしました。

以下、実行結果。

折れ線グラフ

折れ線グラフ

ローソク足

ローソク足のグラフ

ローソク足で表示することができました。折れ線グラフと比較してもちゃんと描画できていますね。それにしてもローソク足すばらしい(分かりやすい)。

 

ざっくり解説。

import matplotlib.pyplot as plt
import mpl_finance as mpf

matplotlib と mpl_finance のインポート
matplotlib.pyplot は慣例どおり plt としています。
mpl_finance はもともと matplotlib.finance にあったので mpf としています。

 

def line_graph(openList, highList, lowList, closeList):
    '''折れ線グラフの描画処理'''
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.plot(openList, label='open')
    ax.plot(highList, label='high')
    ax.plot(lowList, label='low')
    ax.plot(closeList, label='close')
    ax.legend()
    plt.show()

折れ線グラフで表示するために作った関数。始値 高値 安値 終値 のリストを受け取る。

 

def candle_graph(openList, highList, lowList, closeList):
    '''ローソク足グラフの描画処理'''
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    mpf.candlestick2_ohlc(ax, openList, highList, lowList, closeList, width=1)
    ax.legend()
    plt.show()

これがローソク足のグラフを描画するために用意した関数。一行ずつ何をしてるか書いていこうと思う。

def candle_graph(openList, highList, lowList, closeList):

ローソク足で表示するために作った関数。始値 高値 安値 終値 のリストを受け取る。

fig = plt.figure()

変数 fig に Figure インスタンスを代入。いくつかのグラフを描くための用紙を用意したイメージ。

ax = fig.add_subplot(1, 1, 1)

変数 ax に Axes インスタンスを代入。先程の用紙(変数fig)にグラフを描く場所を確保してる感じ。
引数は(行, 列, 場所)を意味している。以下のサイトが分かりやすい。
add_subplot メソッドの引数の数字は何を表しているのか?

mpf.candlestick2_ohlc(ax, openList, highList, lowList, closeList, width=1)

candlestick2_ohlc() がローソク足を描画するためのメソッド。ohlc は引数の順番を意味していて、Open, High, Low, Close の順。
第一引数にはグラフを描く場所(Axesインスタンス)を指定する(今回は変数ax)。その後に ohlc を指定。width=1 を指定しているが、これはローソクの幅を指定している。
その他にも色々あるので 公式ドキュメント を読もう。matplotlib.finance になってるけど matplotlib.finance を mpl_finance で読み替えればいいだけ。

ax.legend()

グラフ(Axesインスタンス)に凡例を表示するようにしている。ちなみにローソク足にラベルはないので結局何も表示されない。

plt.show()

今まで描いた用紙をウィンドウを立ち上げて表示。

 

def main():
    with codecs.open('./nikkei_225.csv', 'r', encoding='utf-8') as f:
        [next(f).encode('utf-8') for _ in range(2)]
        text = f.read().encode('utf-8')
        a = text.replace('\n', ',').split(',')
        openList = list(map(float, a[1::6]))
        highList = list(map(float, a[2::6]))
        lowList = list(map(float, a[3::6]))
        closeList = list(map(float, a[4::6]))
    # 折れ線グラフ
    line_graph(openList, highList, lowList, closeList)
    # ローソク足グラフ
    candle_graph(openList, highList, lowList, closeList)

解説する必要はないが、一応書いておく。
元データを読み込んで 始値・高値・安値・終値 を各々 list型 で代入している。
その後 line_graph() 関数、candle_graph() 関数を呼び出しているだけ。

おわりに

株価の動きを視覚で確認したいときに使えそうですね。他にも証券会社のソフトで対応していない指標をプロットしたり、自分好みにカスタマイズできる。じっくり株価を分析したい場合捗りそうです。

ちなみにX軸を日付にしたり、メモリの間隔、軸のラベル、グラフのタイトルとかイジりたいところはたくさんあります。このくらいなら先が見えますが、matplotlib は好みのグラフを作ろうとすると結構調べたりしなくちゃいけなくなるので時間が掛かります。なので論文の資料作りでなければ、基本的にスルーしたほうが時間の節約になる(私だけかも)。

何かの参考になれば幸いです。

ランダムウォークについてちょっと調べた

今回はランダムウォークについて調べたので、自分が理解・整理するためにメモがてら記事にします。

はじめに

ランダムウォークについて調べた経緯

株価データをネットから持ってくるのが面倒なので、株価の推移を自分でシミュレーション(でっち上げ)しようと思った。そのためには株価の動き方を知らないといけません。でも、それが分かったら株取引成立しない(負けない)。と訳が分からなくなったので調べた。
どうやら株価の推移はファンダメンタルズ的な見方を抜きにすると、ランダムウォークに極めて近いらしい。

そう、ランダムウォーク。言葉としては知っているが、私はランダムウォークの事を知らない。

という訳で今回勉強しようかなと。

ランダムウォーク

ここからはランダムウォークについて調べたものを私なりにまとめたものです。

ランダムウォークとは

次に現れる位置が確率的に無作為(ランダム)に決定される運動。
(ウィキペディア から引用)

要するに、酔っ払ったおっさんの千鳥足のようなイメージですね。

ランダム

ランダムウォークを知る前に、ただの「ランダム」を知っておく必要がある。
説明する必要すらないが、ランダムは 規則性のないこと。

ランダムを数式的に表現すると以下。

[X_n]_{ n = 0 }^{ infinity } = [x_0, x_1, x_2, ..., x_{ infinity  - 1 }, x_infinity]

とすると

X_i = x_i

(単純)ランダムウォーク

上記の「ランダム」は規則性がない数字が突然出てくるイメージだが、ランダムウォークは以前出たランダムな数字に次のランダムな数字を加えて行く感じ。また、スタート地点(最初)が 0 とは限らないので 定数a を加えてる。
例えば ランダムウォークS2 の場合 a + x0 + x1 となる。

数式で表すと以下。

S_{ 0 } = a, S_{ n } = a + sum from{ i = 0 } to{ n - 1 } X_{ i }

X(ランダム) のインデックスを 0 から始めてしまったので、他のサイトと Σ の範囲が違います。ごめんなさい。

また、ランダムXn の値が {+1, -1} の二択、{+8, -8} の二択など(同じ数字で + か - の二択で確率は不問)の場合は単純ランダムウォークという。
数式で表すと以下。

P( X_n = d )=p, P( X_n = -d ) = q = 1 - p

再度文字で表すと、
Xn が +d(プラス) の確率を p
Xn が -d(マイナス) の確率を q としたとき、q = 1 - p であれば単純ランダムウォーク

ざっくりと説明しましたが以上がランダムウォークと言うものでした。なんとなくイメージ湧きましたかね。

ブラウン運動

ランダムウォークを調べると必ずといって良いほど目にする「ブラウン運動」。何それ?ってなるので、もうちょっと頑張ってみます。

ブラウン運動とは

液体のような溶媒中に浮遊する微粒子が、不規則(ランダム)に運動する現象である。
(ウィキペディア から引用)

ランダムウォークじゃないの?

ブラウン運動の説明を見るとランダムウォークじゃんってなりませんか?私はなります。
似たようなものだから検索して出てくるんでしょうが、厳密に言うと違うようです。

ブラウン運動は物理学で、粒子が不規則に運動する現象の名前で、
ランダムウォークは特に指定なく不規則(でたらめ)に運動すること。

ブラウン運動が狭義で、ランダムウォークが広義って感じ。また、ブラウン運動はx軸が時間、ランダムウォークはx軸が歩数。グラフにすると線(ブラウン運動)か、点(ランダムウォーク)とかイメージしておけば良さそう。

ランダムウォークのx軸(歩数)をめちゃくちゃ小さくすれば、ブラウン運動に近似するよね。
例えば 1歩 で 北に 1m 進んでたとするとグラフ上の x=1, y=1000 に点が一つプロットされる。この 1歩 を 100等分 するとグラフ上の x=0.01, y=10 に点 x=0.02, y=20 に点... x=1.00, y=1000 に点のように 1歩 で 100個の点が打たれるので点→線に近づく感じ。

調べたところ、以上のような違いがあるようでした。

株価のことで言えば、x軸が時間なのでランダムウォークというよりはブラウン運動に近いのかな?

おまけ

株価をシュミレーションする分にはランダムウォークなのかブラウン運動なのか意識する必要はなさそうでした。

《ランダム・ウォークとブラウン運動》
Aritalab:Lecture/NetworkBiology/Diffusion - Metabolomics.JP
上記のページの数式でランダムウォークからブラウン運動を再現しているみたいですが、面倒くさい(理解できない)。「回数が増えれば正規分布になるっしょ」としか思えない。皆は理解できるんでしょうか。私には生産管理のシックスシグマとの違いすら分かりません。

それはさておき、パソコンで発生させる疑似乱数(ランダム)は(正規)分布に従って算出されるので、それを順に加えていけばブラウン運動もどきの出来上がりじゃないですか。

おわりに

間違い等ございましたら指摘していただけると嬉しいです。

何かの参考になれば幸いです。