2016年4月10日日曜日

Cygwin mysqld って 大データ入る?

cygwin で
cat /cygdrive/z/db_finance_bak.sql|mysql -u root -p db_finance2
Enter password:

実行してRASPBERRY PI から DUMPした
DBをインポートしてみたが、12時間以上たっても終わってない。13GByte 位あるSQL文
株価データベースはどうしてもこのような馬鹿みたいなサイズになる。

cygwin は64Bit版だと思う。

CPU占有率が25%のまま終わる気配が無い。
更新対象と思われる/var/lib/mysqlの中にあるタイムスタンプすら更新されていないようで、
生きてる可能性が極めて低い。
/usr/share/mysql/mysql.server stop
すら効かない。

思えば過去にも同じ体験をしたことがある気がする(ずいぶん昔の気がするが)

でもネットを探してもCygwinで大規模なサイズのデータベースが構築できないなんてみあたらないけど、現実問題使えた記憶がないなあ。誰か使えてる人っていますか?

困ったなあ。
MysqlWindowsネイティブ版ってあったっけ?
って思って探してみる事にした。

こっちは固まりませんように。
http://dev.mysql.com/downloads/installer/

2016年4月9日土曜日

cygwin lighttpd メモ linux-sysepoll 無いとか、sendfile わからんとかのメモ

lighttpd の設定で躓いたのでメモ lighttpd.confを編集する。

1個目(起)
$ /usr/sbin/lighttpd  -f /etc/lighttpd/lighttpd.conf
2016-04-09 11:20:11: (/usr/src/ports/lighttpd/lighttpd-1.4.37-1.i686/src/lighttpd-1.4.37/src/
configfile.c.1355) the selected event-handler in unknown or not supported: linux-sysepoll
2016-04-09 11:20:11: (/usr/src/ports/lighttpd/lighttpd-1.4.37-1.i686/src/lighttpd-1.4.37/src/
server.c.649) setting default values failed

#server.event-handler = "linux-sysepoll"
server.event-handler = "poll"

linux-sysepollが知らんか、サポートされてないといってるし選択できそうなのでpoll に変更した。

2個目
$ /usr/sbin/lighttpd  -f /etc/lighttpd/lighttpd.conf
2016-04-09 11:23:46: (/usr/src/ports/lighttpd/lighttpd-1.4.37-1.i686/src/
lighttpd-1.4.37/src/network.c.959) server.network-backend has a unknown value: sendfile



server.network-backend = "sendfile"
↓変更
#server.network-backend = "sendfile"

に変更。何かよくわからないが、コメントアウトしてみた。(いいかげんすぎる)


3個目(転)
$ /usr/sbin/lighttpd  -f /etc/lighttpd/lighttpd.conf
2016-04-09 11:25:20: (/usr/src/ports/lighttpd/lighttpd-1.4.37-1.i686/src/lighttpd-1.4.37/src/server.c.927) can't have more connections than fds/2:  1024 256

#server.max-connections = 1024
server.max-connections = 128
これでもかというくらい減らしてやった。

4個目(結)
$ /usr/sbin/lighttpd  -f /etc/lighttpd/lighttpd.conf
2016-04-09 11:26:20: (/usr/src/ports/lighttpd/lighttpd-1.4.37-1.i686/src/lighttpd-1.4.37/src/network.c.410) can't bind to port: localhost 80 Address already in use
あれ?あれれ。

実はApache2がすでに設定してあった事が判明。
やれやれ。完全に無駄な努力であった。

server.port = 8080

でhttp://localhost:8080
でアクセスできましたとさ。

でもapache2 入ってないかと思ってlighttpd 選んでみたのに

動いてるなら別に要らないよね。


2016年4月7日木曜日

バックテストに向けてようやくデータ側の準備は整いつつある

今まで株のシステムはエクセルでずっと考えてきた。
エクセルがシステムトレードに全く使えないという人は居るとは思うけど、
そんなことは全然なくて期待値としてはどうなんだ?とか、
こういうシグナルで利益が取れる株は~な傾向がありそうだなあとか、そういう事はエクセルでも判るようだったし、ローソク足も違った見方ができるようになった。

エクセルは間違いなく株取引で勝つうえでプラスのツールだと思う。

いくらシステムトレード用ソフトが優れているとはいえ、ピボットで即効で結果が見える
エクセルは思い付きを実現する最速のツールとしてはシステムトレードソフトに負けているとは
思えない。
ただ、大量データ操作に関しては、やっぱり力不足な気がしている。
この点に関してはシステムトレード用ソフトには全くかなわない。
同じ事をやろうとすると大規模なマクロを組まなければならない。
でもエクセルはちょっとモッサリしていて大量のデータ操作にはちょっと使いたくないなあという気がする。実際アクティブな銘柄はたぶん3000ぐらいあって、それをエクセルマクロで処理するなんて
悪夢だ。

それで、Perlのフィルタに食わす程度の全銘柄データを出したいなという野望が出てきてだんだん実現に近づいて来た。


ああ、面倒だった。

面倒だった点

まずデータをどこから買うかという事。Yahoo と 無尽蔵等から集める事も可能だけど、寄せ集めのデータを扱うのは案外たいへんなのでData-getを使う事にした。面倒なので、ここの割り切りが必要だ。方法が確立するまではお金払ってもいいかな。

テキストファイルからデータベースへの変換が面倒だった。

分析に必要のないデータの消去が面倒だった。例えば、大証のデータとか。

修正の必要な項目の修正が面倒だった。特に分割の修正と4本値が0の場合の処理とか、
前日のデータから引っ張ってこないといけない。


今の状況と今後

とりあえず、修正後の四本値はsql を投げるPHPでLAN内のRPIWeb Server から取得できるようになった。(期間を指定することも可能)
ただ、SQLは時間がかかるので、バックテストをする前の夜中は、CSVファイルを出力するスクリプトを走らせておいたほうが良さそうだ。

今後は、テクニカル分析の数値とか昨日の上昇下落%とかをブラウスするものを作りたい。できれば、システムトレードの期待値とかも。

うーんようやく道具の一つが持てた。
でもまだまだパンツしかはいてない。

頑張ろう。

2016年4月6日水曜日

RPI家庭内my株価データベース分割修正についてのメモ

data-get.comより株価データを買って、家庭内サーバに株価データベースを構築して遊んでいる。
最低限、4本値と、会社分割情報だけ入れられたらいいかなあと思っている。

mysql> describe tbl_dg_devide;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| s     | char(4) | NO   | PRI |         |       |
| d     | char(8) | NO   | PRI |         |       |
| f     | float   | YES  |     | NULL    |       |
| t     | float   | YES  |     | NULL    |       |
| mul   | float   | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
5 rows in set (0.01 sec)

分割情報を保持するテーブルは↑のような感じ s はセキュリティコード(証券コード)
dは日付文字列にした。データタイム型にするとload data する時に面倒なのでやってない。
f は分割前~に当たり t ~個の株式を割り当てるみたいな。
f と t はあまり必要ない。

mul が重要で、分割修正乗数というべきもの。

とりあえず、Data get の devide.csv はそのままload data できる構造にした。

ところで、data-getの株価は分割情報は別テーブルだ。
これはこれで便利なのだけど。
普通バックテストや過去データの検証に必要なのは分割を調整した後の4本値だ。
だから

ふつうの4本値

分割情報から

⇒ 分割を調整した後の4本値を記録した時系列データを

作らないといけない。

で、やり方にはいろいろあるが、SQLでできるのかどうかを考えてみる。
12.19.1 GROUP BY (集約) 関数
をみてうーんと考えてみたけどもどうにもできそうにない。

できない原因は集約関数にEXCELでいうPRODUCT的な動きをする関数や
Perlでいうmap 関数のようなものが無いからだと思う。
また集約関数を自作できそうな情報もなかったので、これはたぶん無理か難しいんだろうな。

でも、SQLで修正乗数のPRODUCTを返す数式なら返す事ができるなあと気が付いた。

まずソフトバンクの分割を調べてみる
mysql> select * from tbl_dg_devide where s="9984";
+------+----------+------+------+---------+
| s    | d        | f    | t    | mul     |
+------+----------+------+------+---------+
| 9984 | 19960326 |    1 |  1.4 | 0.71429 |
| 9984 | 19960925 |    1 |  1.4 | 0.71429 |
| 9984 | 19970326 |    1 |  1.3 | 0.76923 |
| 9984 | 20000425 |    1 |    3 | 0.33333 |
| 9984 | 20051228 |    1 |    3 | 0.33333 |
+------+----------+------+------+---------+
5 rows in set (0.01 sec)
ソフトバンクの1996年3月2X日の終値を表示
mysql> select d, s,c from tbl_dg_ohlc where s="9984" and d LIKE "1996032%";
+----------+------+-------+
| d        | s    | c     |
+----------+------+-------+
| 19960321 | 9984 | 26800 |
| 19960322 | 9984 | 26000 |
| 19960325 | 9984 | 26300 |
| 19960326 | 9984 | 19200 |
| 19960327 | 9984 | 19800 |
| 19960328 | 9984 | 20200 |
| 19960329 | 9984 | 21800 |
+----------+------+-------+
7 rows in set (0.01 sec)

ソフトバンクの1996年3月2X日の終値を表示↑の二つの表から修正値の数式を出力させてみる。
mysql> select a.s,tbl_dg_ohlc.d,GROUP_CONCAT(a.mul separator '*') 
from (select s,d,mul from tbl_dg_devide where s="9984" ) as a, 
tbl_dg_ohlc 
where a.s = tbl_dg_ohlc.s and a.d > tbl_dg_ohlc.d 
and tbl_dg_ohlc.d LIKE "1997032%" group by tbl_dg_ohlc.s,tbl_dg_ohlc.d ;
+------+----------+-----------------------------------+
| s    | d        | GROUP_CONCAT(a.mul separator '*') |
+------+----------+-----------------------------------+
| 9984 | 19970321 | 0.33333*0.76923*0.33333           |
| 9984 | 19970324 | 0.33333*0.33333*0.76923           |
| 9984 | 19970325 | 0.33333*0.33333*0.76923           |
| 9984 | 19970326 | 0.33333*0.33333                   |
| 9984 | 19970327 | 0.33333*0.33333                   |
| 9984 | 19970328 | 0.33333*0.33333                   |
+------+----------+-----------------------------------+
6 rows in set (0.44 sec)
どうだろう。なぜか、CONCATの順番が入れ替わったりしているが概ね機能してそうな気がする。

おしいところまではできるのだが、あと一押し eval()関数が欲しいなあ。

あ、これだと分割情報の適用されないところが出てくるからRIGHT JOIN した方がいいのか。

select b.s,b.d, IFNULL(GROUP_CONCAT(a.mul separator '*'),1) 
from 
  (select s,d,mul from tbl_dg_devide where s="9984" ) as a
     right join
         (select * from tbl_dg_ohlc where s="9984") as b
     on a.s = b.s and a.d > b.d  group by b.s,b.d ;

2016年4月4日月曜日

家庭内my株価データベースでマーケットの重複を取り除くSQL文のメモ

家庭内my株価データーベース tmp2というテーブルに
s証券コード
d日付
mマーケット
o,h,l,c 始値、高値、低値、終値
v 出来高

という形式で保存されている。
複合プライマリキーとして(s,d,m)を設定。

で、同じ証券コードの同じ日付に2つのマーケットがあると
エクセルなんかで処理するのが面倒になる。

例えば大阪証券取引所のデータなどが邪魔になる。
別にEXCELやPerlでやるのは難しくないのだが、
出来ればSELECT文で取り除きたいなあ。
要らない条件は、まあ、出来高のでかいヤツがあれば、
それでいいマーケットと考えてよかろー。

(1)同日の同証券コードの最大の出来高を取り出す。
select s,d,max(v) as v from tmp2 group by s,d;
単体だと上みたいなSQL

(2)同日の同証券コードの最大の出来高のマーケットは複数ある可能性がある。この場合、個人で株シミュレーション走らせるだけならどちらを選んでもいいだろうが、どちらかを選ばねばならない。
同日の同証券コードの最大の出来高のマーケットのうち最大のマーケットを選ぶ。
select a.s as s ,a.d as d,max(a.m) as m from tmp2 as a, (1) as b where a.v = b.v group by a.s, a.d

(3)同日の同証券コードの(2)で選んだマーケットの4本値をselectする。
select a.s, a.d, a.m, a.o, a.h, a.l, a.c, a.v from tmp2 as a, (2) as b where a.s = b.s and a.d=b.d and a.m=b.m;

select 
    a.s, a.d, a.m, b.o, b.h, b.l, b.c, b.v
from
    (select b.s as s ,b.d as d,max(b.m) as m 
     from  (select s,d,max(v) as v 
            from tmp2 where s="1332" group by s,d ) as a,
           tmp2 as b 
     where a.s = b.s and a.d=b.d and a.v = b.v
     group by s, d
    ) as a,
    tmp2 as b
where a.s = b.s and a.d=b.d and a.m=b.m;

ぬー。 パワー過ぎ。。。。。。頭が。。。。。。。。。。。。
艦これヤルっす。

where s= "1332"のところを変えて使うみたいな。

こんなんでいいのかな…。
よくわかんないのだが、stock_code を変えるだけで実行できるように
ストアドプロシージャ登録しておいた。
便利だワイ

分割を修正するSQLも考えないとなあ。


2016年4月3日日曜日

巨大になってしまう家庭内株価データベースを少し最適化する

テキトーに株価のデータをdata-get から買ってmysql にインポートしたはいいけど、
ギガバイトオーダーのデータ量になってしまい1個の銘柄を検索するのに8分かかるクレイジーなテーブルになってしまった。8分も検索にかかるとやる気がなくなってしまい、艦これをやってしまう。

こ れ は い か ん 。

恐ろしい無計画。

なんで遅いかよくわからないのだが、myisamchk --sort-index --sort-record を使うと速くなるかもっていう気がした。 たぶんあっているだろうが、 テーブルのエンジンがInnodb だったので、できない。 

じゃあ、innodb でクエリを高速化する方法が無いかというと、 無いわけがない。
もしなかったら世界中で mysql が普及するわけがない。

絶対あるはずだがよくわからないなあと思って help alter table とか打ってみると んむむパーティションというモノがあるではないか。

https://dev.mysql.com/doc/refman/5.6/ja/partitioning-limitations.html まずは、今腐るほど遅いテーブルの構造を引き継いだテーブルで実験してみることに。


create table tmp like tbl_dg_ohlc;

要は、日付順に並んでるデータをコード毎にテーブルを分ければアクセスが速くなる。
山積みの書類を積んでおくと、関係のあるヤツどれって言われると(目録はあるにせよ)取りにいかないといけないが。
引き出しにあらかじめ分けて入れておけばサッと取り出せるおばあちゃんの知恵みたいな。

alter table tmp PARTITION BY RANGE COLUMNS(s) (
PARTITION p1500 VALUES LESS THAN('1500'),
PARTITION p2000 VALUES LESS THAN('2000'),
PARTITION p2500 VALUES LESS THAN('2500'),
PARTITION p3000 VALUES LESS THAN('3000'),
PARTITION p3500 VALUES LESS THAN('3500'),
PARTITION p4000 VALUES LESS THAN('4000'),
PARTITION p4500 VALUES LESS THAN('4500'),
PARTITION p5000 VALUES LESS THAN('5000'),
PARTITION p5500 VALUES LESS THAN('5500'),
PARTITION p6000 VALUES LESS THAN('6000'),
PARTITION p6500 VALUES LESS THAN('6500'),
PARTITION p7000 VALUES LESS THAN('7000'),
PARTITION p7500 VALUES LESS THAN('7500'),
PARTITION p8000 VALUES LESS THAN('8000'),
PARTITION p8500 VALUES LESS THAN('8500'),
PARTITION p9000 VALUES LESS THAN('9000'),
PARTITION p9500 VALUES LESS THAN('9500'),
PARTITION p9999 VALUES LESS THAN('9999'),
PARTITION pMAX VALUES LESS THAN(MAXVALUE)
);

むーん。パワー。

insert into tmp select * from tbl_dg_ohlc;

今なら言える。
データ一日1万個アホは万里を超える。

待ち。

ババーーーン。
風呂入ってこよ
select * from tmp where s="9984";
...
| 20160331 | 9984 | t1 |   5454 |   5466 |   5362 |   5366 |   6804900 |
+----------+------+----+--------+--------+--------+--------+-----------+
5332 rows in set (50.46 sec)

もとは8分以上かかっていたが、50秒に短縮され 8倍以上は速くなった。 けどやっぱり十分遅いっちゃあ遅いな、RPIなんで仕方ない部分はあるけどパーティションギチギチに切って 日付とセキュリティIDを入れ替えたり、セキュリティIDやマーケットIDをもっと小さなサイズの数値にしたりという事は可能かもしれない。 でもあんまり複雑にすると面倒なのでどうしたもんか

仮にこれだけしか実力を発揮できないとすると、仮に銘柄が3000くらいあったとして日々それを調査するのにSelect文3000個発行すると、3000分時間がかかって全然実用にならない。パーティションではたぶんこれ以上の高速化はたいして効果ないように思う。


根本的に何か間違っているとしか思えない。

で、いろいろやってみましたよ


alter table tmp modify d char(8) after m;


⇒効果なし。

alter table tmp drop primary key;
alter table tmp add primary key(s,d,m);
select * from tmp where s="9984"
略)
| 9984 | t1 | 20160331 |   5454 |   5466 |   5362 |   5366 |   6804900 |
+------+----+----------+--------+--------+--------+--------+-----------+
5332 rows in set (0.39 sec)

正解はこれだったか。 Raspberry PI の株価サーバは十分実用に耐えると思います。


結論 複合プライマリキーの順番には要注意!!!!

RaspberryPIに構築した my 株価データベースのレスポンスが超絶遅い件

昨日頑張って、mysqlimport した株価データ。 朝になったら終わってたみたいだ、が。

select * from tbl_dg_ohlc where s="9984";

うーんレスポンスがない。動いてんのか心配になり始める。と。

| 20160331 | 9984 | t1 |   5454 |   5466 |   5362 |   5366 |   6804900 |
+----------+------+----+--------+--------+--------+--------+-----------+
5332 rows in set (8 min 16.92 sec)

mysql>


8分って… PRIMARYKEY で INDEXが効いているのではないのか。 切なくなるほど遅い。
where like "9984"もほぼスピードは同じ。

RaspberryPIだけの問題ではなさそう。

さすがにギガ越えでノープランDBはダメか。

データベース屋じゃないのでどこをどうすれば高速化するのかよくわからないが。

さすがに30秒くらいで返ってこないときつい。

やりたい事はとにかくセキュリティコードだけの検索は高速化したい。

他はボチボチでいい。


2016年4月2日土曜日

株価データベースをload data local infile しようとして失敗した

データゲットのデータをMYSQL にインポートする時のメモ

data-get 10年 株価 cdrom も買った5775円だったが4月からは値上がりの様子。
しかし、データゲットのデータはエクセルだけじゃちょっと使いにくい形式。
MySQLとかDBを活用した方がいいっぽい。

load data local infile を使ってやるつもりだった。 ちなみにCD-ROMの構成は
./1990
./1990/199001.zip
./1990/199002.zip
./1990/199003.zip
./1990/199004.zip
./1990/199005.zip
./1990/199006.zip
./1990/199007.zip
./1990/199008.zip
./1990/199009.zip
./1990/199010.zip
./1990/199011.zip
./1990/199012.zip
./1991
./1991/199101.zip
./1991/199102.zip
./1991/199103.zip…

みたいになってて各zip には月ごとの4本値データが全部入ってる感じの
単一のテキストが入っている。

面倒なので、寝てる間にどうにかする作戦。

cd 株価データ/
for i in `ls -1 */*.zip`; do funzip $i >> ~/all.txt; done
cd ~

なんと全て解凍して結合するのに、unix だと2,3行でできる。 で、できたall.txt は 桁を間違えたかと思ったが普通に間違いなく1GByte のファイルになっていた。下記コマンドを打って寝るというのが当初の作戦であった。

load data local infile 'all.txt' replace 
into table  tbl_dg_ohlc fields terminated by ',' 
lines terminated by '\r\n';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

んぬぬ。
タイムアウト。。
┐(´∀`)┌ヤレヤレ。てか若干ヤッパリ感。


mysqlimport ではだめだろうか。
mv all.txt tbl_dg_ohlc
mysqlimport -u root -L --lines-terminated-by="\r\n"
 --fields-terminated-by="," db_finance tbl_dg_ohlc -p
load data local infile でダメだったからダメいかもと思いつつ。 寝てみる。起きてきて終わってたら超嬉しい。 もやすみ

RaspberryPi に 家庭内株価データベースを構築する。

ヤフー!から株価のデータはゲットできるのだけど、流石に全銘柄ってのは申し訳ないなと思い始める。

HTMLからデータを抽出して毎日の転送量の事を思うとやってられないという気持ちが出てきてたぶん転送量とか生のCSVを取るのと比べて100倍くらいは、非効率なんじゃないだろうか。YAHOO FINANCEプレミアム会員になろうとも思ったが、Data-get のアカウントを持ってるので1か月だけ更新してみた。1500円。毎月1500円の副収入が得られるようになったら継続していこうと思う。

でもdata-get の株価は十分だけど、時系列データを取ろうとするとちょっと骨が折れる。
基本的に日々データなので銘柄毎に変換してやる必要がある。

RaspberryPI上に株価データを構築することにする。

といっても、過去にすでにインストール済みであったため、何もすることが無かった。

create table tbl_dg_ohlc(
d CHAR(8), 
s CHAR(4),
m CHAR(2),
o float,
h float,
l float,
c float,
v float,
primary key(d,s,m) );

で、テーブルを作って日々データを解凍して

 load data local infile '201601.txt' replace into table tbl_dg_ohlc
 fields terminated by ',' lines terminated by "\r\n";

みたいな日時作業にできる。

「なんでフィールド名短いネン!」

って突っ込みはあろうが、日々データをいつも見てると
F_SECURITY_CODEみたいな、フィールド名つけるのも面倒くさい。
自分専用だからこれで十分明快なのだ。
d→ 日付
s→証券コード
m→市場コード
o→始値
h→高値
l→低値
c→終値
v→出来高


 select * from tbl_dg_ohlc where s="9984";
な感じでソフトバンクだけの時系列データをとれるようになった ワイ♪ あと解凍するときはunzipをインストールしたら入ってくる funzip が便利。 標準出力に出るのでコマンドラインにまとめやすい。