« 2007年4月 | トップページ | 2007年6月 »

2007年5月に作成された記事

2007年5月27日 (日)

Perlを使ってDDE通信でRSSにアクセスする

楽天証券がDLJ時代から提供しているRSS (Realtime SpreadSheet; Blogなどを読むRSSとは違う)を使って、Excelでリアルタイム株価を取得することができる。RSS自体はDDEというWindowsのプロセス間通信のしくみを使っており、クライアントプログラムを作成すればExcel以外からも使うことができる。

ということで、自分が使い慣れているPerlでDDE通信するプログラムを作成することにした。

PerlでDDE通信をするのに最も簡単な方法は、Win32::DDEというモジュールを使うことだ。ActivePerl標準ではないので、ここを参考にしてppmの設定をしてインストールする。

使いかたは以下のような感じになる。

use Win32::DDE::Client;

my $Server = 'RSS'; # サービス名「RSS」
my $Topic = 'N225.FUT01.OS'; # トピック名 この例は日経平均先物
my $Price = '現在値'; #アイテム名 この例は現在値

#First, Connect DDE
my $Client = new Win32::DDE::Client ($Server, $Topic);
die "Unable to initiate conversation" if $Client->Error;

defined ($Rcvprice = $Client->Request ($Price)) ||
  print "DDE request failed\n";
# 結果は小数点2桁となっているので小数点以下を消す (17580.00を17580にする)
$Rcvprice =~ s/^  (\d+).(\d+)$/\1/;

$Client->Disconnect;

意外と簡単にできる。ただ、Win32::DDEを使う方法にはいくつか問題点がある。

一番大きな問題は、hotlinkが動作しないということである。ExcelのRSSは、株価が変わったらそのことをサーバがクライアントに通知(XTYP_ADVDATA)し、クライアントはそれを受けてからサーバに株価データを取りに行くというホットリンククライアントとなっているが、Perlを使うとそれがうまく動作しない。これは、海外のサイト含めていろいろと調べたり、Win32::DDEを使わずにWin32::APIでDDE関連のwin32api関数をコールするようにしたり、待機するしくみとしてsleep関数ではなくPOEをつかったり、とかなりの試行錯誤をしたんだけど、どうしてもできなかった。Win32::DDEには、テストされていないと書いてあるけどXTYP_ADVSTARTを送る関数があったりコールバック関数を登録することができたりするが、DDEサーバであるRSSがXTYP_ADVDATAを送っているにもかかわらず、それをPerl側で拾えないという感じだった。(RSSがXTYP_ADVDATAを送っていることは、DDE通信を見るツールで確認した。DDE通信を見る方法としてDDESpyというものがあるらしいが、これは何かの有料の開発キットに入っているものらしく利用できなかった。代わりに、こちらのサイトにあるDynamic Data Studioというものを使った。) ただ、クライアント側からデータ取得などでDDE通信をしているときに発生したXTYP_ADVDATAは拾うことができ、実際にコールバック関数が呼ばれた。たまにできることがあるが、基本的にはNGというやっかいな現象だった。

次に問題となるのは、上の例でいう$Client->Request でのデータ取得を16384回以上やるとエラーとなってしまうことである。この原因は、上記の試行錯誤でWin32::APIのwin32api関数をコールするコードを書いているときに判明したが、Win32::DDE::ClientのRequestの処理中に取得したDDEオブジェクトハンドルを解放しないままにしていることが根本原因と分かった。日経平均先物の歩み値を取得するプログラムを書いていたが、1秒に1回データを取得するようにすると、売買が活発な後場にぎりぎり足りなくなるということがあって困っていた。解決策としては、そんなにデータを取得しないようにするか、もしくは根本対策としてWin32::DDE::ClientのRequestで取得したDDEオブジェクトハンドルを解放するようにするか、もしくはWin32::APIを使ってDDE通信をするようにし、その中でDDEオブジェクトハンドルを解放するようにすることである。これにより、0.2秒ごとにデータを取得しても問題なく、10万回データ取得しても問題なくなった。

もう一つ問題があって、たまに以下のようなエラーが出てしまってプログラムが終了してしまうことがある。
Undefined subroutine &main:: called at c:/Perl/site/lib/Win32/DDE/Callback.pm line 46.
これは、newでコールバック関数を登録していても発生していた。該当箇所を見たが、なぜかコールバックが呼ばれたときにうまくコールバック関数自体を読み込めていないというように理解できた。この解決策は、Callback.pmの該当箇所 (&$runsub のところ) をコメントにして無効化してしまうことである。ちなみに、試しにコメントになっている&main::TestCBという部分を有効にし、TestCBという関数をプログラムで用意したところ、その関数が呼ばれ、XTYP_REGISTERを受信していることが分かった。上記の試行錯誤をやっているときに気づいたが、Perlのプログラムで3分などの周期的にデータ取得するプログラムが動作している状況で、場中に適時開示情報などでIEで別の窓を作ってPDF文書を開いた後にデータ取得をしたタイミングでXTYP_REGISTERを受信していることが分かった。XTYP_REGISTER を受け取らないようにするには、DdeInitializeのafCmdでCBF_SKIP_REGISTRATIONSを指定すればよいが、afCmdはWin32::DDEでは決めうちで0になっている。

Win32::APIを使ってDDE通信を記述するには、win32apiのDDE関連を理解する必要がある。本家のMSDNや、こちらのサイトの記述(Window SDK編 第2部第150章第155章)が参考になった。また、DDE関連のヘッダファイル(ddeml.h)はここにあった。これがないと定数の値などが分からなくて困る。

ホットリンクを使うにはPerlをあきらめてC#でも勉強するしかないと覚悟したが、なんとかごまかしが効きそうだったので、しばらくはPerlでやっていく予定。C#を勉強するいい機会とは思ったんだけど。

[2007/06/30追記]

Win32::DDE::Clientで16384回以上のRequestをするとエラーとなる件について、Client.pmに対して根本対策のコードを追加した。たった1行だけど参考に書いておく。

*** Client.pm.orig Sun Oct 12 05:59:44 1997
--- Client.pm Sat Jun 30 23:26:22 2007
***************
*** 102,107 ****
--- 102,108 ----
  Win32::DDE::DdeGetData($hdata, $buf, $size, 0);
  $buf =~ s/\0.*$//s;
  $ret = $buf;
+  Win32::DDE::DdeFreeDataHandle($hdata);
  } else {
  $ret = undef;
  }

| | コメント (2) | トラックバック (0)

2007年5月 6日 (日)

「マーケットプロファイル分析」を読んだ

「マーケットプロファイル分析」 (柏木 淳二 著)を読んだ。

著者の柏木氏は、マーケットプロファイル分析に関する本を3冊出版しているが、この本が最初のものであり、他の2冊と比較して基本的な部分をちゃんと解説している。短期ディーリング戦略についても記述があり、トレンドデーだとどういう戦略にすべきか、ノントレンドデーだとどういう戦略にすべきか、などが書いてある。

他の2冊(「デイトレーダーのためのマーケットプロファイル分析」「マーケットプロファイル - 市場心理を読んで相場に勝つ方法」)はこの本の内容を前提をしているので、すでに絶版となっているが、ぜひ入手して読んでおくことをお勧めしたいと思う。

この本で、30分時間帯ごとのモード、バリューエリア、TPO、RFについて、それがどのように推移するのかということも相場のヒントになるという記述があった。2月の時点でマーケットプロファイルを作成するプログラムを書いていたが、実際の相場で使うときに、場中の30分毎の各指標を表示することができなかったので、この本を読んだことを機に、それもできるように改良した。

この本を読む上で注意が必要なのは、10年ほど前にかかれた本なので、最近の相場では当てはまらないパターンもあるかもしれない、ということがある。このあたりは経験を積んで応用できるようにしていくしかないんだろう。マーケットプロファイルという考え方自体は流動性のある相場なら使えるものだとは思う。

| | コメント (0) | トラックバック (0)

« 2007年4月 | トップページ | 2007年6月 »