競馬であそぶ 6

風鈴の下、カキ氷でも食いながら


  1. 時系列オッズの取得 (2005.07.13)
  2. JV データ取得の準備 (2005.07.19)
  3. JVOPT.pl 最終版 (2005.08.06)
  4. 部分的な修正 (2005.07.31)
  5. kbsTk ファイルに出力 (2005.08.01)
  6. おしまいに、、
---------------------------------

トップページへ




0.  Perl であそぶ

Perl のモジュールを調べているうちに、Perl/Tk で CUI から GUI への道が見えてきました。
Win32::OLE では、VB.NET と同じようなレベルで JV-Link を扱えることが分かりました。
Perl で競馬検討用のツールを作成するのは、そんなに難しくはないんだと実感。

この一年、Access の VBA から始まり、VB.NET を経て再び Perl に戻ってきたわけです。
このシリーズが終わった後は、Python あたりも少しやってみたいような気もするけど、今まで
取り上げたモジュールを活用して、やりのこしたことをもうチョイ進めましょう。

Perl/Tk にしても、Win32::OLE にしても検索で役に立つ先例がなかなか引っかからないという
のは、ちょっと意外だったけど、このシリーズくらいのレベルでどんどん情報が公開されるといい
かな、と思っています。

これからプログラムをやろうという人でも、この程度からなら俺でも出来るって思うでしょ。 多分。
実際は結構ハマったり、バカなこと繰り返してたり、勘違いばかりだったりするんですよね。
そんなとき、同じような間違いをしてるのを見るとナンカが閃いて解決したり、 そういうものなん
です、、でしょ。

だから検索で引っかかるってのは、別に「答え」じゃなくても良い訳です。正解ならもっといいで
すけど。
だから、自分が迷ったところを中心に今回のシリーズは行くつもりです。

このシリーズのテーマは、「(Perl)JVD_OLE で (VB.NET)JVDTXT を超える」です。
で、Perl/Tk をもう少し調べないとダメなんで、この夏あそぶオモチャはこれですね。

実のところ、自由度の高さを考えると、JVD_OLE はむしろバラバラにして他のツールに組み込
んだりした方がイイのかもしれませんが、それは先の話ということにします。




1.  時系列オッズの取得  

速報系のデータの保存期間は、一週間ですが時系列に限って(蓄積系に代用できるデータがない
せいか)保存提供期間が一年間になっています。
sSeia は、このデータを眺めることはあるのですが、実際に馬券検討に使ったことはありません。
しかし、全く意味がないとも言い切れず一応取得する方法だけを考えてみました。

速報系データ取得は、JVRTOpen を使い、パラメータは dataspec と key です。
key は YYYYMMDDJJRR または YYYYMMDDJJKKHHRR のフォーマットで指定するわけ ですが、
レースNo.(RR)以外は、開催スケジュールから切り出すことにします。
ということで 該当年の開催スケジュールがないと、その年の時系列が取得できません。

JVSET.ini の YSCHTime を 20041225000000 くらいに書き換えれば2004年の開催スケジュール
が取得できる筈です。YSNW20049999.dat が取得されていればOKで、 準備はこれだけです。

が、、、古い時系列データを取得するのはいいのですが、当然のことながらファイルサイズはかな
りの大きさです。そのうえ、結構時間がかかります。覚悟してやってください。
他オッズとは違うディレクトリに保存する方がよさそうですね。

↑ この部分は、ini ファイルとスクリプトと共に修正の必要があります。
いまさら、お手本というレベルでもないとおもうので、この辺は自分で修正ですかね。

ファイル名に関しては、他の速報オッズ系とは違うようなので工夫が必要です。
下の例を参考にしてください。保存ファイル( $fname )のあたりです。
一応、JVD_OLE.pl のなかに置けば(多分)動く サブルーチンです。

sub jikretu {
    my @keys ;
    my $ymdbr ;
    my $dir = $cfg->param("pass.rcovP") ;

#   my $f2004 = "${dir}YSNW20049999.dat" ;  # 2004年 -------------
#   open DAT, $f2004 ;
#   while ( <DAT> ) {
#       my ( $m, $n ) = unpack '@2 A1 @11 A10', $_ ;
#       next unless $m == 3 ;
#       ## まぁ、2004年6月からということにしますか。
#       next if $n < 2004060000 ;
#       push @keys, $n ;
#   }
#   close DAT ;

    my $f2005 = "${dir}YSNW20059999.dat" ;  # 2005年 -------------
    open DAT, $f2005 ;
    while ( <DAT> ) {
        my ( $m, $n ) = unpack '@2 A1 @11 A10', $_ ;
        next unless $m == 3 ;
        ## まぁ、試しで今年の 6月以降を
        next if $n < 2005060000 ;
        push @keys, $n ;
    }
    close DAT ;
# -----------------------------------------------------------------
    for my $i ( @keys ) {
        for my $j ( 1..12 ) {
            my $jj = sprintf "%02d", $j ;
            $ymdbr = $i . $jj ;
            &get_jikr( $oz_jktf ) ;
            &get_jikr( $oz_jkur ) ;
        }
    }
    sub get_jikr {  # 引数はリファレンス( 種別ID、仮サイズ、保存用パス)
        my ( $ds, $bs, $ps ) = @{ shift() } ;
        my $rtn = $jvd->JVRTOpen( $ds, $ymdbr ) ;
        my $i = 0 ;
        RTR: while ( $rtn < -400 or $rtn == -1 ){
            sleep 1 ;
            $rtn = $jvd->JVRTOpen( $ds, $ymdbr ) ;
            $i++ ;
            last RTR if $i > 2 ;
        }
        my $dname = substr( $ymdbr, 0, 8 ) ;
        if( $rtn == 0 ) {
            my $dir = $cfg->param( $ps ) ;
            mkdir "$dir$dname" unless -d "$dir$dname" ;
            $dir .= $dname . '/' ;
            my $bsize = Variant( VT_I4, $bs ) ;
            my $pbuf = Variant( VT_UI1,  "\x00" x $bs ) ;
            my $buff = Variant( VT_BSTR|VT_BYREF, \$pbuf ) ;
            my $fn = Variant( VT_BSTR|VT_BYREF, '' ) ;  # ファイル名
            my $flg ;
            my $i = 0 ;
            my @dat = () ;
            while ( $flg = $jvd->JVRead( $buff, $bsize, $fn ) ) {
                if( $flg > 0 ) {
                    $dat[$i] = $buff->Value() ;
                    $i++ ;
                } elsif( $flg == -1 ) {
                    my ( $zen, $gon ) = unpack '@0 A4 @22 A4', $fn ;
                    my $fname = $dir . $zen .$gon . '.dat' ;
                    open DAT, ">$fname" ;
                    for ( @dat ) {
                        s/\x00+//g ;    s/\r// ;
                        print DAT $_ ;
                    }
                    close DAT ;
                    @dat = () ;     $i = 0 ;
                    print "\t\t読み込み完了。→ : $fn\n" ;
                } else {
                    print " 時系列データ・読み込みエラー。 $flg\n" ;
                }
            }
        } elsif( $rtn == -1 ) {
            print "時系列・該当データがありません。$rtn\n" ;
        } elsif ( $rtn == -504 ) {
            print "サーバーメンテナンス中。\n" ;
        } else {
            print "OPENエラー。$rtn\n" ;
        }
        &jv_close() ;
    }
}

期間を指定するのなら、 next if の行で指定するといいと思います。
2004年の分を取得する場合は、# でコメントアウトしている行を使うので、行頭の # を
削除ですね。

↑ では、1〜12R まで取得していますが、
        for my $j ( 1..12 ) {
の行を修正することで、8〜11R とかも可能です。このへんはアタマ使ってください。


ここまでの、JVD_OLE.pl と iniファイルは ⇒⇒
前回シリーズの最終章 に残してあります。




2.  JV データ取得の準備  

データを取得する画面を作るために、少し整理しておきます。
当然、前回の JVD_OLE を Perl/Tk に乗せる作業になります。

JV-Link はデータをJRA-VAN のサーバからダウンロードすると、専用のディレクトリに保存します。
 ⇒ (JV-Link の設定、データの保存場所で確認できます)
このデータは、JV-Link のルールで管理されており、中を覗く必要は殆どありません。
競馬プログラムは直接そのデータを使うわけではなく、自分の使える形にしてそれを取り込むわけ
です。
だから、競馬プログラムを複数使っている場合ダウンロードは最初の一回で済み、同じデータ を使
う次のソフトはデータ登録に要する時間を短縮できます。
逆にいうと、ダウンロードと取得(登録)は違うもので、プログラムで使用しないデータもダウンロード
している場合が結構あるのです。
って、このへんは一応念のため書いておきます。

で、ここで試みていることは、その JVData をテキストで保存して、そのデータを処理しよう。
ただそれだけのことなんです。

リアルタイムデータの取得は(JVRTOpenで)、レース毎(オッズ)と 開催日単位(情報系)とに分類でき
ます。
提供される期間は時系列オッズが一年間、それ以外は一週間です。
オッズの取得には、データ種別ID のほか開催日、レース場、レースNo.が 必要で少し面倒です。
情報系のほうは、データ種別ID と開催日だけです。
共に速報ということなので次々と追加・更新されているわけです。
データ種別ID の数だけで 14 あるので結構、見た目も複雑になりそうです。
いまの段階では、全賭式のオッズと票数、時系列は、外しておこうかなという考えに傾いています。

Perl の場合書き直せば簡単に、いろいろ出来るし「必要なら自分で」。
最悪の場合でも、工夫すれば(しなくても)蓄積系のデータで埋め合わせできると思います。

速報系以外のデータは(JVOpenで) option 1 で通常データ、option 2 で 今週データに分 かれます。
(→ option 3〜4 のセットアップは、必要ないので今回はパスします。)

これは、Fromtime 以降を取得するので、データ種別ID(dataspec)を分けて、それぞれに Fromtime
を保存する方法で行くのはどうかなと思っていました。
普通に使う分にはデータ種別ID の分類は不要ですが、データ取得のツールとして考えると、必要なとき
だけ必要なデータを Get 出来るほうがいい、という考え方です。

その場合、それぞれの取得用のスイッチを用意すればいいだけですが、実際にはデータベースを構築
するのでなければ、option 1 で RACE、DIFF、BLOD は不要だし、特別レース関連の TOKU とTCOV
もあまり必要ないので、結局残るのは option 1では SLOPとYSCH、option 2 では RACEとRCOVとい
うことになります。
まぁ、option 2 を外したら意味ないし、YSCH はこのスクリプトを動かすのに必要なので外せない。
ということで、取捨できる対象は坂路調教(SLOP)だけですね。これも一応、外しておきますが、、
人によって要不要の基準が違うし外すとはいっても、それらを入手する方法は簡単。

ほかに必要な機能は、各設定を変更する方法くらいですか。
保存用パスとか Fromtimeなどは、iniファイルで管理する予定ですが、、これは急ぐ必要はなさそう で
すね。直接、iniファイルをエディタなどで書き換えればいいことですから。
せいぜい、Text Widget 使って直接変更する程度で充分でしょうが、やる気ないです。

タイマー取得は今回は省略します。
オッズ等の情報取得のサブルーチンを個別に(他のスクリプトなどに)組み込んで利用すればイイだけ
で、あまり意味ない気がします。
リアルタイム系データの取得に必要性を感じたら、用意することにします。
最近の薄暮競馬への対策としても有効かもしれませんので、気が向いたらということで、、

上記を念頭に、以下のような作業を行います。

Perl/Tk 部分の Radiobutton は複数の値を保持できないので Checkbutton に変更とか、JVD_OLE
を単純に乗せるだけではうまくいきません。Widget の追加・変更〜
ボタン用の配列の追加・変更
基本データを開催スケジュールから取得 → 各種変更。
encording を sjis → cp932 へ変更。sjis for Windows くらいのこと?らしい。
use encording を使っているせいか、utf8 フラグが残るファイルがあるので、 その対策
ini ファイル名及び項目等を変更。
その他、細部の変更。


トップページへ 次へ