SGソフトウェアの開発日記

日々の開発に関するあれこれを書き散らかしています。

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プログラミングはこれにて終了。