じゃばのひまつぶし:ExcelVBAによる競馬ソフト自作教室とJRA-VAN登録ソフト(おずたんシリーズ)のサポートサイトです。
JRA-VAN Data Lab対応 競馬ソフト自作教室

<競馬予想ソフトを作るには?>
 
競馬予想ソフトを
作るには?

(更新:2016-02-22)
このページを閉じる時は「×」ボタンをクリックしてください。

プログラムのヒントやデバッグの方法    競馬ソフトの参考書

ここはExcel VBA(他のプログラム言語でも)で競馬の予想ソフトを作ってみたいという方のためのヒントです。
番号 項目 内容 備考
予想ソフトの作り方  予想ソフトを作るために必要なアイデアやスキルについて  下記参照 
JRA-VAN Data Labのデータ構造とデータ構造型定義 JRA-VANのデータ構成について 下記参照
JV-Dataのファイル名 JRA-VANのデータの種類とファイル名の関係について 下記参照
JV-Dataの種類 JRA-VANデータの種類の一覧表 下記参照
JV-Dataのファイルの読み方 ダウンロードしたファイルを配列に読む方法 下記参照


1.予想ソフトの作り方 
 JRA-VANデータを使う予想ソフトを作るための大きなポイントは2つです。
(1)どのようなソフトにするかというコンセプト(アイデア)・・・What
(2)プログラミングのテクニック(スキル)・・・How


(1)は、いわば何を作るか、つまりWhatでどんな機能のものを作るかで、オリジナルソフトには一番肝心なエッセンス−これはシークレットにしておく方がいいでしょう。理由は2つあります。
@1つは、個人の経験や予想理論を基にした貴重なアイデアですから、他の人に真似されないように。。。
Aもう1つは、私のように自分の予想理論がなく、人のアイデアを寄せ集めて作るために、秘密にして置かないと恥ずかしい、という場合もありますが。。。(でも競馬の本を買っての上なので勘弁していただきましょう)(^ ^;;

(2)は、アイデアを具体的な形にするためのスキル。いわばHowで、どのように作るか。データをどのように計算して、どのように表示するか。アイデアがすばらしくて、十分なスキルがあれば、売れるソフトが作れます(そういう方はここには用はありませんので、どうぞお引取りを)。

 ここはアイデアはあるけど、スキルにちょっと自信がないという人のためのサイトです。といって万年初心者の私なので、スマートにはできませんが、動けばいいやという方針で進めます。
 ここではExcelに付属しているVBA(Visual Basic for Application)という言語を利用してプログラムを作ります。VBAはVisual Basicの一種で、処理速度は遅いですが、まあ実用にはなると思います。初心者にとってはプログラムはなかなかとっつきにくいですが、判るところを少しずつ増やし、根気よく取り組めば、必ずできます。

プログラミングは楽しい!! あなたも競馬でプログラムをモノにしませんか。競馬が当たらなくても楽しめますよ。。。

アイデアもスキルもないが、自分でじっくりと作る根気もない、という方には、市販ソフトを購入することをお勧めします。。。
もう少し説明をすると。。。
(1)What--コンセプト(アイデア)や予想理論
 これは料理にたとえれば、あっさりとした麺類か、ヘビーなフルコースに仕上げるか。血統のデータベースにするか、スピード指数をベースにするか、あるいはオッズの動きを見るか。。。アナタのこだわりの”味”を出してください。
 私が普段使うソフトは、色々な人のアイデアを寄せ集めたもので、タイム指数や、SD指数を使ったり、市販の本を参考にしたり、オッズの変化も見るという鍋物のようなものです。

(2)How--プログラミング・テクニック
 これは料理で言えば、どのような材料(データ)をどのように料理するか。簡単な素材でも名料理人の腕にかかれば、すごい一品になりますが、腕前によっては素材を活かしきれない、ということに。私はいまだにそうですが。。。

ここで使うJRA-VANのデータは、素材としては十分でしょう。
料理するには、
@データの仕組み(構造)を理解すること。
Aデータの解析方法
 *データの取り込み方(検索、解読、抽出)
 *データのセーブやロード
 *データの計算や加工(オッズや連対率、スピード指数など)や計算結果の表示
等が必要です。
プログラミング・テクニックをアップするには?
@予想ソフトに必要なパーツ・プログラムを理解する。
 ソフトの流れを考えて、全体をどのような構成・順番でつくるのかを決め、細分化します。その中で使うプログラムはどのようなものが必要かを推定して、参考書等で近いプログラムを探して理解します。そして自分のプログラムに合わせるにはどこを変えればいいかを考えます。最初はこの作業がうまくいかないでしょう。慣れないとどんなプログラムが必要かがわからないからです。しかし、漠然とでもいいですから、自分で考えること、あるいは参考書のプログラムを予想ソフトに利用するにはどうすればいいのかなという眼で見ていくと必ずヒントになります。

AJRA-VANのソフトウエア工房などのプログラム例やサポートを読む。
 これも最初は難しいかもしれません。書かれていることがチンプンカンプンで、あきらめてしまうかもしれませんが、根気よく理解できるものを増やすつもりで読んでいくと、いろんな関係が少しずつ理解できていくと思います。
下記のサイトはまず入り口として参考になるので必読です。

予想ソフトの参考になるJRA-VAN Data Labサイト
(URLは時々変わる場合がありますので、注意してください)
 サイトURL  内容
http://jra-van.jp/dlb/index.html JRA-VAN Data Labの総合ページ
http://jra-van.jp/dlb/sdv/index.html JRA-VAN Data Labの予想ソフト開発コーナー。
ソフト開発に必要な仕様や開発ツールの総合ページ
http://jra-van.jp/dlb/sdv/sdk.html ソフトウエア開発キット(SDK)提供コーナー。JRA-VANデータの仕様書が入手できます。必見
http://jra-van.jp/dlb/sdv/pgm.html プログラミングパーツ・開発支援ツール提供コーナー。VBAやVBなどのサンプルプログラムが提供されています。ここも必見。VBAサンプルプログラムを利用します。
http://forum.jra-van.ne.jp/cgi-bin/datalab/bbsjvdata/datalabbbs.cgi JV-Dataの使い方の質問掲示板。過去のヒントになりそうな質問を探したり、聞きたいことを書き込むと回答が得られる場合があります。
http://forum.jra-van.ne.jp/cgi-bin/datalab/bbsjvlink/datalabbbs.cgi JV-Link質問箱。上と似たような掲示板。
http://forum.jra-van.ne.jp/cgi-bin/datalab/bbsprogram/datalabbbs.cgi プログラミング質問広場。上の2つと似たような掲示板ですが、全般的な質問向き。

2.JRA-VAN Data Labのデータ構造とデータ構造型定義
 JRA-VANデータ(JV-Data)は、基本的には「固定長バイト」のデータで構成されたテキスト型データです。

 JV-Dataの内の代表的な「レース詳細」(レコード種別ID=RA)データの構造イメージは下図のようになっています。図の右側の細長い短冊が「1つのレースを定義するレコード」になっています。レコードに含まれるデータはデータの中身によって「位置」と「データの長さ」が決められています。

 例えば最初の2バイトは「レコード種別ID」でこの短冊がどういうデータなのかという種類を区別する記号が割り当てられ、次の3バイト目から1バイト長のデータは「データ区分」としてこのレコードが前日情報なのか、月曜日の成績確定情報なのかなどの区別を示し、次の4バイト目から8バイト長のデータは「データ作成年月日」でいつ作られたレコードかを示し、さらに次の12バイト目から・・・という具合に最後のデータ区切りまで細かく位置が決められていて、全部で”1272バイト”の長さで提供されるというわけです。

このデータの”何バイト目から何バイト”を正しく読み取れば、必要な情報が得られるわけです。JRA-VANのサンプルソフトには、この情報を読み取る関数がふくまれています。このデータの位置と中身については「JRA-VAN Data Lab. JVData仕様書」を見てください。
慣れないととっつきにくいデータ構造型ですが、理解すれば便利なものです。

(1)JV-Dataは、レコード種別によって長さの決まった「固定長データ」で提供される。短いもので数十バイトから、三連単オッズのように長いデータで80kバイトまで。

(2)レコードの長さは「固定」で、未勝利戦でもG1レースでもレコードの長さは同じで、使わない箇所は「スペース」などの空白データで埋められています。

(3)レコードの数は、その日の開催レース数や出走頭数により変化する。つまり、3場所開催なら「レース詳細(RA)」のレコード数は最大36個、2場所なら24個が提供されます。
いわば、細長いレコードを細かい間仕切りで区切られた各階の「部屋」とすると「レース詳細」データは全体で図の左のように36階建てのビルのような形になっています。各階の部屋には無人(データがない)の箇所もあったり、データの中身は異なったりしますが、間取りと部屋の大きさは各階すべて同じです。

(4)すべて同じ間取りのレコードを互いに区別する情報が、図の太い線で囲まれた「レース開催情報」の部分で、ここに開催年月日や開催場所、レース番号などの情報が含まれています。ここを解読すれば、どの場所の何レースかが特定できます。レコード種別IDが異なってもこの識別できる情報が必ず含まれています。



同様にやはり代表的な「馬毎レース情報」(レコード種別ID=SE)のイメージを下図に示します。
馬毎レース情報というのは出走馬のデータなので、レコード数は1日分で最大3場所x12レースx18頭=648個になります。
各レコードの構成は"RA"データの場合と同じように各データの位置や長さは固定です。馬毎レース情報の場合は、識別データとして、「レース開催情報」のほかに、「馬番・枠番」や「血統登録番号」があります。馬番や枠番はレースが変ると変りますが、「血統登録番号」は各競走馬固有のもので、データベースでは重要なキーインデックスになります。



データ構造型とは?
 JRA-VANのデータはデータ構造型で定義されています。というと分かりにくいですが、上図のようにデータを区切り別にあるいは階層的にまとめて定義しているようなものと考えます。

 下図にJRA-VAN Data Lab.のサンプルソフト(Excel版)に含まれているデータ構造型定義の一部を示します。はじめの方の<レコードヘッダ>や<競走識別情報1>という部分はいろいろな定義の中で共通に使われる定義です。一方、<コーナー通過順位>という部分は、「レース詳細」という構造体定義の中でのみ使われる定義です。

 「レース詳細」(Public Type JV_RA_RACE)というデータの定義の中を見ると、単にAs Stringと文字列で定義している部分もありますが、id As RACE_ID のように別に定義されたものを使って変数(id)を定義するという部分もいくつかあります。 



上図の"RA"データは、サンプルソフトでは mRaData As JV_RA_RACEのように定義されます。つまりレコードの1つがJV_RA_RACEの構成をもち、内部はいろいろな項目で定義されています。このようにデータをあるまとまった区切りや階層的にして定義することを構造型といいます。
例えば、「レース詳細(RA)」のデータから、
@レコード種別を取得するには、mRaData.head.RecordSpec とします(headというRECORD_IDの部分の中のRecordSpecを読み出す)。
Aレース番号を取得するには、mRaData.id.RaceNum とします。
B登録頭数を取得するには、mRaData.TourokuTosu とします。

実際の使用例は本文の中の例を見てください。
3.JRA-VAN Data Lab データ(JV-Data)のファイル名
 JRA-VANデータをダウンロードする場合は、ファイル名がキーとなります。このファイル名は「データ種別ID」と「開催日付」及び「データ作成日付」などを組み合わせた形になっています。
ファイル名の決め方の詳細は不明ですが、4種類あり、大体下記のようになっています。

(1)「レース詳細」データの場合
 RAXXYYYYMMDDYYYYMMDDHHMMSS.jvd
それぞれの記号の意味は、
先頭の2文字がデータの種類により固有の記号が割り当てられています。レース詳細なら"RA"、馬毎レース情報なら"SE"、払戻情報なら"HR"など。「JRA-VAN Data Lab. JVData仕様書」のレコード種別ID項目に掲載されています。

XX:これはデータが作成されたタイミングによってある決まった文字列が割り当てられているようですが、内容は公開されていません。JRA-VANはこの文字列を識別記号として使うことを推奨していません(大体固定されているようですが)。
YYYYMMDD:開催日日付。レースが開催される年月日。
つぎのYYYYMMDDHHMMSSは、データが作成された日付・時刻を示すようです。
この長いファイル名を持つデータは次の速報系の(2)(3)(4)以外のデータです。

(2)0B30YYYYMMDDJJRR.jvd形式
 これは速報系データのうち、全賭式オッズデータのファイル名の形式です。
0B30:ゼロビーサンゼロ。速報系全賭式オッズデータのデータ種別ID。
YYYYMMDD:レース開催年月日。
JJ:開催場所コード番号。
RR:レース番号。
0B30オッズデータには、単・複・枠連、馬連、ワイド、馬単、三連複、三連単のデータが含まれます。
0B31データは単・複・枠連、0B32は馬連、0B33はワイド、0B34は馬単、0B35は三連複、0B36は三連単の単独データです。

(3)0B11YYYYMMDD.jvd形式
 これは速報系データのうち、「開催変更情報」(0B14)、「馬体重」(0B11)、「速報レース情報」(0B12)、「データマイニング情報」(0B13)などに使われるファイル名です。
0B11:データ種別ID。この場合は馬体重情報。
YYYYMMDD:レース開催日付。

(4)0B410000000000YYYYMMDDJJRR.jvd形式
 これは速報系データのうち、時系列オッズデータの「単複枠オッズ」(0B41)、「馬連オッズ」(0B42)のファイル名の形式です。
0B41:ゼロビーヨンイチ。オッズ種類のID。今のところ時系列データは、"0B41","0B42"が提供されています。
間に10桁の"0"(ゼロ)をはさみ、(2)と同じ形式の識別情報が続きます。
4.JV-Dataの種類
 下表は、JV-Dataで使われるデータフォーマットの種類の一覧です(サンプルプログラムの標準モジュール:JVlink_Stluctに記述されています)。全部で29種類のデータがあり、それぞれ固有のデータ構造体で定義されます。データセット関数というのは、ダウンロードしたデータをデータ構造体に代入する関数(サブルーチン)です。
このデータセット関数を使うことでJV-Dataが使いやすくなります。
番号 フォーマット名 データ構造体名 データセット関数名 備考
1 特別登録馬 JV_TK_TOKUUMA SetData_TK  
2 レース詳細 JV_RA_RACE SetData_RA  
3 馬毎レース情報 JV_SE_RACE_UMA SetData_SE  
4 払戻 JV_HR_PAY SetData_HR  
5 票数1 JV_H1_HYOSU_ZENKAKE SetData_H1 三連単以外
6 票数6 JV_H6_HYOSU_SANRENTAN SetData_H6 三連単のみ
7 オッズ1 JV_O1_ODDS_TANFUKUWAKU SetData_O1 単複枠連オッズ
8 オッズ2 JV_O2_ODDS_UMAREN SetData_O2 馬連オッズ
9 オッズ3 JV_O3_ODDS_WIDE SetData_O3 ワイドオッズ
10 オッズ4 JV_O4_ODDS_UMATAN SetData_O4 馬単オッズ
11 オッズ5 JV_O5_ODDS_SANREN SetData_O5 三連複オッズ
12 オッズ6 JV_O6_ODDS_SANRENTAN SetData_O6 三連単オッズ
13 競走馬マスタ JV_UM_UMA SetData_UM  
14 騎手マスタ JV_KS_KISYU SetData_KS  
15 調教師マスタ JV_CH_CHOKYOSI SetData_CH  
16 生産者マスタ JV_BR_BREEDER SetData_BR  
17 馬主マスタ JV_BN_BANUSI SetData_BN  
18 繁殖馬マスタ JV_HN_HANSYOKU SetData_HN  
19 産駒マスタ JV_SK_SANKU SetData_SK  
20 レコードマスタ JV_RC_RECORD SetData_RC  
21 坂路調教 JV_HC_HANRO SetData_HC  
22 馬体重 JV_WH_BATAIJYU SetData_WH  
23 天候馬場状態 JV_WE_WEATHER SetData_WE  
24 出走取消・競走除外 JV_AV_INFO SetData_AV  
25 騎手変更 JV_JC_INFO SetData_JC  
26 発走時刻変更 JV_TC_INFO SetData_TC  
27 コース変更 JV_CC_INFO SetData_CC  
28 データマイニング予想 JV_DM_INFO SetData_DM  
29 開催スケジュール JV_YS_SCHEDULE SetData_YS  
実際のソフトで使う場合には、下図のようにダウンロードしたデータを必要なデータセット関数でデータをセットして初めて利用できると考えてください。


サンプルプログラムの標準モジュール(JVLink_Stluct)には他にも共通のデータ構造体やバイト長データを切り出す重要な関数などが定義されています。
5.JV-Dataのファイルの読み方  
** 馬主マスタ”BN”を例にしたダウンロード **
(1)JVLinkでダウンロードしたデータを表示する場合(サンプルソフトと同じ)
  @追加する定義
    Dim mBnData As JV_BN_BANUSI  ‘(サンプルソフトの馬主マスタの定義参照)
    Dim j As Integer, k As Integer

 A参考コード
    Dim i As Integer
    i = 0
    retVal = 1
    While retVal <> 0
        'JVOpenで指定したデータを1レコードずつ取り込み
        retVal = JVLink1.JVRead(buff, 40000, filename)

        If Left(buff, 2) = "BN" Then         馬主マスタの場合
            'JVData構造体にBNのレコードをセットする
            Call SetData_BN(buff, mBnData)        ←データセット関数利用

            'Sheet1の表示箇所に表示
            Sheet1.Cells(4 + i, 2) = mBnData.BanusiCode      馬主コード
            Sheet1.Cells(4 + i, 3) = mBnData.BanusiName     馬主名(法人格無)
            Sheet1.Cells(4 + i, 4) = mBnData.Fukushoku      服色標示

            繰り返し表示(本年・累計賞金、着回数データ)
            For j= 0 To 1
               Sheet1.Cells(4 + i, 5 + 9 * j) = mBnData.HonRuikei(j).SetYear
               Sheet1.Cells(4 + i, 6 + 9 * j) = mBnData.HonRuikei(j).HonSyokinTotal
               Sheet1.Cells(4 + i, 7 + 9 * j) = mBnData.HonRuikei(j).Fukasyokin

               For k= 0 To 5
                  Sheet1.Cells(4+i,8+9*j + k) = mBnData.HonRuikei(j).Chakukaisu(k)
               Next k

            Next j

            i = i + 1

               ‘(2)のいったん配列に読み込む場合はここに追加(後述)

           End If

           Label1.Caption = buff
           DoEvents
       Wend

       JVLink.JVClose

 上記でSheet1にデータセット関数で読み込んだデータが表示されると思います。馬主は法人格のものは表示していないので歯抜けになるかも、また繰り返し表示の部分はセル位置がずれてるかもしれませんので、適当にj,k列位置を計算してください。

(2)JVLinkでダウンロードしたデータをいったん配列に読み込む場合
 以下を追加
@ 標準モジュール内(NENGAPPIの定義と同じモジュール)
  Public BnData( ) As String             馬主マスタ配列

A (1)と同じプロシージャ内
        Dim FileData(1) As String             ファイル名保存
        ReDim BnData(1 To 1296) As String   仮馬主マスタ配列
B 上記の(後述)の部分に下記コードを挿入
  BnData(i)= Left(buff, Len(buff) -2 )    バッファデータを配列に読み込む
C上記のJVLink.JVClose の後に追加(BnData配列のセーブとロード)
 セーブ
    '----- ファイルへの代入 -----
    If retVal = -1 Then             'データの区切り           
        If Left(filename, 2) = "BN" Then        '馬主マスタデータ
            FileData(1) = Left(filename, Len(filename) - 4) & ".dat"
        End If
    End If
  
   CopyFile$ = COPY_DIR & NENGAPPI & "\" & FileData(1)         '馬主マスタ
    FileNo = FreeFile
    Open CopyFile$ For Output As #FileNo
    For q = 1 To i
        Print #FileNo, BnData(q)
    Next q
    Close #FileNo

 ロード
    CopyFile$ = COPY_DIR & NENGAPPI & "\BN*.dat"           '馬主マスター
    If Dir(CopyFile$) <> "" Then
        filename = Dir(CopyFile$)
        FileData(1) = filename
        CopyFile$ = COPY_DIR & NENGAPPI & "\" & filename
        FileNo = FreeFile
        Open CopyFile$ For Input As #FileNo
   'データ数(k)を求める
    k = FileLen(CopyFile$) / 477      '477は馬主データのサイズ(バイト)
        ReDim BnData(1 to k) As String
        For i = 1 To k
            Line Input #FileNo, BnData(i)
        Next i
        Close #FileNo
    End If
ReDim BnData(1 To 1296)のデータサイズ1296は「土日分」で最大1296頭の馬主がすべて違う場合の想定のため。実際には600くらいで十分? 1296というのは仮のサイズで、最初は馬主数が分からないので、最大に設定しておき、読みながらカウントI=I+1していけば最後のIが馬主数になります。セーブするときにI分だけセーブします。ロードするときはファイル長を477バイトで割ったサイズkが馬主数なので、最大k分のデータを読み込みます。

以上でコードは終わりです。うまくいった場合にはディレクトリ内にBNxxxx.datファイルができているはずです。ロード部分はセーブしたものを読み出すためのサンプルなので、なくても構いませんが、これを使ってデータセット関数でCall SetData_BN(buff, mBnData)buff部分をBnData(i)に置き換えれば、iを変化して配列の中身を次々にmBnDataにセットすることができます。BnData(i)の形にしてしまえば別にSetData_BNを使う必要もないのですが、半角・全角の処理をやってくれるのは楽かなと思います。

以上は”BN”のデータで説明しましたが、他のデータでも基本的には同じです。FileData(1)というのは他のデータも同様にセーブするときにこのサイズを増やせば類似の方法でセーブできという便宜上のものなので、”BN”しかセーブしない場合は、A$とかでも構いません。



ページトップへ
 Copyright(C):Jaba 2000-2012