わたねこコーリング

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

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 等、他の指数計算関数も紹介してみようと思います。

Nexus7 を Factory Image で初期化する

3年程使っている Nexus7 で、Lollipop にアプデした頃からおかしな現象が見られるようになりました。日本語の特定の文字が表示されなかったり線か網がかかったような表示になるというもの。調べたら、ああそうそう、こんな感じ(↓)。

detail.chiebukuro.yahoo.co.jp

「設定」からリセットする方法だと、この不具合は解消できないようで、上記質問への回答にある「Factory Image の焼き直し」ってのを試してみることに。ネットで調べながら進めていったのですが、参考にした記事は若干古い(3〜4年前くらい)ものが多く、今では事情が違う部分もあるようなので、今回の手順を備忘録として書き残しておきます。尚、当方環境は Nexus7 (Nakasi) + Mac OSX 10.9.5 なので、異なる環境の方は適宜読み替えられたし。

手順はおおまかに以下のようになります。

  1. 手持ちのパソコンにて、Google Developers から自分の機種に合った Factory Image ファイルをダウンロードして解凍する。
  2. Factory Image の書き換えには fastboot というコマンドが必要なので、これも入手してパソコンにインストールしておく。
  3. Nexus のブートローダを起動して、パソコンに USB 接続する。
  4. パソコンにて Factory Image に同梱されていたシェルスクリプトを実行して、ブートイメージを書き換える。

まず(1)ですが、 Factory Image は機種毎に異なるものが用意されているので、自分の機種を知る必要があります。Nexus の「設定」で確認すると「Model : ME370T」とあったのですが、これは Nakasi というコードネームに該当するみたい。という訳でここから MD5 チェックサム 32624479e2f24d07fd04a2099a163604 の 5.1.1 イメージをゲット。ダブルクリックして解凍すると、中に flash-all.sh というテキストファイルがあって、これがイメージファイル書き換えのシェルスクリプトとのこと。参考にした記事にはスクリプト最終行にある

fastboot -w update image-nakasi-lmy47v.zip 

から -w を削除しておけってのがありました。どういうことかと調べたら -w はユーザデータとキャッシュファイルを消去するオプションらしく、要は自分のデータ類を残しておきたかったら -w 無しがいいよ、ということでしょう。ご尤もなので従ってみます。

次いで(2)ですが、ネットの参考記事には Android SDKインスコしろってのもあったんですが、やってみると SDK には fastboot が含まれていないようだったので、ここから入手しました。ダウンロードに同梱されている ADB-Install-Mac.sh を下記のようにターミナルから実行します。

$ sh ADB-Install-Mac.sh 
This will install ADB and Fastboot on your computer.
Root Permissions required. Please type your password.
Password: (←ここで管理者パスワードを入力)
Changed directory to /Users/yourname/Downloads/Android
Moving ADB
ADB Moved to /usr/bin/adb
moving Fastboot
Fastboot moved to /usr/bin/fastboot
You may now run Android Debug Bridge and Fastboot commands
Have a nice day.

さて、パソコン側の用意が出来たので(3)を。Nexus の電源とボリュームダウンキーを長押しして再起動し、こんな画面が表示されれば OK。
f:id:mariyudu:20150907134030p:plain

USB ケーブルで Nexus とパソコンと接続したら、いよいよ(4)のブートイメージ書き換え。ターミナルから実行した様子です(↓)。

$ sh flash-all.sh 
...
(bootloader) erasing userdata...
(bootloader) erasing userdata done
(bootloader) erasing cache...
(bootloader) erasing cache done
(bootloader) unlocking...
(bootloader) Bootloader is unlocked now.
OKAY [ 28.433s]
finished. total time: 28.433s
erasing 'boot'...
OKAY [  0.034s]
finished. total time: 0.036s
erasing 'cache'...
OKAY [  0.089s]
finished. total time: 0.089s
erasing 'recovery'...
OKAY [  0.033s]
finished. total time: 0.033s
erasing 'system'...
OKAY [  0.703s]
finished. total time: 0.703s
erasing 'userdata'...
OKAY [  4.964s]
finished. total time: 4.965s
sending 'bootloader' (2100 KB)...
OKAY [  0.303s]
writing 'bootloader'...
OKAY [  1.220s]
finished. total time: 1.523s
rebooting into bootloader...
OKAY [  0.019s]
finished. total time: 0.020s
archive does not contain 'boot.sig'
archive does not contain 'recovery.sig'
archive does not contain 'system.sig'
--------------------------------------------
Bootloader Version...: 4.23
Baseband Version.....: N/A
Serial Number........: (註:ひみつですw)
--------------------------------------------
checking product...
OKAY [  0.040s]
checking version-bootloader...
OKAY [  0.027s]
sending 'boot' (5184 KB)...
OKAY [  0.711s]
writing 'boot'...
OKAY [  0.222s]
sending 'recovery' (5738 KB)...
OKAY [  0.773s]
writing 'recovery'...
OKAY [  0.237s]
sending 'system' (649455 KB)...
OKAY [ 85.181s]
writing 'system'...
OKAY [ 36.497s]
rebooting...

finished. total time: 123.835s

実行に2分くらいかかりました。これが終わると Nexus が再起動を2回ほど繰り返して(2回目の起動時間が長かった…)、めでたく Lollipop が起動されました。不具合もちゃんと解消されたようです、ふう。

しかしこの作業、一般ユーザにはちょっとハードルが高いですよねぇ。GUI 上で実行可能な初期化ツールとか出してくれないのかしら > Google さん

D3.js でローソク足チャート描くなら TechanJS がイイ!(かもしんない)

最近、データ分析の真似事をしたくなって、どうせやるなら実益も目指せる株取引を対象に、とごにょごにょ始めたりしています。そこで必要になるのが、データの「見える化」。ローソク足チャートをベースに、諸処の分析結果を作画して「ほほー」等と言ってみたい訳ですが、まずはツール選びに一苦労。jqPlot の様に高レベルに実装されたプロダクトは使うのも簡単なのですが、そのぶんちょっとしたカスタマイズにも苦労するようです。

他の手段を調べてみると、データ分析のビジュアライズには D3.js がイイという話。けど、D3.js ってのは「グラフを簡単に描けるライブラリ」というよりはデータ分析の視覚化フレームワーク的な、非常に広範囲な利用を想定した「低レベル」な実装なんですね。なので、グラフひとつ描くにもそれなりの学習が要るみたい…「努力すんのは嫌いだしめんどっちーし楽して身につく方法はないもんかな」と調べていたら、TechanJS という D3.js ベースの財務グラフ作画ライブラリを見つけました。

開発元提供のサンプルを見て頂ければ分かるように、ローソク足チャートは序の口で、MACD・RSI・トレンド線・一目均衡表など、テクニカル分析を齧ると出てくる様々な手法の作図が用意されているようです。しかも、このライブラリは作図だけでなくデータ分析の機能も併せ持っているらしい! とっても凄そうなのですが、先ずはシンプルにローソク足チャートに移動平均線を重ね描きするという初歩の初歩にチャレンジしてみました。で、出来た図がこんな感じ(↓)。

f:id:mariyudu:20150830212210p:plain

直近100日の日経平均日足と、5日・25日・75日の移動平均線です。TechanJS はドキュメントが殆ど無いので、サンプルのコードを参考に必要に応じて削ったり足したりしながらのプログラミングでした。作画には D3.js 流儀のステップが必要で関数一発という訳には行きませんが、データをポンと渡すだけで軸の目盛を実用的に調整してくれるところが有り難いです。プログラムは JSFiddle に上げておきましたよ、と(↓)。

jsfiddle.net

なにぶん、D3.js そのものに未だ不慣れなので自由自在に使えるようになるまでは長い道のりになりそうですが、一攫千金をニンジンにがんばってみようかと。

MuseScore ver.2 のギタータブ譜機能を試してみた

全国の撥弦楽器愛好者に朗報です。オープンソース&無料の楽譜作成アプリ、MuseScore (ミューズスコア)のバージョン2が先ごろの3月にリリースされて、かねてから予告されていた待望のタブ譜機能が正式に実装されました! ギターやウクレレ、その他を多少嗜む身としては本当にグッドニュースです。音楽的な表現に慣れ親しむという意味で五線譜の楽譜を蔑ろにすべきではないと思いつつも、アコースティック・ギターなんかは変則的なチューニングを用いることが多く、どうしてもタブ譜が欲しい時があるのですよね…

という訳で、早速試してみることにしました。お題は、戦前ブルーズの巨人、ブラインド・ブレイクの「ポリス・ドッグ・ブルース」のイントロを、五線譜とタブの二段構成で作成してみるというものです。

スコア書類の作成

先ず五線譜とタブの二段形式のスコアを新規作成します。メニューから[ファイル]>[新規作成…]を選択して、表示されたダイアログにて曲名や作曲者名等を適宜入力して、ボタン[次へ]をクリック(↓)。
f:id:mariyudu:20150601202704p:plain

テンプレートの一覧から「Solo」というグループにある「Guitar + Tablature」をクリックして選択(↓)。
f:id:mariyudu:20150601202757p:plain

「ポリス・ドッグ・ブルース」はキーが D (ニ長調)なので、調号からシャープふたつを選択して、ボタン[次へ]をクリック(↓)。
f:id:mariyudu:20150601202836p:plain

拍子・小節数はデフォルトのままで、ボタン[完了]をクリック(↓)。
f:id:mariyudu:20150601202847p:plain

はい、五線譜とタブの二段スコアのひな形ができました(↓)。
f:id:mariyudu:20150601202855p:plain

チューニングの変更

この曲のギターはレギュラーチューニングではなくオープン D という、6弦から順に DADF#AD に合わせる変則チューニングなので、その設定が必要になります。タブ譜の上でマウスを右クリックして、コンテクストメニューから[譜表のプロパティ]を選択します(↓)。
f:id:mariyudu:20150601202910p:plain

このダイアログの左下あたりにあるボタン[文字列データの編集…]をクリックすると、ギターの調弦が表示されたサブダイアログが表示されます(※ヘンな表記ですが多分「弦(Strings)」が「文字列」に誤訳されているのでしょう)。この値(6弦なら E2)をダブルクリック → 表示された音符選択ダイアログで変更する値(6弦なら D2)をダブルクリック、という手順で各弦を必要に応じて調弦を変更します(↓)。
f:id:mariyudu:20150601202924p:plain

はい、この通り DADF#AD へのチューニング設定が完了(↓)。
f:id:mariyudu:20150601203027p:plain

あと、チューニングに合わせて「使用可能な音高の範囲」も設定しておいたほうが良さげ(音符入力の際にこの範囲を逸脱すると赤くエラー表示されてしまうので)。5フレットでのハーモニクス等考えると、D2 〜 D6 とかにしておけば良いかと(↓)。
f:id:mariyudu:20150601203037p:plain

音符の入力

あとは音符を入力していくだけです。タブ譜の先頭をクリックして選択状態にしておいて、メニューバーから音符入力ボタンをクリックするか、n キーを押して、音符入力モードに入ります(↓)。
f:id:mariyudu:20150601203049p:plain

音符(というかタブ譜なのでポジション番号)の入力位置が青く表示されますので、音符の種類(4分,8分etc)をメニューバーから選択してポジション番号をキー入力します。カーソルキーの←・→で左右位置が、↑・↓で弦の移動ができるので、これらの繰り返しでどんどん音符を入力していきましょー(↓)。
f:id:mariyudu:20150601203147p:plain

そんな感じで黙々と入力していったら、こんな感じでイントロ部分が出来上がりました(↓)。
f:id:mariyudu:20150601203505p:plain

…と、必要最小限ですがタブ譜の作成手順でした。説明した以外でも、繰り返し記号やタイ・スラー等はどうやって入力するの? 的なギモンがあると思いますが、その辺は通常の楽譜機能に属する事柄なので、純正のハンドブックから学んで頂ければと。自分でも MuseScore は初心者レベルなので、これからどんどん使い倒して、獲得したノウハウは共有して行こうと思ってます。そんな訳で、今日はここまで!

Redis で FIFO バッファを作って PHP から使う

昨今じゃ当たり前になった NoSQL ってやつですが、自分はどうも使う機会が無かったというか、フツーに RDB 使ったほうが目的に叶うケースが多かったので memcached でさえ殆ど手を触れずに今日まで来ました。それがやっと先ごろ、NoSQL なシチュエーションが発生!という訳で、人生初 NoSQL の作業メモです。

要件は、各所から発生するデータをそのまま RDB に書き込むと諸事情で色々と嬉しくないので、いったんバッファに溜めておいて専用のデータストア用プログラム経由で逐次 RDB に格納するというものです。古いものから順に読み出す必要があるので、所謂 FIFO (First In First Out) バッファですな。memcached は万一のデータ消失が怖いので、最近評判が良いらしい Redis を採用。

まずは環境づくりから。当方の AWS EC2 な LAMP サーバにて、Redis を PHP から使えるようにします。Redis 関係は EPEL リポジトリにしか無いようなので、それを指定して yumインスコします。

% sudo yum --enablerepo=epel -y install redis

Redis サーバを起動して、ブート時の設定も忘れずに。

% sudo service redis start
% sudo chkconfig redis on

で、動作確認…

$ redis-cli
redis 127.0.0.1:6379> info
redis_version:2.4.10
(省略)
redis 127.0.0.1:6379> exit

よし、OK。

PHP の Redis 用モジュールのほうも同様にインスコ

% sudo yum --enablerepo=epel -y install php-pecl-redis
% sudo service httpd reload

以上で環境が整ったので、プログラムを書きます。Redis は色々なデータ型が用意されていますが、FIFO バッファは Lists 型を使って実現できるとここにあったので、これに倣って LPUSH で書き込み、RPOP で読み出すことにします。RDB 用のデータを Redis に書き込む側はこんな感じ。

$data = array(':name' => $name, ':email' => $email, ':created' => date('Y-m-d H:i:s')); //テーブル列名 => 値、な1レコードぶんのデータ
$redis = new Redis();
$redis->connect('localhost');
$redis->lPush('mykey', json_encode($data)); //JSON に変換して Redis に保存

Redis → RDB の処理側はこんな感じ。

$redis = new Redis();
$redis->connect('localhost');
$pdo = new PDO('mysql:host=localhost;dbname=my_db', 'login_name', 'login_pw');
$stmt = $pdo->prepare('INSERT INTO my_table (name, email, created) VALUES (:name, :email, :created)');
while ($data = $redis->rPop('mykey')) { //有るだけ読み出しては RDB に追加
	$data = json_decode($data, true);
	$stmt->execute($data);
}

とまぁ、こんな具合です。実にシンプルな利用ケースなので一寸物足りない気もw 他のデータ型も使ってみたいなー。

Thunderbird アドレス帳と GMail 連絡リストを同期させて、迷惑メール誤振分けを是正する

SNS やら諸サービスの台頭で連絡手段も多彩になりましたが、仕事ではやっぱり未だ E メールがメイン。自分の場合、GMail で用途別にアカウントを作って、それらを Thunderbird に集約して使ってます。で、困るのが GMail 側で正常メールが迷惑メールに誤振分けされる件。これを抑止するにはそのメールの差出人アドレスを GMail 側で連絡帳に追加しておけば良いのですが、その度にウェブブラウザで設定するのが面倒でしてねぇ。何とかならんか? と調べたら、Thunderbird アドレス帳と Google 連絡先を同期させる Google Contacts という Thunderbird アドオンがあるようなので、それを試してみました。以下、手順。

配布元から Google Contacts アドオンをダウンロードして、書いてある手順(↓)に従ってインストール。Ver.24 までと表記されてますが、現行バージョン(31.5.0)でも問題なく動作するようです。
f:id:mariyudu:20150321143558p:plain

インストール後に、Google 連絡先のインポート可否を聞いてくるのでオケーイと言ってやります(↓)。
f:id:mariyudu:20150321144136p:plain

Thunderbird アドレス帳ウィンドウを表示させると、おお、Google 連絡先が加わってる(↓)。
f:id:mariyudu:20150321144621p:plain

さて、誤振分けの対応はここから。誤振分けされてしまったメールの差出人を右クリックして、そのアドレスを Thunderbird アドレス帳に追加します。
f:id:mariyudu:20150321151103p:plain

んで、Thunderbird アドレス帳ウィンドウを開いて、追加されたメアドを Google 連絡帳にドラッグ&ドロップしてコピーします(↓ モザイクだらけでわかりづらいですがw)。f:id:mariyudu:20150321151822p:plain

以上です。メアドを直接 Google 連絡先のほうに追加できればいちばんなんですが、それでもいちいちブラウザで GMail を開くのに比べたらだいぶ楽になりました。

続・MySQL データベースからテーブル定義書を生成する

以前書いた「MySQL データベースからテーブル定義書を生成する」が、地味にアクセスがあるようです(当社比)。ナウでヤングで意識高いギークさんには見向きもされないような類の古臭いイシューだと思ってましたが、平成27年のニッポンでは現在進行形の悩ましい問題だったりする訳ですかね?

とまぁそんな訳で続編というか改訂版というか。前回記事では、ダンプした DDLSQL::Translator という CPAN モジュールを使った perl スクリプトXML 化した上で、それを XSLT で HTML 変換するという、ちょっとややこしい手順でした。その後、MySQL のダンプコマンド mysqldump には --xml というオプションがあって、こいつを使えば XML 形式の DDL がカンタンに入手できることが判明!(って今頃ヲイw つまり、

mysqldump --no-data --xml foodb > foodb.xml

XMLDDL を生成しておいて、

xsltproc -o foodb-document.html style.xsl foodb.xml

で HTML 変換という、たった2手順でコトが済んでしまう訳です(MySQL 限定)。知らぬこととはいえお恥ずかしい。

さて、冒頭で書いたように、このイシューには割と需要があるようにも見えるので XLST 処理を行える環境が手元に無い方を想定して、上記の xsltproc 処理をウェブ上で行えるサービスのようなモノを作ってみました。使い方はカンタン。フォームにて、左テキストボックスに DDLXML を、右テキストボックスにスタイルの XSL をコピペして変換ボタンをポチっとするだけです。


なにせ1時間程度でちゃちゃっと作ったモノなので、XML のバリデーション等は一切行っていませんが(文法に誤りがあると「変換できませんですた」って言うだけw)、マジで需要があるようだったらご希望を取り入れながら充実させて行こうかと。