1500mのレースに未対応だったので修正をかけたら、さらにバグを発見した件
JRAの過去のレース結果を解析して予想に役立てようという試みを性懲りもなく続けています。
過去走の解析では、対象レースと同じ距離のレースだけでなく、その前後の長い距離、短い距離のレース結果も解析対象としています。1400mの競争ならば、1150m、1200mなどの短い距離や、1600mといった長い距離のレースが対象となります。先週までは、あまりかけ離れた距離よりも近い距離のほうが参考になるかと思って対象距離の上下250mで区切っていました。
今週から札幌開催が加わったのですが、ここで問題が発生しました。1500mのレースだけ、過去走の解析結果が、すっぽり抜け落ちていたのです。過去走のデータを確認すると、ほとんどの馬が、1800mのレースの経験馬で、250mの範囲に引っかからなかったので集計されなかったことがわかりました。
他の距離だとだいたい250mの範囲をカバーしておけばいいので、1500mのレースだけ範囲を300mに広げることにして、VBAのコードを修正しようと見直したのですが、そのコードに、致命的なバグが隠れていたというのが今回の話です。
これが、致命的なバグを含んだコードです。
'該当距離が存在しない場合に機能しない
Function fcClosedLongerDistance(Distance As Long, TrackType As String, DistanceList() As B2DistanceInfo)
fcClosedLongerDistance = Distance
Dim Distance2 As Long
ListSize = UBound(DistanceList)
Dim Index As Long
Index = fcB2DistanceInfoGetIndex(Distance, DistanceList)
If Index < 0 Then
Exit Function
End If
Dim N As Long
N = -1
Dim Cnt As Long
For Cnt = Index + 1 To ListSize
Distance2 = DistanceList(Cnt).Distance
If DistanceList(Cnt).N > N Then
fcClosedLongerDistanceOLD = Distance2
N = DistanceList(Cnt).N
End If
If Abs(Distance2 - Distance) > 250 Then
Exit Function
End If
Next Cnt
End Function
Function fcB2DistanceInfoGetIndex(Distance As Long, DistanceList() As B2DistanceInfo)
fcB2DistanceInfoGetIndex = -1
Dim Distance2 As Long
ListSize = UBound(DistanceList)
Dim Cnt As Long
For Cnt = 0 To ListSize
If DistanceList(Cnt).Distance = Distance Then
fcB2DistanceInfoGetIndex = Cnt
Exit Function
End If
Next Cnt
End Function
ダメなのは、最初の関数の前半で二つ目の関数をコールしてIndexを取得している部分です。DistanceList配列が、過去走の中に出現する距離を昇順に並べたリストなのですが、 二つ目の関数で、対象レースの距離の要素番号を検索しています。長距離の解析の場合は、この要素番号以降の項目を、ひとつめの関数の後半でスキャンしているのですが、 大前提として、過去走に、対象レースの距離が含まれていないと、この処理は機能しません。
札幌の1500mのレースでは、そもそも1500mを走ったことのある馬がいなかったため、DistanceList配列に1500mの要素は含まれていません。従って、エラー(-1)を返していたという状況でした。 修正後のコードがこちら。
'長距離 Function fcClosedLongerDistance(Distance As Long, TrackType As String, DistanceList() As B2DistanceInfo) fcClosedLongerDistance = Distance Dim Distance2 As Long ListSize = UBound(DistanceList) Dim Diff As Long Diff = 250 If Distance = 1500 Then Diff = 300 End If Dim N As Long N = -1 Dim Cnt As Long For Cnt = 0 To ListSize Distance2 = DistanceList(Cnt).Distance If Distance2 <= Distance Then GoTo Continue End If If DistanceList(Cnt).N > N Then fcClosedLongerDistance = Distance2 N = DistanceList(Cnt).N End If If Abs(Distance2 - Distance) > Diff Then Exit Function End If Continue: Next Cnt End Function
Indexを取得する関数は不要になったので削除。1500mの距離のみ、探索範囲を300mとして1800mまでをカバーしています。他の距離については探索範囲は250mのままです。 DistanceList配列の要素Nは、各馬の過去4走における距離別のレースをカウントしたものです。同じレースであっても馬が異なれば別カウントです。1500mのレースの過去走で、 1700mのカウントが5、1800mのカウントが15であれば、1800mのレース成績を解析対象としています。
この変更で予想の精度が上がることを期待して解析処理を走らせてみたところ、一か所変更漏れが発覚し、先ほどから再度実行中。処理完了に6時間ぐらいかかるので、 今日のVBAプログラミングはこれにて終了。