私と私の猫の他は誰でも隠し事を持っている

野良プログラマ発、日々のアウトプット

PHP Trader 関数を使ってみる - 移動平均の巻

明日からの週明け市場は日経平均1万7千円台回復か? 等と今日の産経ニュースに載ってましたが、はてさてどうなりますか。という訳でご無沙汰しております、細々とシストレなぞもすなる野良プログラマ Mariyudu です。

プログラマさんがシストレする時にどんな言語が便利なのかは知りませんが、個人的には使い慣れた PHP を使ってます。んで、PHP には株式や FX 等のテクニカル分析用の Technical Analysis for Traders という数学関数群が人知れず用意されてまして、これはどうやら TA-Lib というライブラリをラップしたもののようです。残念なことに、php.net のマニュアルはあまり親切とは言えないし、ユーザも少ないのか情報に乏しいようなので、当方が試行錯誤して使ってみた経過なぞをアウトプットしてみます。

まずインストールから。Trader 関数は PECL モジュール化されてるので、sudo pecl install trader でインスコできるでしょう(たぶん)。CentOS ユーザには Remi リポジトリに用意されているので、sudo yum --enablerepo=remi install php-pecl-trader でも OK(当方はこちら)。

今回は手始めに移動平均を算出する関数、trader_ma を使ってみます。コーリングシーケンスは

trader_ma(<株価が格納された1次元の配列>, <集計日数>, <移動平均の種類>)

となります。第三パラメータには TRADER_MA_TYPE_SMA (単純移動平均)、TRADER_MA_TYPE_EMA (指数平滑移動平均)、TRADER_MA_TYPE_WMA (加重移動平均線)等の多種が用意されています。正直、単純移動平均なら自分で書いた方が早いくらいですが、EMA や WMA はそれなりの計算手順を踏むので一発で計算できるこの関数は便利かも。返り値は、第一パラメータの配列に応じるかたちで移動平均値が格納された配列です。例えば5日移動平均だと、最低5日ぶんの直近株価データが必要なので、返り値配列のインデックス[0]〜[3]には何もセットされず、[4]から計算結果がセットされている、という感じ。

以下、サンプルプログラムです。各種株価データを提供されている、k-db.com さんの所から今年の日経平均日足データを入手して、それを元に移動平均を算出して表示するというシナリオです。

<?php
// 入手した CSV ファイルから株価データを読み込んで、配列に格納
$data = file('indices_I101_1d_2016.csv', FILE_IGNORE_NEW_LINES);
//見出し行を省く
unset($data[0]);
// 各行のカンマ区切りを配列に分割
$data = array_map(function($item){ return explode(',', $item); }, $data);
// 日付昇順でソート
usort($data, function($a, $b){ return ($a[0] < $b[0]) ? -1 : 1; });
// trader_ma の入力用に、終値だけ収集(要実数変換)
$closePrices = array_map(function($item){ return +$item[4]; }, $data);
// 5日・25日・75日の指数平滑移動平均を計算
$emas = [5 => [], 25 => [], 75 => []];
foreach ($emas as $d => &$ema) {
	$ema = trader_ma($closePrices, $d, TRADER_MA_TYPE_EMA);
}
// 出力
echo "日付,株価,5日EMA,25日EMA,75日EMA\n";
foreach ($data as $n => $data) {
	echo implode(",", [
		$data[0],
		$closePrices[$n],
		@$emas[5][$n],
		@$emas[25][$n],
		@$emas[75][$n],
	]) . "\n";
}

これを実行した結果はこんな感じ↓。

日付,株価,5日EMA,25日EMA,75日EMA
2016-01-04,18450.98,,,
2016-01-05,18374,,,
2016-01-06,18191.32,,,
2016-01-07,17767.34,,,
2016-01-08,17697.96,18096.32,,
2016-01-12,17218.96,17803.867,,
(中略)
2016-08-29,16737.49,16579.888,16517.979,16433.468
2016-08-30,16725.36,16628.379,16533.931,16441.15
2016-08-31,16887.4,16714.719,16561.121,16452.893
2016-09-01,16926.84,16785.426,16589.253,16465.365
2016-09-02,16925.68,16832.177,16615.132,16477.479

実はこれ、巷の株情報サイトに載っている値とはちょっと違っています。指数平滑移動平均は 𝑓(前日の計算結果, 当日株価) という計算式なので、理論上は過去全ての株価データを与えてやらないと正しい計算値にならないことになります。当方であれこれした所では10年分くらいのデータがあればそれ程大きな差異は出ないようですが。

ということで、また折を見てボリンジャーバンドMACD 等、他の指数計算関数も紹介してみようと思います。