9
3

More than 5 years have passed since last update.

MATLABで競艇の解析を始めよう(払戻金の取得)

Posted at

MATLABでボートレース解析をする4番目の記事です。

 この時期は台風とかの影響でボートレースの中止が多いですねー、という季節に書いてます。江戸川は台風が来ても来なくても波がザッパンザッパンしてますけど。

みんな大好きな払戻金も取り込まないとね。

 1番目の記事でダウンロードができて、2番目の記事で出走表を読み込んで、3番目の記事で結果を読み込みましたが、配当はまだ取ってないですね。配当は3連単3,300円とかの払戻金のことです。

 こっちの方が今までの出走表とかよりデータが少ないので簡単そうですね。場所+日付+レース番号から、配当一式にアクセスできればいいかな。

 とりあえず 2019/8/1 - 8/3 の 3 日分をループにするとこんな感じ。

addpath('C:\work\boat')

%% テーブルを作ろう
T_div = table;
for n = datenum('20190801','YYYYmmDD'):datenum('20190803','YYYYmmDD')

    %% レース結果の読み込み
    fname = ['K',datestr(n,'YYmmDD'),'.TXT'];
    fid = fopen(fname);
    S = textscan(fid,'%s','delimiter','\n');
    C = S{1};
    fclose(fid);

    %% BGN/ENDを探す
    KBGN = find(contains(C,'BGN'));
    KEND = find(contains(C,'END'));

    %% BGN-END Loop
    for BEloop = 1:length(KBGN)

        %% BGN-ENDで切り取る
        res = C(KBGN(BEloop)+1:KEND(BEloop)-1);
        res(cellfun(@isempty,res)) = [];

        % 場所
        place = res{1}(1:3);
        place(place == 12288) = [];

        % 開催日
        ymd = datestr(n,'YYYYmmDD');
        start_idx = startsWith(res,'着');
        x = find(start_idx)-1;
        end_x = [x(2:end)-1;length(res)];

        % ここからレースのループ
        for Rloop = 1:length(x)
            % レース番号
            race = res(x(Rloop):end_x(Rloop));
            R = regexp(race{1},'\d+R','match');
            R = str2double(R{1}(1:end-1));

            ix = contains(race,'単勝');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) == 1   % 誰も買ってない場合の特払い70円 (2019/01/02 の 620行目の若松2Rとか)
                    win = NaN;
                    win_d = str2double(z{1}{1});
                elseif isempty(z{1})  % 2013/01/14 の 児島7R に単勝が書いてない
                    win = NaN;
                    win_d = NaN;
                else
                    win = str2double(z{1}{1});
                    win_d = str2double(z{1}{2});
                end
            end

            ix = contains(race,'複勝');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) == 1    % 特払い70円
                    show = [NaN NaN];
                    show_d = [70 70];
                elseif length(z{1}) < 4    % 2019/8/1 の 383行目みたいに、複勝なのに1個しか書いてないのが結構ある。
                    show = [NaN NaN];
                    show_d = [NaN NaN];
                else
                    show = [str2double(z{1}{1}),str2double(z{1}{3})];
                    show_d = [str2double(z{1}{2}),str2double(z{1}{4})];
                end
            end

            ix = contains(race,'2連単');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    exacta = NaN;
                    exacta_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    exacta = NaN;
                    exacta_d = str2double(z{1}{2});
                else
                    exacta = str2double([z{1}{2},z{1}{3}]);
                    exacta_d = str2double(z{1}{4});
                end
            end

            ix = contains(race,'2連複');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    quinella = NaN;
                    quinella_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    quinella = NaN;
                    quinella_d = str2double(z{1}{2});
                else
                    quinella = str2double([z{1}{2},z{1}{3}]);
                    quinella_d = str2double(z{1}{4});
                end
            end

            ix = contains(race,'拡連複');
            ix = ix | circshift(ix,1) | circshift(ix,2);
            rx = race(ix);
            if any(ix)
                z = regexp(rx,'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    wide = [NaN NaN NaN];
                    wide_d = [NaN NaN NaN];
                elseif ~all(ismember(rx{2}(1:3),'123456-'))  % フォーマットがおかしい (2013/04/04 三国9Rとか)
                    wide = [NaN NaN NaN];
                    wide_d = [NaN NaN NaN];
                else
                    wide = [str2double([z{1}{1},z{1}{2}]) str2double([z{2}{1},z{2}{2}]) str2double([z{3}{1},z{3}{2}])];
                    wide_d = [str2double(z{1}{3}) str2double(z{2}{3}) str2double(z{3}{3})];
                end
            end

            ix = contains(race,'3連単');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    trifecta = NaN;
                    trifecta_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    trifecta = NaN;
                    trifecta_d = str2double(z{1}{2});
                else
                    trifecta = str2double([z{1}{2},z{1}{3},z{1}{4}]);
                    trifecta_d = str2double(z{1}{5});
                end
            end

            ix = contains(race,'3連複');
            if any(ix)
                z = regexp(race(ix),'\d+','match');
                if length(z{1}) <= 1   % 不成立
                    trio = NaN;
                    trio_d = NaN;
                elseif length(z{1}) == 2   % 特払い70円
                    trio = NaN;
                    trio_d = str2double(z{1}{2});
                else
                    trio = str2double([z{1}{2},z{1}{3},z{1}{4}]);
                    trio_d = str2double(z{1}{5});
                end
                T_div(end+1,:) = {place,ymd,R,win,win_d,show,show_d,exacta,exacta_d,quinella,quinella_d,wide,wide_d,trifecta,trifecta_d,trio,trio_d};
            end
        end
    end
end

T_div.Properties.VariableNames = {'Place','YYYYMMDD','R','win','win_d','show','show_d','exacta','exacta_d','quinella','quinella_d','wide','wide_d','trifecta','trifecta_d','trio','trio_d'};

% 数種類に分類できる項目はカテゴリカル。
T_div.win = categorical(T_div.win);
T_div.show = categorical(T_div.show);
T_div.quinella = categorical(T_div.quinella);
T_div.wide = categorical(T_div.wide);
T_div.exacta = categorical(T_div.exacta);
T_div.trifecta = categorical(T_div.trifecta);
T_div.trio = categorical(T_div.trio);

例外が多すぎてプログラムが長くなってしまった。。。
ただ、実行時間は1秒未満でした。

ボートレース豆知識

 不成立は、フライングとかの失格が多くて、賭けが成り立たなくなったときに不成立になります。3艇失格なら3連複が不成立、4艇失格なら複勝・2連複・拡連複・3連複・3連単が不成立かな。

 特払いは、当たりの結果を誰も買ってないときに、購入者全員に金額の7割を払い戻す制度です。例えば単勝1番の舟券を1,000円持ってたのに6番が1着になってしまった場合でも、世界中の誰しもが6番の単勝を買ってない場合は、1番の舟券でも700円返ってきます。(=みんな一律に損をするけど、ハズレなのにお金が返ってくるので得した気になれる。)

データはちゃんと取れたのかな

コマンドウィンドウで見てみよう。

>> T_div

T_div =

  480×17 table

     Place      YYYYMMDD     R         win        win_d              show                 show_d       exacta    exacta_d    quinella    quinella_d       wide              wide_d           trifecta    trifecta_d    trio    trio_d
    _______    __________    __    ___________    _____    ________________________    ____________    ______    ________    ________    __________    __________    ____________________    ________    __________    ____    ______

    '唐津'     '20190801'     1    1                100    1            2               100     110      12         430         12           330       12  14  24     180     240     760      124             1400    124       820 
    '唐津'     '20190801'     2    1                110    1            3               120     190      13         450         13           380       13  12  23     140     100     160      132              660    123       170 
    '唐津'     '20190801'     3    3                160    3            2               120     210      32         680         23           570       23  13  12     130     110     150      321             1380    123       170 
    '唐津'     '20190801'     4    3                140    3            5               170     290      35         600         35           640       35  23  25     160     680     970      352             9420    235      3000 
    '唐津'     '20190801'     5    1                190    1            2               190     660      12         800         12           730       12  15  25     250     950    2000      125            13880    125      4860 
    '唐津'     '20190801'     6    6                900    6            4               520     490      64        3020         46          1300       46  56  45     250    1030    1480      645            28120    456      4840 
    '唐津'     '20190801'     7    2                490    2            3               210     150      23        1140         23           600       23  25  35     340     640     680      235             9340    235      2720 
    '唐津'     '20190801'     8    3                150    3            6               100     260      36         350         36           380       36  23  26     180     190     430      362             1080    236       430 
    '唐津'     '20190801'     9    1                110    1            2               110     190      12         250         12           250       12  13  23     120     140     200      123              590    123       230 
    '唐津'     '20190801'    10    3                730    3            4               600    1140      34        5370         34          2530       34  35  45     670     640    1100      345            21230    345      3900 
    '唐津'     '20190801'    11    2                190    2            1               100     100      21         380         12           150       12  24  14     120     250     150      214             1260    124       340 
    '唐津'     '20190801'    12    2                720    2            1               100     100      21         860         12           170       12  26  16     140     610    1100      216            11640    126      2460 
    '福岡'     '20190801'     1    1                150    1            2               110     430      12         160         12           190       12  16  26     150     270    1280      126             1680    126       690 
    '福岡'     '20190801'     2    1                230    1            3               130     100      13         820         13           360       13  15  35     120    1760     320      135            10380    135      1790 
    '福岡'     '20190801'     3    1                330    1            4               280     390      14         510         14           370       14  16  46     140     540     380      146             1320    146       520 
    '福岡'     '20190801'     4    2               2770    <undefined>  <undefined>     NaN     NaN      26       11130         26          4920       26  12  16     620     460     200      261            36510    126      1940 
    '福岡'     '20190801'     5    3                170    3            4               120     150      34         560         34           310       34  35  45     200     260     430      345             1290    345       510 
    '福岡'     '20190801'     6    1                360    1            2               130     130      12         750         12           420       12  13  23     280     160     250      123             2070    123       550 
    '福岡'     '20190801'     7    1                400    1            4               120     100      14         390         14           280       14  13  34     250     840     840      143             2820    134       900 
    '福岡'     '20190801'     8    1                100    1            3               100     110      13         150         13           110       13  15  35     100     450     300      135              800    135       610 
    '福岡'     '20190801'     9    2                620    2            4               120     210      24        1880         24           950       24  25  45     160     560     910      245             5350    245      1220 
    '福岡'     '20190801'    10    2                330    2            3               130     100      23         850         23           550       23  12  13     200     160     110      231             1920    123       240 
    '福岡'     '20190801'    11    1                720    1            2               100     140      12         300         12           140       12  15  25     190     230     420      125             1570    125       520 
    '福岡'     '20190801'    12    1                120    1            2               100     100      12         310         12           310       12  15  25     130     200     410      125             1860    125       900 

大丈夫そう!
win が単勝で当たりのボート番号、win_d が単勝の払戻金です。その他 _d を付けたのを金額にしました。

欠けたデータは何なのだ。

Qiita だと白くて目立つ Undefined とか NaN とかがあるけどなんだろう。
元のファイルで 2019/8/1 の福岡 4R を見てみよう。

   4R       予 選                    H1800m  晴   風  北   2m  波   3cm
  着 艇 登番  選 手 名  モーター ボート 展示 進入 スタートタイミンク レースタイム 差し   
-------------------------------------------------------------------------------
  01  2 3315 広 瀬  聖 仁 23  171  6.96   2    0.21     1.53.7
  02  6 4573 佐 藤    翼 65  112  6.90   6    0.05     1.56.0
  03  1 3870 寺 嶋    雄 21  120  6.92   1    0.11     1.57.0
  04  3 3977 山 本  兼 士 51  123  6.96   3    0.15     1.57.3
  05  5 3658 阪 本  聖 秀 61  165  6.89   5    0.12      .  . 
  06  4 4736 高 倉  和 士 55  161  6.94   4    0.08      .  . 

        単勝     2         2770  
        複勝     6          120  
        2連単   2-6      11130  人気    24 
        2連複   2-6       4920  人気    13 
        拡連複   2-6        620  人気    11 
                 1-2        460  人気     7 
                 1-6        200  人気     2 
        3連単   2-6-1    36510  人気    86 
        3連複   1-2-6     1940  人気     8 

複勝は2と6が当たりなのに、6しか書いてない!みたいなダメなデータが結構ある。。(なんとなく福岡に多い気がする。)
でもデータはその他にもたくさんあるのでプログラムで除外しちゃえばいいか、、という方針で、こういうのを見つけたら NaN とかにしておきましょう。(些細なことは気にしない。)

払戻金データも取れました!

 長くなったからここまでにするけど、次こそはデータの整理かなあ。
 また今度書くので、気になる人は「いいね」を押してね。(いいね病)

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3