From df428ed1e88a1b0845f2c6a868509b5bb6b6f8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fahri=20Can=20Se=C3=A7er?= Date: Wed, 22 Apr 2026 02:17:02 +0300 Subject: [PATCH] gg --- .../catboost_info/catboost_training.json | 874 ++++++++++++++++++ .../catboost_info/learn/events.out.tfevents | Bin 0 -> 47720 bytes ai-engine/catboost_info/learn_error.tsv | 871 +++++++++++++++++ .../catboost_info/test/events.out.tfevents | Bin 0 -> 47720 bytes ai-engine/catboost_info/test_error.tsv | 871 +++++++++++++++++ ai-engine/catboost_info/time_left.tsv | 871 +++++++++++++++++ ai-engine/features/rolling_features.py | 243 +++++ ai-engine/scripts/backtest_niche.py | 215 +++++ .../scripts/conditional_frequency_engine.py | 312 +++++++ ai-engine/scripts/extract_training_data.py | 10 +- .../scripts/extract_training_data_v27.py | 305 ++++++ ai-engine/scripts/strategy_generator.py | 317 +++++++ ai-engine/scripts/train_v27_value_sniper.py | 480 ++++++++++ mds/changelog-2026-04-22.md | 155 ++++ src/modules/coupons/coupons.controller.ts | 38 +- src/modules/coupons/coupons.module.ts | 16 +- .../coupons/dto/coupons-request.dto.ts | 44 + .../services/frequency-engine.service.ts | 584 ++++++++++++ .../coupons/services/smart-coupon.service.ts | 239 ++++- 19 files changed, 6436 insertions(+), 9 deletions(-) create mode 100644 ai-engine/catboost_info/catboost_training.json create mode 100644 ai-engine/catboost_info/learn/events.out.tfevents create mode 100644 ai-engine/catboost_info/learn_error.tsv create mode 100644 ai-engine/catboost_info/test/events.out.tfevents create mode 100644 ai-engine/catboost_info/test_error.tsv create mode 100644 ai-engine/catboost_info/time_left.tsv create mode 100644 ai-engine/features/rolling_features.py create mode 100644 ai-engine/scripts/backtest_niche.py create mode 100644 ai-engine/scripts/conditional_frequency_engine.py create mode 100644 ai-engine/scripts/extract_training_data_v27.py create mode 100644 ai-engine/scripts/strategy_generator.py create mode 100644 ai-engine/scripts/train_v27_value_sniper.py create mode 100644 mds/changelog-2026-04-22.md create mode 100644 src/modules/coupons/services/frequency-engine.service.ts diff --git a/ai-engine/catboost_info/catboost_training.json b/ai-engine/catboost_info/catboost_training.json new file mode 100644 index 0000000..be369ac --- /dev/null +++ b/ai-engine/catboost_info/catboost_training.json @@ -0,0 +1,874 @@ +{ +"meta":{"test_sets":["test"],"test_metrics":[{"best_value":"Min","name":"Logloss"}],"learn_metrics":[{"best_value":"Min","name":"Logloss"}],"launch_mode":"Train","parameters":"","iteration_count":2000,"learn_sets":["learn"],"name":"experiment"}, +"iterations":[ +{"learn":[0.692389481],"iteration":0,"passed_time":0.04679785798,"remaining_time":93.54891809,"test":[0.6924099937]}, +{"learn":[0.6916338586],"iteration":1,"passed_time":0.08350330552,"remaining_time":83.41980222,"test":[0.6916660956]}, +{"learn":[0.6910159214],"iteration":2,"passed_time":0.132821758,"remaining_time":88.41501689,"test":[0.691108145]}, +{"learn":[0.6903417151],"iteration":3,"passed_time":0.162826233,"remaining_time":81.25029026,"test":[0.6904585078]}, +{"learn":[0.6896961461],"iteration":4,"passed_time":0.1969265393,"remaining_time":78.57368918,"test":[0.689812816]}, +{"learn":[0.6890979366],"iteration":5,"passed_time":0.2309352918,"remaining_time":76.74749531,"test":[0.689192261]}, +{"learn":[0.6884946167],"iteration":6,"passed_time":0.2693987513,"remaining_time":76.70167304,"test":[0.6886032715]}, +{"learn":[0.6879503686],"iteration":7,"passed_time":0.3199759681,"remaining_time":79.67401607,"test":[0.6880706742]}, +{"learn":[0.6874528094],"iteration":8,"passed_time":0.3645802206,"remaining_time":80.65324659,"test":[0.6876192378]}, +{"learn":[0.6869036785],"iteration":9,"passed_time":0.4116507506,"remaining_time":81.91849936,"test":[0.6870868859]}, +{"learn":[0.6863761921],"iteration":10,"passed_time":0.4562469316,"remaining_time":82.49774064,"test":[0.6865493528]}, +{"learn":[0.6859038678],"iteration":11,"passed_time":0.491541699,"remaining_time":81.43207481,"test":[0.686105086]}, +{"learn":[0.685410175],"iteration":12,"passed_time":0.5221556769,"remaining_time":79.80948692,"test":[0.6856345086]}, +{"learn":[0.6849483392],"iteration":13,"passed_time":0.5553110353,"remaining_time":78.77483686,"test":[0.6852027185]}, +{"learn":[0.6845417792],"iteration":14,"passed_time":0.5952927147,"remaining_time":78.77706925,"test":[0.6848238481]}, +{"learn":[0.6841038875],"iteration":15,"passed_time":0.6300274185,"remaining_time":78.12339989,"test":[0.6844045699]}, +{"learn":[0.6836957422],"iteration":16,"passed_time":0.662600544,"remaining_time":77.29040464,"test":[0.6840077621]}, +{"learn":[0.6832947461],"iteration":17,"passed_time":0.7004221698,"remaining_time":77.12426337,"test":[0.6836197496]}, +{"learn":[0.6829014105],"iteration":18,"passed_time":0.7300844347,"remaining_time":76.12090869,"test":[0.6832475033]}, +{"learn":[0.6825264546],"iteration":19,"passed_time":0.7641559459,"remaining_time":75.65143865,"test":[0.6829012069]}, +{"learn":[0.6822106577],"iteration":20,"passed_time":0.8040792063,"remaining_time":75.77489282,"test":[0.6825880966]}, +{"learn":[0.6818649349],"iteration":21,"passed_time":0.8356039756,"remaining_time":75.12839381,"test":[0.6822424968]}, +{"learn":[0.6815467855],"iteration":22,"passed_time":0.8861440327,"remaining_time":76.16985881,"test":[0.6819180513]}, +{"learn":[0.6812293319],"iteration":23,"passed_time":0.920219319,"remaining_time":75.76472393,"test":[0.6816384467]}, +{"learn":[0.6808837443],"iteration":24,"passed_time":0.960164738,"remaining_time":75.8530143,"test":[0.6813262593]}, +{"learn":[0.6805816494],"iteration":25,"passed_time":0.9895547925,"remaining_time":75.13004463,"test":[0.6810353411]}, +{"learn":[0.6803209634],"iteration":26,"passed_time":1.025550161,"remaining_time":74.94112844,"test":[0.6808138172]}, +{"learn":[0.6800350862],"iteration":27,"passed_time":1.060852064,"remaining_time":74.71429535,"test":[0.6805550049]}, +{"learn":[0.6797703947],"iteration":28,"passed_time":1.10467538,"remaining_time":75.07983357,"test":[0.680347991]}, +{"learn":[0.6794926675],"iteration":29,"passed_time":1.141766834,"remaining_time":74.97602208,"test":[0.680089679]}, +{"learn":[0.6792251865],"iteration":30,"passed_time":1.180421588,"remaining_time":74.9758099,"test":[0.6798451919]}, +{"learn":[0.6789670166],"iteration":31,"passed_time":1.213674604,"remaining_time":74.64098814,"test":[0.6796090443]}, +{"learn":[0.678722402],"iteration":32,"passed_time":1.245848393,"remaining_time":74.26011482,"test":[0.6793890865]}, +{"learn":[0.678476935],"iteration":33,"passed_time":1.287262512,"remaining_time":74.43406171,"test":[0.6791683772]}, +{"learn":[0.6782297335],"iteration":34,"passed_time":1.327473991,"remaining_time":74.52818262,"test":[0.6789766369]}, +{"learn":[0.6780226701],"iteration":35,"passed_time":1.3760549,"remaining_time":75.07143955,"test":[0.6787930242]}, +{"learn":[0.6778291026],"iteration":36,"passed_time":1.427620019,"remaining_time":75.74102965,"test":[0.6786087714]}, +{"learn":[0.6776045324],"iteration":37,"passed_time":1.468182407,"remaining_time":75.80457587,"test":[0.6784161299]}, +{"learn":[0.6773969079],"iteration":38,"passed_time":1.508647379,"remaining_time":75.85788487,"test":[0.6782227897]}, +{"learn":[0.6771819602],"iteration":39,"passed_time":1.549435187,"remaining_time":75.92232419,"test":[0.6780242369]}, +{"learn":[0.6769816736],"iteration":40,"passed_time":1.586036608,"remaining_time":75.78160282,"test":[0.6778499631]}, +{"learn":[0.6767984027],"iteration":41,"passed_time":1.621458864,"remaining_time":75.59086802,"test":[0.6776975784]}, +{"learn":[0.6766201184],"iteration":42,"passed_time":1.663424818,"remaining_time":75.70517136,"test":[0.6775231674]}, +{"learn":[0.6764394377],"iteration":43,"passed_time":1.70110089,"remaining_time":75.62166686,"test":[0.6773582124]}, +{"learn":[0.6762698797],"iteration":44,"passed_time":1.739954496,"remaining_time":75.59135644,"test":[0.6772234666]}, +{"learn":[0.6760974263],"iteration":45,"passed_time":1.776461223,"remaining_time":75.46098325,"test":[0.6770659843]}, +{"learn":[0.6759245179],"iteration":46,"passed_time":1.819761638,"remaining_time":75.61690381,"test":[0.6769049529]}, +{"learn":[0.6757673909],"iteration":47,"passed_time":1.869479807,"remaining_time":76.02551217,"test":[0.6767664194]}, +{"learn":[0.6756172628],"iteration":48,"passed_time":1.916010121,"remaining_time":76.28848462,"test":[0.6766584917]}, +{"learn":[0.675474531],"iteration":49,"passed_time":1.953635244,"remaining_time":76.19177452,"test":[0.6765507257]}, +{"learn":[0.6753286933],"iteration":50,"passed_time":1.993876686,"remaining_time":76.19736591,"test":[0.6764489911]}, +{"learn":[0.6751900513],"iteration":51,"passed_time":2.038943041,"remaining_time":76.38194316,"test":[0.6763947956]}, +{"learn":[0.6750574835],"iteration":52,"passed_time":2.080276765,"remaining_time":76.42073325,"test":[0.6762778712]}, +{"learn":[0.6749329567],"iteration":53,"passed_time":2.158576742,"remaining_time":77.78871001,"test":[0.6761865366]}, +{"learn":[0.6748033265],"iteration":54,"passed_time":2.220619687,"remaining_time":78.52918711,"test":[0.6760679685]}, +{"learn":[0.6746797823],"iteration":55,"passed_time":2.286959228,"remaining_time":79.39015604,"test":[0.6759774874]}, +{"learn":[0.674535525],"iteration":56,"passed_time":2.328472096,"remaining_time":79.3723032,"test":[0.6758500622]}, +{"learn":[0.6744256514],"iteration":57,"passed_time":2.367031568,"remaining_time":79.25474665,"test":[0.6757625065]}, +{"learn":[0.674310819],"iteration":58,"passed_time":2.409161286,"remaining_time":79.25732298,"test":[0.6756876412]}, +{"learn":[0.6741967947],"iteration":59,"passed_time":2.444825903,"remaining_time":79.04937087,"test":[0.6756151069]}, +{"learn":[0.6740879654],"iteration":60,"passed_time":2.48484996,"remaining_time":78.98564055,"test":[0.6755303655]}, +{"learn":[0.6739772476],"iteration":61,"passed_time":2.521603395,"remaining_time":78.8204416,"test":[0.6754565036]}, +{"learn":[0.67388281],"iteration":62,"passed_time":2.554102332,"remaining_time":78.5285114,"test":[0.6753738983]}, +{"learn":[0.6737789726],"iteration":63,"passed_time":2.593937938,"remaining_time":78.46662263,"test":[0.6752897299]}, +{"learn":[0.6736812332],"iteration":64,"passed_time":2.623889155,"remaining_time":78.11116175,"test":[0.6752115539]}, +{"learn":[0.6735930009],"iteration":65,"passed_time":2.660795108,"remaining_time":77.96935967,"test":[0.6751595431]}, +{"learn":[0.6734947116],"iteration":66,"passed_time":2.695822592,"remaining_time":77.77649358,"test":[0.6750764658]}, +{"learn":[0.6733961481],"iteration":67,"passed_time":2.725876686,"remaining_time":77.44696703,"test":[0.6750179194]}, +{"learn":[0.6732990195],"iteration":68,"passed_time":2.761848366,"remaining_time":77.29172746,"test":[0.6749408803]}, +{"learn":[0.6732133575],"iteration":69,"passed_time":2.791847449,"remaining_time":76.97522253,"test":[0.6748795802]}, +{"learn":[0.673111539],"iteration":70,"passed_time":2.824541003,"remaining_time":76.73999429,"test":[0.674790372]}, +{"learn":[0.6730080451],"iteration":71,"passed_time":2.861023716,"remaining_time":76.61185729,"test":[0.6747239773]}, +{"learn":[0.6729157861],"iteration":72,"passed_time":2.897136588,"remaining_time":76.47646857,"test":[0.6746701254]}, +{"learn":[0.6728347949],"iteration":73,"passed_time":2.935718661,"remaining_time":76.40802894,"test":[0.6746120937]}, +{"learn":[0.6727640693],"iteration":74,"passed_time":3.040023476,"remaining_time":78.02726921,"test":[0.6745550085]}, +{"learn":[0.6726808811],"iteration":75,"passed_time":3.097341794,"remaining_time":78.41165279,"test":[0.6744855074]}, +{"learn":[0.6726029645],"iteration":76,"passed_time":3.152948955,"remaining_time":78.74182909,"test":[0.6744264172]}, +{"learn":[0.6725356026],"iteration":77,"passed_time":3.216126808,"remaining_time":79.24866314,"test":[0.674381715]}, +{"learn":[0.6724606887],"iteration":78,"passed_time":3.256861302,"remaining_time":79.19532355,"test":[0.6743331681]}, +{"learn":[0.6723849561],"iteration":79,"passed_time":3.305679851,"remaining_time":79.33631641,"test":[0.67428564]}, +{"learn":[0.6723050519],"iteration":80,"passed_time":3.348083566,"remaining_time":79.32064647,"test":[0.6742202413]}, +{"learn":[0.6722508802],"iteration":81,"passed_time":3.38129387,"remaining_time":79.08928832,"test":[0.6741620971]}, +{"learn":[0.6721773904],"iteration":82,"passed_time":3.41660066,"remaining_time":78.91112609,"test":[0.6741109453]}, +{"learn":[0.6721007598],"iteration":83,"passed_time":3.48099347,"remaining_time":79.39980344,"test":[0.6740556003]}, +{"learn":[0.6720353564],"iteration":84,"passed_time":3.535359896,"remaining_time":79.64957884,"test":[0.6740146772]}, +{"learn":[0.6719790902],"iteration":85,"passed_time":3.581806996,"remaining_time":79.71603012,"test":[0.673983295]}, +{"learn":[0.6719140024],"iteration":86,"passed_time":3.612293661,"remaining_time":79.42893993,"test":[0.6739595301]}, +{"learn":[0.6718573633],"iteration":87,"passed_time":3.644530261,"remaining_time":79.18570293,"test":[0.6739336659]}, +{"learn":[0.671795602],"iteration":88,"passed_time":3.67809653,"remaining_time":78.97575809,"test":[0.673890361]}, +{"learn":[0.6717369134],"iteration":89,"passed_time":3.712417516,"remaining_time":78.78574951,"test":[0.673863586]}, +{"learn":[0.6716711079],"iteration":90,"passed_time":3.743502971,"remaining_time":78.53128759,"test":[0.6738190616]}, +{"learn":[0.6716070843],"iteration":91,"passed_time":3.775351679,"remaining_time":78.2975109,"test":[0.6737799295]}, +{"learn":[0.6715517232],"iteration":92,"passed_time":3.806186247,"remaining_time":78.04728142,"test":[0.6737364374]}, +{"learn":[0.6714957378],"iteration":93,"passed_time":3.83798807,"remaining_time":77.82133257,"test":[0.6737093719]}, +{"learn":[0.6714364567],"iteration":94,"passed_time":3.871278973,"remaining_time":77.62933099,"test":[0.6736630475]}, +{"learn":[0.6713881758],"iteration":95,"passed_time":3.913531039,"remaining_time":77.6183656,"test":[0.67364367]}, +{"learn":[0.6713336502],"iteration":96,"passed_time":3.945433866,"remaining_time":77.40371802,"test":[0.6735998081]}, +{"learn":[0.6712700267],"iteration":97,"passed_time":3.989716281,"remaining_time":77.43306496,"test":[0.6735526984]}, +{"learn":[0.6712154424],"iteration":98,"passed_time":4.020621946,"remaining_time":77.20406384,"test":[0.6735012924]}, +{"learn":[0.6711600413],"iteration":99,"passed_time":4.053732144,"remaining_time":77.02091074,"test":[0.6734818024]}, +{"learn":[0.6711060533],"iteration":100,"passed_time":4.084124711,"remaining_time":76.78963194,"test":[0.6734379341]}, +{"learn":[0.6710494943],"iteration":101,"passed_time":4.116434744,"remaining_time":76.59797199,"test":[0.6734059869]}, +{"learn":[0.6709936897],"iteration":102,"passed_time":4.148330356,"remaining_time":76.40177365,"test":[0.6733740852]}, +{"learn":[0.6709472183],"iteration":103,"passed_time":4.176511193,"remaining_time":76.14101176,"test":[0.6733330971]}, +{"learn":[0.6708914508],"iteration":104,"passed_time":4.2025065,"remaining_time":75.84523636,"test":[0.6733060254]}, +{"learn":[0.6708388195],"iteration":105,"passed_time":4.232975206,"remaining_time":75.63448151,"test":[0.6732755898]}, +{"learn":[0.6707885854],"iteration":106,"passed_time":4.261364958,"remaining_time":75.39031649,"test":[0.6732294722]}, +{"learn":[0.6707454167],"iteration":107,"passed_time":4.290824713,"remaining_time":75.1688922,"test":[0.6732035176]}, +{"learn":[0.6706973013],"iteration":108,"passed_time":4.324192493,"remaining_time":75.01878903,"test":[0.673196437]}, +{"learn":[0.6706577031],"iteration":109,"passed_time":4.351512102,"remaining_time":74.76688976,"test":[0.6731652709]}, +{"learn":[0.67061108],"iteration":110,"passed_time":4.38641502,"remaining_time":74.64808984,"test":[0.673138808]}, +{"learn":[0.6705625485],"iteration":111,"passed_time":4.424063991,"remaining_time":74.57707871,"test":[0.6731062725]}, +{"learn":[0.6705146484],"iteration":112,"passed_time":4.45863849,"remaining_time":74.45531709,"test":[0.6730726625]}, +{"learn":[0.6704704423],"iteration":113,"passed_time":4.497153675,"remaining_time":74.40027922,"test":[0.6730285927]}, +{"learn":[0.6704155922],"iteration":114,"passed_time":4.533368584,"remaining_time":74.30782417,"test":[0.6729872702]}, +{"learn":[0.6703687117],"iteration":115,"passed_time":4.564651269,"remaining_time":74.13623268,"test":[0.6729721425]}, +{"learn":[0.6703324232],"iteration":116,"passed_time":4.596824343,"remaining_time":73.98136956,"test":[0.6729564624]}, +{"learn":[0.6702884624],"iteration":117,"passed_time":4.628377967,"remaining_time":73.81870623,"test":[0.6729312424]}, +{"learn":[0.670253478],"iteration":118,"passed_time":4.668052254,"remaining_time":73.78660748,"test":[0.6729354345]}, +{"learn":[0.6702140804],"iteration":119,"passed_time":4.692108266,"remaining_time":73.50969617,"test":[0.6729085401]}, +{"learn":[0.6701682529],"iteration":120,"passed_time":4.723741667,"remaining_time":73.354633,"test":[0.6728898322]}, +{"learn":[0.6701320588],"iteration":121,"passed_time":4.756626425,"remaining_time":73.22085595,"test":[0.6728773638]}, +{"learn":[0.6700939824],"iteration":122,"passed_time":4.788008428,"remaining_time":73.06578714,"test":[0.6728618874]}, +{"learn":[0.6700655902],"iteration":123,"passed_time":4.815546648,"remaining_time":72.85456058,"test":[0.6728540413]}, +{"learn":[0.6700190743],"iteration":124,"passed_time":4.843186806,"remaining_time":72.64780209,"test":[0.6728441291]}, +{"learn":[0.6699792296],"iteration":125,"passed_time":4.875548614,"remaining_time":72.51411192,"test":[0.672815631]}, +{"learn":[0.6699379404],"iteration":126,"passed_time":4.916953662,"remaining_time":72.51538748,"test":[0.6728082021]}, +{"learn":[0.669895454],"iteration":127,"passed_time":4.952918369,"remaining_time":72.43643115,"test":[0.6727900064]}, +{"learn":[0.6698563938],"iteration":128,"passed_time":4.991585558,"remaining_time":72.39733782,"test":[0.6727649552]}, +{"learn":[0.6698215571],"iteration":129,"passed_time":5.028084166,"remaining_time":72.32705685,"test":[0.6727467657]}, +{"learn":[0.6697857067],"iteration":130,"passed_time":5.059198996,"remaining_time":72.18048033,"test":[0.6727396032]}, +{"learn":[0.6697449303],"iteration":131,"passed_time":5.096035515,"remaining_time":72.1166238,"test":[0.6727245271]}, +{"learn":[0.6697052425],"iteration":132,"passed_time":5.125282589,"remaining_time":71.94663604,"test":[0.6726955143]}, +{"learn":[0.6696695553],"iteration":133,"passed_time":5.156392608,"remaining_time":71.80469109,"test":[0.67269209]}, +{"learn":[0.6696269265],"iteration":134,"passed_time":5.190402292,"remaining_time":71.70444647,"test":[0.672677932]}, +{"learn":[0.6695969271],"iteration":135,"passed_time":5.221466142,"remaining_time":71.56480065,"test":[0.6726540285]}, +{"learn":[0.6695489786],"iteration":136,"passed_time":5.251144663,"remaining_time":71.40790151,"test":[0.6726288583]}, +{"learn":[0.6695173859],"iteration":137,"passed_time":5.274361693,"remaining_time":71.16566285,"test":[0.6725863431]}, +{"learn":[0.6694811164],"iteration":138,"passed_time":5.309398952,"remaining_time":71.08483058,"test":[0.6725837967]}, +{"learn":[0.6694477439],"iteration":139,"passed_time":5.344693175,"remaining_time":71.00806646,"test":[0.6725772977]}, +{"learn":[0.6694082161],"iteration":140,"passed_time":5.377737126,"remaining_time":70.90222211,"test":[0.6725685594]}, +{"learn":[0.6693679185],"iteration":141,"passed_time":5.416087925,"remaining_time":70.8668406,"test":[0.6725553829]}, +{"learn":[0.6693341916],"iteration":142,"passed_time":5.452286939,"remaining_time":70.80347444,"test":[0.6725484347]}, +{"learn":[0.6692933159],"iteration":143,"passed_time":5.490006789,"remaining_time":70.7600875,"test":[0.6725306172]}, +{"learn":[0.6692619696],"iteration":144,"passed_time":5.521869859,"remaining_time":70.64185233,"test":[0.672543149]}, +{"learn":[0.6692229289],"iteration":145,"passed_time":5.553520721,"remaining_time":70.5221056,"test":[0.6725196247]}, +{"learn":[0.6691840164],"iteration":146,"passed_time":5.582178524,"remaining_time":70.3658286,"test":[0.6725226452]}, +{"learn":[0.6691581406],"iteration":147,"passed_time":5.611368671,"remaining_time":70.21793769,"test":[0.6725056913]}, +{"learn":[0.6691177196],"iteration":148,"passed_time":5.636941079,"remaining_time":70.02669757,"test":[0.6724771476]}, +{"learn":[0.6690851126],"iteration":149,"passed_time":5.673704689,"remaining_time":69.97569117,"test":[0.6724439435]}, +{"learn":[0.6690518144],"iteration":150,"passed_time":5.706346207,"remaining_time":69.87439826,"test":[0.672442532]}, +{"learn":[0.6690149711],"iteration":151,"passed_time":5.738210991,"remaining_time":69.76456521,"test":[0.6724303064]}, +{"learn":[0.668993877],"iteration":152,"passed_time":5.765951318,"remaining_time":69.60596133,"test":[0.6724235788]}, +{"learn":[0.6689596579],"iteration":153,"passed_time":5.795573467,"remaining_time":69.47161442,"test":[0.6724294499]}, +{"learn":[0.6689372651],"iteration":154,"passed_time":5.81744896,"remaining_time":69.24640858,"test":[0.6724285935]}, +{"learn":[0.6689003045],"iteration":155,"passed_time":5.853529431,"remaining_time":69.19171968,"test":[0.6724172017]}, +{"learn":[0.6688680182],"iteration":156,"passed_time":5.888380392,"remaining_time":69.12283479,"test":[0.6724130745]}, +{"learn":[0.6688348164],"iteration":157,"passed_time":5.924601775,"remaining_time":69.07035741,"test":[0.6723860878]}, +{"learn":[0.6687947046],"iteration":158,"passed_time":5.964531924,"remaining_time":69.06102687,"test":[0.6723707604]}, +{"learn":[0.6687605251],"iteration":159,"passed_time":5.996805452,"remaining_time":68.9632627,"test":[0.6723566111]}, +{"learn":[0.668726253],"iteration":160,"passed_time":6.022341459,"remaining_time":68.78935368,"test":[0.6723469906]}, +{"learn":[0.6686862718],"iteration":161,"passed_time":6.05082584,"remaining_time":68.65072774,"test":[0.6723287161]}, +{"learn":[0.668663478],"iteration":162,"passed_time":6.079027554,"remaining_time":68.51026759,"test":[0.6723155898]}, +{"learn":[0.6686399521],"iteration":163,"passed_time":6.108511297,"remaining_time":68.38552891,"test":[0.6722970834]}, +{"learn":[0.6686058279],"iteration":164,"passed_time":6.140719309,"remaining_time":68.29224202,"test":[0.6722872244]}, +{"learn":[0.6685761282],"iteration":165,"passed_time":6.169540017,"remaining_time":68.16226742,"test":[0.6722800481]}, +{"learn":[0.6685469327],"iteration":166,"passed_time":6.2020892,"remaining_time":68.07442817,"test":[0.6722550973]}, +{"learn":[0.6685157003],"iteration":167,"passed_time":6.231576547,"remaining_time":67.95385854,"test":[0.6722394313]}, +{"learn":[0.6684805143],"iteration":168,"passed_time":6.263261652,"remaining_time":67.85817802,"test":[0.6722204135]}, +{"learn":[0.6684485765],"iteration":169,"passed_time":6.295102833,"remaining_time":67.7649305,"test":[0.6721982148]}, +{"learn":[0.6684144429],"iteration":170,"passed_time":6.325415964,"remaining_time":67.65605729,"test":[0.6721971176]}, +{"learn":[0.6683849752],"iteration":171,"passed_time":6.35697084,"remaining_time":67.56129474,"test":[0.6721880705]}, +{"learn":[0.6683568537],"iteration":172,"passed_time":6.395913563,"remaining_time":67.5452837,"test":[0.672179176]}, +{"learn":[0.6683266628],"iteration":173,"passed_time":6.437330522,"remaining_time":67.55497433,"test":[0.6721769709]}, +{"learn":[0.6682937842],"iteration":174,"passed_time":6.472195712,"remaining_time":67.49575528,"test":[0.6721693215]}, +{"learn":[0.6682657097],"iteration":175,"passed_time":6.503044842,"remaining_time":67.395192,"test":[0.6721581386]}, +{"learn":[0.6682301443],"iteration":176,"passed_time":6.533528251,"remaining_time":67.29164972,"test":[0.6721638661]}, +{"learn":[0.6681995916],"iteration":177,"passed_time":6.562589882,"remaining_time":67.17437509,"test":[0.6721598475]}, +{"learn":[0.6681658267],"iteration":178,"passed_time":6.590816982,"remaining_time":67.04959623,"test":[0.6721433342]}, +{"learn":[0.6681422687],"iteration":179,"passed_time":6.624646227,"remaining_time":66.98253407,"test":[0.6721335599]}, +{"learn":[0.6681216601],"iteration":180,"passed_time":6.655147334,"remaining_time":66.88239227,"test":[0.6721300594]}, +{"learn":[0.6680899019],"iteration":181,"passed_time":6.687788902,"remaining_time":66.80439684,"test":[0.6721153533]}, +{"learn":[0.6680676394],"iteration":182,"passed_time":6.718057043,"remaining_time":66.7033314,"test":[0.6721076397]}, +{"learn":[0.6680413672],"iteration":183,"passed_time":6.751300957,"remaining_time":66.6324051,"test":[0.6721009911]}, +{"learn":[0.6680088406],"iteration":184,"passed_time":6.784288393,"remaining_time":66.55936991,"test":[0.6720999252]}, +{"learn":[0.6679873982],"iteration":185,"passed_time":6.810905309,"remaining_time":66.42463565,"test":[0.6720953028]}, +{"learn":[0.6679663544],"iteration":186,"passed_time":6.832974292,"remaining_time":66.24696466,"test":[0.6720942505]}, +{"learn":[0.6679417375],"iteration":187,"passed_time":6.867184511,"remaining_time":66.18796986,"test":[0.6720856237]}, +{"learn":[0.6679100197],"iteration":188,"passed_time":6.918652024,"remaining_time":66.29459691,"test":[0.6720876136]}, +{"learn":[0.667881208],"iteration":189,"passed_time":6.96948149,"remaining_time":66.39348156,"test":[0.6720880182]}, +{"learn":[0.6678475427],"iteration":190,"passed_time":7.018176318,"remaining_time":66.47058094,"test":[0.6720743856]}, +{"learn":[0.6678310341],"iteration":191,"passed_time":7.074099623,"remaining_time":66.61443812,"test":[0.6720598415]}, +{"learn":[0.6678060257],"iteration":192,"passed_time":7.117099742,"remaining_time":66.63522919,"test":[0.6720563492]}, +{"learn":[0.6677789336],"iteration":193,"passed_time":7.191058554,"remaining_time":66.94356571,"test":[0.6720389527]}, +{"learn":[0.6677478773],"iteration":194,"passed_time":7.2421897,"remaining_time":67.03667902,"test":[0.6720317324]}, +{"learn":[0.6677212408],"iteration":195,"passed_time":7.282401129,"remaining_time":67.02781447,"test":[0.672000736]}, +{"learn":[0.667704316],"iteration":196,"passed_time":7.317019235,"remaining_time":66.96744,"test":[0.6719895017]}, +{"learn":[0.6676819639],"iteration":197,"passed_time":7.351194179,"remaining_time":66.90329248,"test":[0.6719725302]}, +{"learn":[0.6676554448],"iteration":198,"passed_time":7.389840926,"remaining_time":66.87991712,"test":[0.6719770493]}, +{"learn":[0.6676318346],"iteration":199,"passed_time":7.432994652,"remaining_time":66.89695187,"test":[0.6719667172]}, +{"learn":[0.6676074705],"iteration":200,"passed_time":7.471295231,"remaining_time":66.86995085,"test":[0.6719511616]}, +{"learn":[0.6675849784],"iteration":201,"passed_time":7.506377837,"remaining_time":66.8141948,"test":[0.6719427289]}, +{"learn":[0.6675631744],"iteration":202,"passed_time":7.540821494,"remaining_time":66.75298633,"test":[0.6719299116]}, +{"learn":[0.6675397619],"iteration":203,"passed_time":7.56808212,"remaining_time":66.62880141,"test":[0.6719106583]}, +{"learn":[0.6675169086],"iteration":204,"passed_time":7.605676901,"remaining_time":66.59604896,"test":[0.6718967065]}, +{"learn":[0.6674864762],"iteration":205,"passed_time":7.638300222,"remaining_time":66.51995436,"test":[0.671890967]}, +{"learn":[0.6674670714],"iteration":206,"passed_time":7.665554951,"remaining_time":66.39777791,"test":[0.6718896293]}, +{"learn":[0.6674375599],"iteration":207,"passed_time":7.700277678,"remaining_time":66.34085384,"test":[0.6718883534]}, +{"learn":[0.6674148457],"iteration":208,"passed_time":7.734145802,"remaining_time":66.27681881,"test":[0.6718827289]}, +{"learn":[0.6673974446],"iteration":209,"passed_time":7.766232144,"remaining_time":66.19788351,"test":[0.6718763224]}, +{"learn":[0.6673812139],"iteration":210,"passed_time":7.796801222,"remaining_time":66.1065279,"test":[0.67187262]}, +{"learn":[0.6673515687],"iteration":211,"passed_time":7.831891449,"remaining_time":66.05387693,"test":[0.6718590402]}, +{"learn":[0.6673197956],"iteration":212,"passed_time":7.871259964,"remaining_time":66.0372843,"test":[0.6718455115]}, +{"learn":[0.6672900754],"iteration":213,"passed_time":7.910110502,"remaining_time":66.01615587,"test":[0.6718253747]}, +{"learn":[0.6672550009],"iteration":214,"passed_time":7.951342226,"remaining_time":66.01463197,"test":[0.671794877]}, +{"learn":[0.6672271563],"iteration":215,"passed_time":7.989001461,"remaining_time":65.98323429,"test":[0.6717873786]}, +{"learn":[0.667204521],"iteration":216,"passed_time":8.025973631,"remaining_time":65.94613357,"test":[0.6717765089]}, +{"learn":[0.667181968],"iteration":217,"passed_time":8.058434478,"remaining_time":65.87215707,"test":[0.6717616726]}, +{"learn":[0.6671640023],"iteration":218,"passed_time":8.087145957,"remaining_time":65.76806826,"test":[0.6717499215]}, +{"learn":[0.66714351],"iteration":219,"passed_time":8.112590578,"remaining_time":65.63823286,"test":[0.6717326052]}, +{"learn":[0.6671167156],"iteration":220,"passed_time":8.148644349,"remaining_time":65.59474342,"test":[0.6717161937]}, +{"learn":[0.6670915937],"iteration":221,"passed_time":8.197662625,"remaining_time":65.65515382,"test":[0.6717056951]}, +{"learn":[0.6670595279],"iteration":222,"passed_time":8.239228431,"remaining_time":65.65519696,"test":[0.6717021438]}, +{"learn":[0.667033994],"iteration":223,"passed_time":8.268371203,"remaining_time":65.55637168,"test":[0.6716868488]}, +{"learn":[0.6670008246],"iteration":224,"passed_time":8.298555216,"remaining_time":65.46638004,"test":[0.6716751909]}, +{"learn":[0.6669858319],"iteration":225,"passed_time":8.327401394,"remaining_time":65.36641625,"test":[0.671670116]}, +{"learn":[0.6669553964],"iteration":226,"passed_time":8.357648377,"remaining_time":65.27802014,"test":[0.6716558757]}, +{"learn":[0.6669274683],"iteration":227,"passed_time":8.384989701,"remaining_time":65.16755154,"test":[0.6716559962]}, +{"learn":[0.666896348],"iteration":228,"passed_time":8.418297538,"remaining_time":65.1039517,"test":[0.6716487875]}, +{"learn":[0.6668698686],"iteration":229,"passed_time":8.453919972,"remaining_time":65.05842761,"test":[0.6716427451]}, +{"learn":[0.6668513411],"iteration":230,"passed_time":8.49049033,"remaining_time":65.02024846,"test":[0.6716323255]}, +{"learn":[0.6668309985],"iteration":231,"passed_time":8.523986676,"remaining_time":64.95865708,"test":[0.6716303547]}, +{"learn":[0.6668058585],"iteration":232,"passed_time":8.550998228,"remaining_time":64.84812819,"test":[0.6716309509]}, +{"learn":[0.6667845908],"iteration":233,"passed_time":8.575382398,"remaining_time":64.71848425,"test":[0.6716215401]}, +{"learn":[0.6667582863],"iteration":234,"passed_time":8.607602961,"remaining_time":64.64859245,"test":[0.6716162103]}, +{"learn":[0.6667332943],"iteration":235,"passed_time":8.6353786,"remaining_time":64.54579597,"test":[0.6716135097]}, +{"learn":[0.6667070085],"iteration":236,"passed_time":8.66085309,"remaining_time":64.42651476,"test":[0.6716156696]}, +{"learn":[0.6666907315],"iteration":237,"passed_time":8.691362456,"remaining_time":64.34529684,"test":[0.6716020054]}, +{"learn":[0.6666633028],"iteration":238,"passed_time":8.719983169,"remaining_time":64.25058728,"test":[0.6715921704]}, +{"learn":[0.6666406707],"iteration":239,"passed_time":8.746012652,"remaining_time":64.13742611,"test":[0.6715804466]}, +{"learn":[0.6666134624],"iteration":240,"passed_time":8.773898765,"remaining_time":64.03853912,"test":[0.6715882966]}, +{"learn":[0.6665850522],"iteration":241,"passed_time":8.803292064,"remaining_time":63.9511878,"test":[0.6715753942]}, +{"learn":[0.6665631193],"iteration":242,"passed_time":8.833976809,"remaining_time":63.87365125,"test":[0.6715752261]}, +{"learn":[0.6665412643],"iteration":243,"passed_time":8.862338006,"remaining_time":63.7797768,"test":[0.6715625509]}, +{"learn":[0.6665168385],"iteration":244,"passed_time":8.892424073,"remaining_time":63.69879285,"test":[0.6715628214]}, +{"learn":[0.6664904845],"iteration":245,"passed_time":8.932383667,"remaining_time":63.68862175,"test":[0.6715601629]}, +{"learn":[0.6664678274],"iteration":246,"passed_time":8.962911123,"remaining_time":63.61126801,"test":[0.6715576255]}, +{"learn":[0.6664539777],"iteration":247,"passed_time":8.991624872,"remaining_time":63.52147894,"test":[0.6715550274]}, +{"learn":[0.6664334121],"iteration":248,"passed_time":9.021847081,"remaining_time":63.44278811,"test":[0.6715448645]}, +{"learn":[0.6664121724],"iteration":249,"passed_time":9.05121341,"remaining_time":63.35849387,"test":[0.6715308166]}, +{"learn":[0.666392034],"iteration":250,"passed_time":9.085113431,"remaining_time":63.30622865,"test":[0.671519334]}, +{"learn":[0.666366899],"iteration":251,"passed_time":9.110250512,"remaining_time":63.19332498,"test":[0.6715184071]}, +{"learn":[0.6663414098],"iteration":252,"passed_time":9.137253573,"remaining_time":63.09399997,"test":[0.6715163019]}, +{"learn":[0.6663157816],"iteration":253,"passed_time":9.174559864,"remaining_time":63.06606899,"test":[0.6715096094]}, +{"learn":[0.6662989799],"iteration":254,"passed_time":9.196898204,"remaining_time":62.93563673,"test":[0.6714992963]}, +{"learn":[0.6662696102],"iteration":255,"passed_time":9.238149902,"remaining_time":62.9348962,"test":[0.6714917256]}, +{"learn":[0.6662479711],"iteration":256,"passed_time":9.267818291,"remaining_time":62.85528125,"test":[0.671477406]}, +{"learn":[0.6662231874],"iteration":257,"passed_time":9.297538986,"remaining_time":62.77640665,"test":[0.6714741542]}, +{"learn":[0.6661947927],"iteration":258,"passed_time":9.324772701,"remaining_time":62.68119411,"test":[0.6714576155]}, +{"learn":[0.6661669951],"iteration":259,"passed_time":9.357824574,"remaining_time":62.62544138,"test":[0.6714473645]}, +{"learn":[0.6661426137],"iteration":260,"passed_time":9.388345461,"remaining_time":62.55299907,"test":[0.6714427232]}, +{"learn":[0.6661216749],"iteration":261,"passed_time":9.427290804,"remaining_time":62.53676114,"test":[0.6714364275]}, +{"learn":[0.6660983123],"iteration":262,"passed_time":9.461913185,"remaining_time":62.49179925,"test":[0.6714339587]}, +{"learn":[0.6660803402],"iteration":263,"passed_time":9.496090562,"remaining_time":62.44398945,"test":[0.6714336287]}, +{"learn":[0.6660617842],"iteration":264,"passed_time":9.524189317,"remaining_time":62.35648477,"test":[0.6714283568]}, +{"learn":[0.6660443878],"iteration":265,"passed_time":9.55372419,"remaining_time":62.27878852,"test":[0.6714271895]}, +{"learn":[0.6660176079],"iteration":266,"passed_time":9.590356068,"remaining_time":62.2475171,"test":[0.671413471]}, +{"learn":[0.6659967546],"iteration":267,"passed_time":9.620235131,"remaining_time":62.17256436,"test":[0.6714072396]}, +{"learn":[0.6659751467],"iteration":268,"passed_time":9.645948482,"remaining_time":62.0711406,"test":[0.6714002677]}, +{"learn":[0.6659539329],"iteration":269,"passed_time":9.682675077,"remaining_time":62.04084401,"test":[0.6714001163]}, +{"learn":[0.6659263951],"iteration":270,"passed_time":9.711914203,"remaining_time":61.96272936,"test":[0.6713933952]}, +{"learn":[0.6659038921],"iteration":271,"passed_time":9.739142426,"remaining_time":61.87219894,"test":[0.6713926761]}, +{"learn":[0.6658767418],"iteration":272,"passed_time":9.768751964,"remaining_time":61.79719649,"test":[0.6713836619]}, +{"learn":[0.6658510507],"iteration":273,"passed_time":9.804576737,"remaining_time":61.76167682,"test":[0.6713772112]}, +{"learn":[0.6658210119],"iteration":274,"passed_time":9.848653906,"remaining_time":61.77791996,"test":[0.6713603715]}, +{"learn":[0.6657963011],"iteration":275,"passed_time":9.88663261,"remaining_time":61.75563268,"test":[0.6713560246]}, +{"learn":[0.6657748552],"iteration":276,"passed_time":9.925808942,"remaining_time":61.74068161,"test":[0.6713837913]}, +{"learn":[0.6657490013],"iteration":277,"passed_time":9.965409489,"remaining_time":61.72818396,"test":[0.6713684274]}, +{"learn":[0.665732402],"iteration":278,"passed_time":9.99537326,"remaining_time":61.65604796,"test":[0.6713619356]}, +{"learn":[0.6657118786],"iteration":279,"passed_time":10.02216777,"remaining_time":61.5647449,"test":[0.6713584836]}, +{"learn":[0.665684467],"iteration":280,"passed_time":10.05593393,"remaining_time":61.51654955,"test":[0.6713673572]}, +{"learn":[0.6656584634],"iteration":281,"passed_time":10.08025153,"remaining_time":61.41089406,"test":[0.6713625568]}, +{"learn":[0.6656309991],"iteration":282,"passed_time":10.11102202,"remaining_time":61.34496401,"test":[0.6713542652]}, +{"learn":[0.6656073482],"iteration":283,"passed_time":10.14714598,"remaining_time":61.31162855,"test":[0.6713512017]}, +{"learn":[0.6655890957],"iteration":284,"passed_time":10.17528061,"remaining_time":61.23019734,"test":[0.671342038]}, +{"learn":[0.6655665563],"iteration":285,"passed_time":10.2021403,"remaining_time":61.14149818,"test":[0.6713279798]}, +{"learn":[0.6655452454],"iteration":286,"passed_time":10.23423432,"remaining_time":61.08447174,"test":[0.6713123285]}, +{"learn":[0.6655255286],"iteration":287,"passed_time":10.26481698,"remaining_time":61.0186343,"test":[0.6713035326]}, +{"learn":[0.6655053548],"iteration":288,"passed_time":10.29945844,"remaining_time":60.97707056,"test":[0.6713022203]}, +{"learn":[0.6654893396],"iteration":289,"passed_time":10.32366496,"remaining_time":60.87402441,"test":[0.671296041]}, +{"learn":[0.6654648912],"iteration":290,"passed_time":10.35344703,"remaining_time":60.80426453,"test":[0.6712829551]}, +{"learn":[0.6654442759],"iteration":291,"passed_time":10.3949915,"remaining_time":60.8035804,"test":[0.6712769751]}, +{"learn":[0.6654173127],"iteration":292,"passed_time":10.43148765,"remaining_time":60.77320621,"test":[0.6712702915]}, +{"learn":[0.6653914518],"iteration":293,"passed_time":10.47162738,"remaining_time":60.76393303,"test":[0.6712379343]}, +{"learn":[0.6653648946],"iteration":294,"passed_time":10.50360107,"remaining_time":60.70725362,"test":[0.6712192006]}, +{"learn":[0.665344141],"iteration":295,"passed_time":10.53460819,"remaining_time":60.64517686,"test":[0.6712074061]}, +{"learn":[0.6653140817],"iteration":296,"passed_time":10.57659448,"remaining_time":60.64626395,"test":[0.6711953324]}, +{"learn":[0.665295365],"iteration":297,"passed_time":10.61260262,"remaining_time":60.61291829,"test":[0.6711891001]}, +{"learn":[0.6652787488],"iteration":298,"passed_time":10.63910358,"remaining_time":60.52546889,"test":[0.6711870526]}, +{"learn":[0.6652502991],"iteration":299,"passed_time":10.6681867,"remaining_time":60.45305797,"test":[0.6711812809]}, +{"learn":[0.665231168],"iteration":300,"passed_time":10.70260503,"remaining_time":60.41104967,"test":[0.6711768946]}, +{"learn":[0.6652136682],"iteration":301,"passed_time":10.72952096,"remaining_time":60.32690925,"test":[0.6711845012]}, +{"learn":[0.6651903001],"iteration":302,"passed_time":10.76489952,"remaining_time":60.29054288,"test":[0.6711869636]}, +{"learn":[0.6651697153],"iteration":303,"passed_time":10.80197155,"remaining_time":60.26363073,"test":[0.671186884]}, +{"learn":[0.6651525958],"iteration":304,"passed_time":10.82922271,"remaining_time":60.18207375,"test":[0.6711890401]}, +{"learn":[0.6651322685],"iteration":305,"passed_time":10.8578399,"remaining_time":60.10843394,"test":[0.6711868603]}, +{"learn":[0.6651113828],"iteration":306,"passed_time":10.89228879,"remaining_time":60.06724727,"test":[0.6711900892]}, +{"learn":[0.6650886807],"iteration":307,"passed_time":10.93056436,"remaining_time":60.04712628,"test":[0.6711884242]}, +{"learn":[0.6650622251],"iteration":308,"passed_time":10.97231236,"remaining_time":60.04589061,"test":[0.6711837119]}, +{"learn":[0.6650429987],"iteration":309,"passed_time":11.00296848,"remaining_time":59.98392494,"test":[0.6711766645]}, +{"learn":[0.665015513],"iteration":310,"passed_time":11.03002276,"remaining_time":59.90259947,"test":[0.671172959]}, +{"learn":[0.6650019022],"iteration":311,"passed_time":11.05828865,"remaining_time":59.82817707,"test":[0.6711740433]}, +{"learn":[0.664979951],"iteration":312,"passed_time":11.09287745,"remaining_time":59.78812863,"test":[0.6711715069]}, +{"learn":[0.6649549638],"iteration":313,"passed_time":11.1177757,"remaining_time":59.69608229,"test":[0.6711589843]}, +{"learn":[0.6649340455],"iteration":314,"passed_time":11.14959087,"remaining_time":59.64146228,"test":[0.6711446402]}, +{"learn":[0.6649162445],"iteration":315,"passed_time":11.18718772,"remaining_time":59.61779784,"test":[0.6711415366]}, +{"learn":[0.6649048119],"iteration":316,"passed_time":11.21179073,"remaining_time":59.52505932,"test":[0.6711359351]}, +{"learn":[0.6648796463],"iteration":317,"passed_time":11.24311165,"remaining_time":59.46828238,"test":[0.671143361]}, +{"learn":[0.6648605481],"iteration":318,"passed_time":11.27486028,"remaining_time":59.41391889,"test":[0.6711353638]}, +{"learn":[0.6648429084],"iteration":319,"passed_time":11.30400807,"remaining_time":59.34604237,"test":[0.6711444387]}, +{"learn":[0.6648238121],"iteration":320,"passed_time":11.33488419,"remaining_time":59.28744721,"test":[0.6711487352]}, +{"learn":[0.6647969527],"iteration":321,"passed_time":11.36208838,"remaining_time":59.20988915,"test":[0.67114436]}, +{"learn":[0.6647854723],"iteration":322,"passed_time":11.39429642,"remaining_time":59.15862259,"test":[0.6711444722]}, +{"learn":[0.6647589304],"iteration":323,"passed_time":11.4363998,"remaining_time":59.15866068,"test":[0.6711325635]}, +{"learn":[0.6647429024],"iteration":324,"passed_time":11.47751019,"remaining_time":59.15332173,"test":[0.6711269403]}, +{"learn":[0.6647237508],"iteration":325,"passed_time":11.5136833,"remaining_time":59.12241054,"test":[0.6711154078]}, +{"learn":[0.6647059396],"iteration":326,"passed_time":11.54795566,"remaining_time":59.08174257,"test":[0.6711203043]}, +{"learn":[0.664686288],"iteration":327,"passed_time":11.57245915,"remaining_time":58.99131613,"test":[0.6711241333]}, +{"learn":[0.6646532527],"iteration":328,"passed_time":11.60790333,"remaining_time":58.95685857,"test":[0.6711213497]}, +{"learn":[0.6646306438],"iteration":329,"passed_time":11.63787346,"remaining_time":58.89469298,"test":[0.6711231641]}, +{"learn":[0.6646098516],"iteration":330,"passed_time":11.66805718,"remaining_time":58.83379887,"test":[0.6711049215]}, +{"learn":[0.6645858284],"iteration":331,"passed_time":11.70070223,"remaining_time":58.78545579,"test":[0.6711031963]}, +{"learn":[0.6645707188],"iteration":332,"passed_time":11.724753,"remaining_time":58.69418391,"test":[0.6710996314]}, +{"learn":[0.6645485788],"iteration":333,"passed_time":11.75795297,"remaining_time":58.64895104,"test":[0.6710867309]}, +{"learn":[0.6645305696],"iteration":334,"passed_time":11.78053066,"remaining_time":58.55099567,"test":[0.6710914578]}, +{"learn":[0.6645108881],"iteration":335,"passed_time":11.81570271,"remaining_time":58.51586106,"test":[0.6710929585]}, +{"learn":[0.6644923286],"iteration":336,"passed_time":11.8448851,"remaining_time":58.45116888,"test":[0.6710984779]}, +{"learn":[0.6644805222],"iteration":337,"passed_time":11.86964023,"remaining_time":58.36491734,"test":[0.6710923199]}, +{"learn":[0.6644572776],"iteration":338,"passed_time":11.90591446,"remaining_time":58.33546879,"test":[0.6710893917]}, +{"learn":[0.6644320741],"iteration":339,"passed_time":11.94145444,"remaining_time":58.30239521,"test":[0.6710923306]}, +{"learn":[0.6644115048],"iteration":340,"passed_time":11.98658051,"remaining_time":58.31594449,"test":[0.6710927901]}, +{"learn":[0.6643949013],"iteration":341,"passed_time":12.02038848,"remaining_time":58.27428098,"test":[0.6711092802]}, +{"learn":[0.6643619789],"iteration":342,"passed_time":12.06653941,"remaining_time":58.29229096,"test":[0.6711012995]}, +{"learn":[0.6643389502],"iteration":343,"passed_time":12.12283646,"remaining_time":58.35877087,"test":[0.6711015305]}, +{"learn":[0.6643088915],"iteration":344,"passed_time":12.17733618,"remaining_time":58.41591705,"test":[0.6710975574]}, +{"learn":[0.664286972],"iteration":345,"passed_time":12.22133732,"remaining_time":58.42223099,"test":[0.6710899474]}, +{"learn":[0.664274149],"iteration":346,"passed_time":12.2642467,"remaining_time":58.42305415,"test":[0.671085152]}, +{"learn":[0.6642536926],"iteration":347,"passed_time":12.30091895,"remaining_time":58.39401755,"test":[0.6710814533]}, +{"learn":[0.6642357634],"iteration":348,"passed_time":12.32484094,"remaining_time":58.30462002,"test":[0.6710701892]}, +{"learn":[0.664207914],"iteration":349,"passed_time":12.35469303,"remaining_time":58.24355287,"test":[0.67105503]}, +{"learn":[0.6641853097],"iteration":350,"passed_time":12.40148755,"remaining_time":58.26225919,"test":[0.6710527861]}, +{"learn":[0.6641654917],"iteration":351,"passed_time":12.43803877,"remaining_time":58.23263605,"test":[0.6710508715]}, +{"learn":[0.664143804],"iteration":352,"passed_time":12.47995438,"remaining_time":58.22800245,"test":[0.6710560803]}, +{"learn":[0.6641290647],"iteration":353,"passed_time":12.51241326,"remaining_time":58.17918707,"test":[0.6710465693]}, +{"learn":[0.6641117244],"iteration":354,"passed_time":12.5417829,"remaining_time":58.11614893,"test":[0.6710440741]}, +{"learn":[0.6640880219],"iteration":355,"passed_time":12.5692936,"remaining_time":58.0447154,"test":[0.6710496913]}, +{"learn":[0.6640669415],"iteration":356,"passed_time":12.5976392,"remaining_time":57.97737034,"test":[0.6710404659]}, +{"learn":[0.6640462999],"iteration":357,"passed_time":12.62815847,"remaining_time":57.92021287,"test":[0.6710293986]}, +{"learn":[0.664030296],"iteration":358,"passed_time":12.65342509,"remaining_time":57.8391938,"test":[0.6710353817]}, +{"learn":[0.6640028542],"iteration":359,"passed_time":12.68233453,"remaining_time":57.77507954,"test":[0.6710271815]}, +{"learn":[0.6639813347],"iteration":360,"passed_time":12.72037964,"remaining_time":57.75263774,"test":[0.6710288077]}, +{"learn":[0.6639597941],"iteration":361,"passed_time":12.744473,"remaining_time":57.66698004,"test":[0.6710169894]}, +{"learn":[0.6639429832],"iteration":362,"passed_time":12.77086568,"remaining_time":57.59203063,"test":[0.6710119848]}, +{"learn":[0.6639222708],"iteration":363,"passed_time":12.81194554,"remaining_time":57.58335961,"test":[0.6710114775]}, +{"learn":[0.6639065546],"iteration":364,"passed_time":12.84133287,"remaining_time":57.52213492,"test":[0.6710013614]}, +{"learn":[0.6638823236],"iteration":365,"passed_time":12.87057337,"remaining_time":57.46042866,"test":[0.6709985657]}, +{"learn":[0.6638648195],"iteration":366,"passed_time":12.8971183,"remaining_time":57.38690512,"test":[0.6709948954]}, +{"learn":[0.6638436235],"iteration":367,"passed_time":12.93825161,"remaining_time":57.37833324,"test":[0.6709970591]}, +{"learn":[0.6638208732],"iteration":368,"passed_time":12.97444296,"remaining_time":57.3477411,"test":[0.6709739289]}, +{"learn":[0.6637956357],"iteration":369,"passed_time":13.00974924,"remaining_time":57.31321963,"test":[0.6709754911]}, +{"learn":[0.6637718453],"iteration":370,"passed_time":13.03832239,"remaining_time":57.24912984,"test":[0.6709717066]}, +{"learn":[0.663756918],"iteration":371,"passed_time":13.07843077,"remaining_time":57.23571316,"test":[0.67096845]}, +{"learn":[0.6637353525],"iteration":372,"passed_time":13.11729124,"remaining_time":57.21671005,"test":[0.6709739445]}, +{"learn":[0.6637143112],"iteration":373,"passed_time":13.14745329,"remaining_time":57.15978354,"test":[0.6709728881]}, +{"learn":[0.6636956547],"iteration":374,"passed_time":13.18118022,"remaining_time":57.11844761,"test":[0.6709694284]}, +{"learn":[0.663680995],"iteration":375,"passed_time":13.20539229,"remaining_time":57.03605604,"test":[0.6709604166]}, +{"learn":[0.66366728],"iteration":376,"passed_time":13.23563977,"remaining_time":56.97995583,"test":[0.6709605025]}, +{"learn":[0.6636487567],"iteration":377,"passed_time":13.27428255,"remaining_time":56.96001665,"test":[0.6709603727]}, +{"learn":[0.6636266904],"iteration":378,"passed_time":13.30625754,"remaining_time":56.91146033,"test":[0.670944339]}, +{"learn":[0.6636116064],"iteration":379,"passed_time":13.33327871,"remaining_time":56.84187241,"test":[0.6709447187]}, +{"learn":[0.6635902746],"iteration":380,"passed_time":13.36632239,"remaining_time":56.79809961,"test":[0.6709538679]}, +{"learn":[0.6635654896],"iteration":381,"passed_time":13.39639051,"remaining_time":56.74177969,"test":[0.6709640912]}, +{"learn":[0.6635393029],"iteration":382,"passed_time":13.42189438,"remaining_time":56.66632694,"test":[0.6709534847]}, +{"learn":[0.6635171734],"iteration":383,"passed_time":13.46730432,"remaining_time":56.6749057,"test":[0.6709471555]}, +{"learn":[0.663500789],"iteration":384,"passed_time":13.50832777,"remaining_time":56.66480351,"test":[0.6709506783]}, +{"learn":[0.663477743],"iteration":385,"passed_time":13.54029627,"remaining_time":56.61667921,"test":[0.6709546729]}, +{"learn":[0.6634584806],"iteration":386,"passed_time":13.56996301,"remaining_time":56.5590448,"test":[0.670930774]}, +{"learn":[0.6634337499],"iteration":387,"passed_time":13.59835745,"remaining_time":56.4962686,"test":[0.6709287322]}, +{"learn":[0.6634135584],"iteration":388,"passed_time":13.6279617,"remaining_time":56.43867943,"test":[0.6709198643]}, +{"learn":[0.6633868455],"iteration":389,"passed_time":13.65633448,"remaining_time":56.37615005,"test":[0.6709220389]}, +{"learn":[0.6633755323],"iteration":390,"passed_time":13.68565529,"remaining_time":56.31769658,"test":[0.6709230923]}, +{"learn":[0.663356103],"iteration":391,"passed_time":13.71789303,"remaining_time":56.27135714,"test":[0.670930414]}, +{"learn":[0.6633337631],"iteration":392,"passed_time":13.75060752,"remaining_time":56.2270389,"test":[0.6709354296]}, +{"learn":[0.663319422],"iteration":393,"passed_time":13.77167974,"remaining_time":56.13532403,"test":[0.6709351544]}, +{"learn":[0.6632911566],"iteration":394,"passed_time":13.80416242,"remaining_time":56.09033084,"test":[0.6709414935]}, +{"learn":[0.6632687875],"iteration":395,"passed_time":13.82525369,"remaining_time":55.9992599,"test":[0.6709445943]}, +{"learn":[0.6632431997],"iteration":396,"passed_time":13.85836516,"remaining_time":55.95707646,"test":[0.6709475685]}, +{"learn":[0.6632189331],"iteration":397,"passed_time":13.88898168,"remaining_time":55.90489613,"test":[0.6709533591]}, +{"learn":[0.663201035],"iteration":398,"passed_time":13.91726355,"remaining_time":55.84345598,"test":[0.6709592222]}, +{"learn":[0.6631898553],"iteration":399,"passed_time":13.95316828,"remaining_time":55.81267311,"test":[0.6709508704]}, +{"learn":[0.6631712482],"iteration":400,"passed_time":13.99418497,"remaining_time":55.80224881,"test":[0.6709479912]}, +{"learn":[0.663143025],"iteration":401,"passed_time":14.0253575,"remaining_time":55.75254052,"test":[0.6709417519]}, +{"learn":[0.663121538],"iteration":402,"passed_time":14.04844239,"remaining_time":55.67087467,"test":[0.6709476082]}, +{"learn":[0.6631087792],"iteration":403,"passed_time":14.0761289,"remaining_time":55.60767753,"test":[0.6709480979]}, +{"learn":[0.6630859067],"iteration":404,"passed_time":14.10555105,"remaining_time":55.55149118,"test":[0.6709448724]}, +{"learn":[0.663066483],"iteration":405,"passed_time":14.1427661,"remaining_time":55.52603242,"test":[0.6709421934]}, +{"learn":[0.6630443652],"iteration":406,"passed_time":14.18285552,"remaining_time":55.51176619,"test":[0.6709386261]}, +{"learn":[0.6630250376],"iteration":407,"passed_time":14.21458769,"remaining_time":55.46476372,"test":[0.6709461564]}, +{"learn":[0.6630007822],"iteration":408,"passed_time":14.24035708,"remaining_time":55.39464088,"test":[0.670934384]}, +{"learn":[0.6629768728],"iteration":409,"passed_time":14.26711915,"remaining_time":55.32858403,"test":[0.6709312987]}, +{"learn":[0.6629528093],"iteration":410,"passed_time":14.29943785,"remaining_time":55.28420133,"test":[0.670931806]}, +{"learn":[0.6629260936],"iteration":411,"passed_time":14.32489173,"remaining_time":55.21341763,"test":[0.6709286111]}, +{"learn":[0.6629102182],"iteration":412,"passed_time":14.35119075,"remaining_time":55.14610101,"test":[0.6709224729]}, +{"learn":[0.6628863488],"iteration":413,"passed_time":14.37946054,"remaining_time":55.08653242,"test":[0.6709236504]}, +{"learn":[0.6628648972],"iteration":414,"passed_time":14.41005914,"remaining_time":55.03600899,"test":[0.6709245901]}, +{"learn":[0.6628454339],"iteration":415,"passed_time":14.45103793,"remaining_time":55.02510598,"test":[0.6709463437]}, +{"learn":[0.6628200274],"iteration":416,"passed_time":14.48428995,"remaining_time":54.98472661,"test":[0.6709567049]}, +{"learn":[0.6627942591],"iteration":417,"passed_time":14.5135184,"remaining_time":54.92915339,"test":[0.670945606]}, +{"learn":[0.6627744647],"iteration":418,"passed_time":14.53698524,"remaining_time":54.85196578,"test":[0.6709479298]}, +{"learn":[0.662765485],"iteration":419,"passed_time":14.56542473,"remaining_time":54.79374067,"test":[0.6709464351]}, +{"learn":[0.6627503257],"iteration":420,"passed_time":14.58728594,"remaining_time":54.71098455,"test":[0.6709414048]}, +{"learn":[0.6627323029],"iteration":421,"passed_time":14.61501375,"remaining_time":54.65045425,"test":[0.6709414427]}, +{"learn":[0.6627111509],"iteration":422,"passed_time":14.64231614,"remaining_time":54.58849302,"test":[0.6709296343]}, +{"learn":[0.6626785863],"iteration":423,"passed_time":14.66665432,"remaining_time":54.51567739,"test":[0.670924721]}, +{"learn":[0.6626576561],"iteration":424,"passed_time":14.69050441,"remaining_time":54.44128104,"test":[0.670906284]}, +{"learn":[0.6626363113],"iteration":425,"passed_time":14.71910475,"remaining_time":54.38467341,"test":[0.6708996826]}, +{"learn":[0.6626181065],"iteration":426,"passed_time":14.73941058,"remaining_time":54.2976413,"test":[0.6708987677]}, +{"learn":[0.66259794],"iteration":427,"passed_time":14.77242451,"remaining_time":54.25759657,"test":[0.670909526]}, +{"learn":[0.6625765658],"iteration":428,"passed_time":14.79088688,"remaining_time":54.1642967,"test":[0.6709033226]}, +{"learn":[0.6625526572],"iteration":429,"passed_time":14.82430966,"remaining_time":54.12596783,"test":[0.6708750209]}, +{"learn":[0.66253135],"iteration":430,"passed_time":14.84439175,"remaining_time":54.03909666,"test":[0.6708752079]}, +{"learn":[0.6625035695],"iteration":431,"passed_time":14.8764415,"remaining_time":53.99597284,"test":[0.6708776566]}, +{"learn":[0.662480212],"iteration":432,"passed_time":14.90666075,"remaining_time":53.94627573,"test":[0.6708736133]}, +{"learn":[0.6624611632],"iteration":433,"passed_time":14.93845927,"remaining_time":53.90236684,"test":[0.6708754298]}, +{"learn":[0.6624332625],"iteration":434,"passed_time":14.98024104,"remaining_time":53.89443041,"test":[0.6708751084]}, +{"learn":[0.6624120584],"iteration":435,"passed_time":15.00605075,"remaining_time":53.82904442,"test":[0.6708642042]}, +{"learn":[0.6623941719],"iteration":436,"passed_time":15.03384083,"remaining_time":53.77092268,"test":[0.6708610465]}, +{"learn":[0.6623766304],"iteration":437,"passed_time":15.05972545,"remaining_time":53.70614417,"test":[0.6708574768]}, +{"learn":[0.6623623329],"iteration":438,"passed_time":15.08505889,"remaining_time":53.63958297,"test":[0.6708557953]}, +{"learn":[0.6623442925],"iteration":439,"passed_time":15.11080547,"remaining_time":53.57467393,"test":[0.670871378]}, +{"learn":[0.6623212715],"iteration":440,"passed_time":15.13466304,"remaining_time":53.50326458,"test":[0.6708640187]}, +{"learn":[0.6623025941],"iteration":441,"passed_time":15.16037021,"remaining_time":53.43859001,"test":[0.6708700565]}, +{"learn":[0.6622749791],"iteration":442,"passed_time":15.18471062,"remaining_time":53.36928767,"test":[0.6708667534]}, +{"learn":[0.6622534499],"iteration":443,"passed_time":15.21140556,"remaining_time":53.30843931,"test":[0.6708675383]}, +{"learn":[0.6622305473],"iteration":444,"passed_time":15.23498219,"remaining_time":53.23684787,"test":[0.6708740175]}, +{"learn":[0.6622059333],"iteration":445,"passed_time":15.26647355,"remaining_time":53.19304911,"test":[0.6708774523]}, +{"learn":[0.6621871707],"iteration":446,"passed_time":15.28793136,"remaining_time":53.11444609,"test":[0.6708697231]}, +{"learn":[0.6621638454],"iteration":447,"passed_time":15.31613827,"remaining_time":53.05947899,"test":[0.6708614971]}, +{"learn":[0.6621511296],"iteration":448,"passed_time":15.33689091,"remaining_time":52.9788815,"test":[0.6708607946]}, +{"learn":[0.6621349978],"iteration":449,"passed_time":15.36674634,"remaining_time":52.92990406,"test":[0.6708740865]}, +{"learn":[0.6621120424],"iteration":450,"passed_time":15.393642,"remaining_time":52.87084582,"test":[0.6708729562]}, +{"learn":[0.6620958271],"iteration":451,"passed_time":15.42984657,"remaining_time":52.84381082,"test":[0.6708674017]}, +{"learn":[0.6620793528],"iteration":452,"passed_time":15.46956188,"remaining_time":52.82872456,"test":[0.6708693088]}, +{"learn":[0.6620572713],"iteration":453,"passed_time":15.49032259,"remaining_time":52.74898396,"test":[0.6708712037]}, +{"learn":[0.6620395025],"iteration":454,"passed_time":15.52379393,"remaining_time":52.71266289,"test":[0.6708703905]}, +{"learn":[0.6620188044],"iteration":455,"passed_time":15.55053135,"remaining_time":52.65355352,"test":[0.6708577595]}, +{"learn":[0.6620017347],"iteration":456,"passed_time":15.57735398,"remaining_time":52.59487352,"test":[0.6708493546]}, +{"learn":[0.6619811454],"iteration":457,"passed_time":15.60434803,"remaining_time":52.53690973,"test":[0.6708523777]}, +{"learn":[0.6619695569],"iteration":458,"passed_time":15.63056555,"remaining_time":52.47647387,"test":[0.6708454134]}, +{"learn":[0.661952377],"iteration":459,"passed_time":15.656355,"remaining_time":52.41475368,"test":[0.6708404483]}, +{"learn":[0.6619237442],"iteration":460,"passed_time":15.68232112,"remaining_time":52.35377918,"test":[0.6708274771]}, +{"learn":[0.6619089407],"iteration":461,"passed_time":15.71164945,"remaining_time":52.30414904,"test":[0.6708244992]}, +{"learn":[0.6618886168],"iteration":462,"passed_time":15.7361944,"remaining_time":52.23872743,"test":[0.6708344314]}, +{"learn":[0.6618831383],"iteration":463,"passed_time":15.76527735,"remaining_time":52.18850433,"test":[0.6708279081]}, +{"learn":[0.6618690774],"iteration":464,"passed_time":15.78652262,"remaining_time":52.11249942,"test":[0.6708258106]}, +{"learn":[0.661845878],"iteration":465,"passed_time":15.81756836,"remaining_time":52.06899113,"test":[0.6708049714]}, +{"learn":[0.6618290213],"iteration":466,"passed_time":15.83979966,"remaining_time":51.99660146,"test":[0.670810989]}, +{"learn":[0.6618050064],"iteration":467,"passed_time":15.87342473,"remaining_time":51.9617237,"test":[0.6708212237]}, +{"learn":[0.6617832833],"iteration":468,"passed_time":15.90381555,"remaining_time":51.9162934,"test":[0.6708221741]}, +{"learn":[0.6617652311],"iteration":469,"passed_time":15.93502938,"remaining_time":51.87360627,"test":[0.6708259658]}, +{"learn":[0.6617443144],"iteration":470,"passed_time":15.96919221,"remaining_time":51.84054117,"test":[0.6708159692]}, +{"learn":[0.6617202619],"iteration":471,"passed_time":15.99477329,"remaining_time":51.77968981,"test":[0.6708136212]}, +{"learn":[0.6617005831],"iteration":472,"passed_time":16.02279091,"remaining_time":51.72685354,"test":[0.6708224942]}, +{"learn":[0.6616824419],"iteration":473,"passed_time":16.04763422,"remaining_time":51.66390258,"test":[0.6708363084]}, +{"learn":[0.6616538226],"iteration":474,"passed_time":16.07374645,"remaining_time":51.60518598,"test":[0.670850875]}, +{"learn":[0.6616314155],"iteration":475,"passed_time":16.09993591,"remaining_time":51.54685363,"test":[0.6708527236]}, +{"learn":[0.6616127861],"iteration":476,"passed_time":16.12811357,"remaining_time":51.49500411,"test":[0.6708453401]}, +{"learn":[0.6616029072],"iteration":477,"passed_time":16.15264086,"remaining_time":51.43163051,"test":[0.6708413844]}, +{"learn":[0.6615843751],"iteration":478,"passed_time":16.17696751,"remaining_time":51.36778201,"test":[0.6708364569]}, +{"learn":[0.661563216],"iteration":479,"passed_time":16.20551145,"remaining_time":51.31745293,"test":[0.6708251774]}, +{"learn":[0.6615432257],"iteration":480,"passed_time":16.22860577,"remaining_time":51.2500045,"test":[0.6708154393]}, +{"learn":[0.6615263324],"iteration":481,"passed_time":16.25544093,"remaining_time":51.19452144,"test":[0.6708111613]}, +{"learn":[0.6615033259],"iteration":482,"passed_time":16.27729221,"remaining_time":51.12350369,"test":[0.6708102339]}, +{"learn":[0.661484293],"iteration":483,"passed_time":16.30502335,"remaining_time":51.07110619,"test":[0.6707929623]}, +{"learn":[0.6614678231],"iteration":484,"passed_time":16.32842702,"remaining_time":51.00529266,"test":[0.6707900226]}, +{"learn":[0.6614463024],"iteration":485,"passed_time":16.36272839,"remaining_time":50.97360242,"test":[0.6707832384]}, +{"learn":[0.6614155436],"iteration":486,"passed_time":16.39272506,"remaining_time":50.92852776,"test":[0.6707739118]}, +{"learn":[0.6613958945],"iteration":487,"passed_time":16.42636604,"remaining_time":50.89480625,"test":[0.6707737538]}, +{"learn":[0.661380611],"iteration":488,"passed_time":16.4597142,"remaining_time":50.86018027,"test":[0.6707730234]}, +{"learn":[0.6613677802],"iteration":489,"passed_time":16.48056007,"remaining_time":50.78703206,"test":[0.6707796291]}, +{"learn":[0.6613530086],"iteration":490,"passed_time":16.51091177,"remaining_time":50.74331132,"test":[0.670791408]}, +{"learn":[0.6613248211],"iteration":491,"passed_time":16.53097438,"remaining_time":50.66810846,"test":[0.6707944906]}, +{"learn":[0.6613059359],"iteration":492,"passed_time":16.56161402,"remaining_time":50.62546112,"test":[0.6707835635]}, +{"learn":[0.6612729965],"iteration":493,"passed_time":16.5854633,"remaining_time":50.56216139,"test":[0.6707908928]}, +{"learn":[0.6612624948],"iteration":494,"passed_time":16.61302735,"remaining_time":50.51031547,"test":[0.670796262]}, +{"learn":[0.6612401679],"iteration":495,"passed_time":16.63896978,"remaining_time":50.45365029,"test":[0.6707877825]}, +{"learn":[0.6612191637],"iteration":496,"passed_time":16.663707,"remaining_time":50.39346403,"test":[0.6707854132]}, +{"learn":[0.6611912219],"iteration":497,"passed_time":16.69040179,"remaining_time":50.33932428,"test":[0.6707756206]}, +{"learn":[0.6611773017],"iteration":498,"passed_time":16.71612789,"remaining_time":50.28238068,"test":[0.6707707899]}, +{"learn":[0.6611638216],"iteration":499,"passed_time":16.74072553,"remaining_time":50.2221766,"test":[0.6707704386]}, +{"learn":[0.6611450533],"iteration":500,"passed_time":16.77346538,"remaining_time":50.18647626,"test":[0.6707621465]}, +{"learn":[0.6611179111],"iteration":501,"passed_time":16.80230735,"remaining_time":50.13915621,"test":[0.6707661931]}, +{"learn":[0.6610959069],"iteration":502,"passed_time":16.83637769,"remaining_time":50.10747,"test":[0.6707651988]}, +{"learn":[0.6610728788],"iteration":503,"passed_time":16.87382128,"remaining_time":50.08578697,"test":[0.6707607827]}, +{"learn":[0.6610436668],"iteration":504,"passed_time":16.92151611,"remaining_time":50.09438927,"test":[0.670760242]}, +{"learn":[0.6610188976],"iteration":505,"passed_time":16.9898618,"remaining_time":50.16374216,"test":[0.6707506008]}, +{"learn":[0.6610030555],"iteration":506,"passed_time":17.03818668,"remaining_time":50.17359509,"test":[0.6707452886]}, +{"learn":[0.6609831174],"iteration":507,"passed_time":17.06933058,"remaining_time":50.13275833,"test":[0.6707355189]}, +{"learn":[0.6609586562],"iteration":508,"passed_time":17.1106164,"remaining_time":50.12166807,"test":[0.6707312551]}, +{"learn":[0.660935882],"iteration":509,"passed_time":17.14537899,"remaining_time":50.09140137,"test":[0.6707199485]}, +{"learn":[0.6609202024],"iteration":510,"passed_time":17.19066307,"remaining_time":50.09177556,"test":[0.6707131947]}, +{"learn":[0.6609011137],"iteration":511,"passed_time":17.21958034,"remaining_time":50.04440537,"test":[0.6707154112]}, +{"learn":[0.6608726737],"iteration":512,"passed_time":17.24756917,"remaining_time":49.99441591,"test":[0.6706982346]}, +{"learn":[0.6608608849],"iteration":513,"passed_time":17.27150822,"remaining_time":49.93280391,"test":[0.6706988941]}, +{"learn":[0.6608387256],"iteration":514,"passed_time":17.29800365,"remaining_time":49.87870957,"test":[0.6706989098]}, +{"learn":[0.6608136063],"iteration":515,"passed_time":17.34332283,"remaining_time":49.87885868,"test":[0.670693306]}, +{"learn":[0.6607946343],"iteration":516,"passed_time":17.37393636,"remaining_time":49.83664916,"test":[0.6706944515]}, +{"learn":[0.6607703935],"iteration":517,"passed_time":17.4173655,"remaining_time":49.83114994,"test":[0.6706899688]}, +{"learn":[0.6607509625],"iteration":518,"passed_time":17.46008645,"remaining_time":49.82348368,"test":[0.6706909374]}, +{"learn":[0.6607238109],"iteration":519,"passed_time":17.4906988,"remaining_time":49.78121967,"test":[0.6706855074]}, +{"learn":[0.6606999858],"iteration":520,"passed_time":17.5186435,"remaining_time":49.7314275,"test":[0.6706787779]}, +{"learn":[0.6606813873],"iteration":521,"passed_time":17.54613056,"remaining_time":49.6804233,"test":[0.6706737082]}, +{"learn":[0.6606610372],"iteration":522,"passed_time":17.57100039,"remaining_time":49.62211774,"test":[0.6706761225]}, +{"learn":[0.660638456],"iteration":523,"passed_time":17.60084283,"remaining_time":49.5779466,"test":[0.670685455]}, +{"learn":[0.6606156483],"iteration":524,"passed_time":17.62599925,"remaining_time":49.52066456,"test":[0.6706693855]}, +{"learn":[0.6605968623],"iteration":525,"passed_time":17.65519625,"remaining_time":49.47482751,"test":[0.6706647216]}, +{"learn":[0.6605735776],"iteration":526,"passed_time":17.67910836,"remaining_time":49.41428199,"test":[0.6706569188]}, +{"learn":[0.6605517294],"iteration":527,"passed_time":17.70744827,"remaining_time":49.36621942,"test":[0.6706549134]}, +{"learn":[0.6605309239],"iteration":528,"passed_time":17.72943083,"remaining_time":49.3005534,"test":[0.6706547978]}, +{"learn":[0.6605086434],"iteration":529,"passed_time":17.75830336,"remaining_time":49.25416215,"test":[0.6706564214]}, +{"learn":[0.6604803349],"iteration":530,"passed_time":17.78141858,"remaining_time":49.19190939,"test":[0.6706559196]}, +{"learn":[0.6604566326],"iteration":531,"passed_time":17.80870208,"remaining_time":49.14130574,"test":[0.6706515072]}, +{"learn":[0.6604430839],"iteration":532,"passed_time":17.82904188,"remaining_time":49.07167811,"test":[0.6706474616]}, +{"learn":[0.6604273738],"iteration":533,"passed_time":17.86246645,"remaining_time":49.03815696,"test":[0.6706424204]}, +{"learn":[0.6604048016],"iteration":534,"passed_time":17.90552779,"remaining_time":49.03102469,"test":[0.6706520008]}, +{"learn":[0.6603845173],"iteration":535,"passed_time":18.02843143,"remaining_time":49.24183511,"test":[0.6706448306]}, +{"learn":[0.6603669212],"iteration":536,"passed_time":18.07245966,"remaining_time":49.23651485,"test":[0.6706415789]}, +{"learn":[0.6603488983],"iteration":537,"passed_time":18.10631942,"remaining_time":49.20341819,"test":[0.6706305359]}, +{"learn":[0.6603176881],"iteration":538,"passed_time":18.13531438,"remaining_time":49.1571323,"test":[0.6706152774]}, +{"learn":[0.6602953862],"iteration":539,"passed_time":18.16575265,"remaining_time":49.11481272,"test":[0.670616585]}, +{"learn":[0.6602672025],"iteration":540,"passed_time":18.20025584,"remaining_time":49.08349958,"test":[0.6705963243]}, +{"learn":[0.6602568636],"iteration":541,"passed_time":18.22381751,"remaining_time":49.02274158,"test":[0.6706027368]}, +{"learn":[0.660235705],"iteration":542,"passed_time":18.25438575,"remaining_time":48.98092088,"test":[0.6706003522]}, +{"learn":[0.6602152295],"iteration":543,"passed_time":18.28070524,"remaining_time":48.9277699,"test":[0.6706044301]}, +{"learn":[0.6601897709],"iteration":544,"passed_time":18.30768805,"remaining_time":48.87648827,"test":[0.6706047241]}, +{"learn":[0.6601683731],"iteration":545,"passed_time":18.33807201,"remaining_time":48.83435294,"test":[0.6706038235]}, +{"learn":[0.6601472267],"iteration":546,"passed_time":18.36776304,"remaining_time":48.79041993,"test":[0.6706026913]}, +{"learn":[0.6601262337],"iteration":547,"passed_time":18.41134623,"remaining_time":48.78334803,"test":[0.6705845786]}, +{"learn":[0.6601119991],"iteration":548,"passed_time":18.44405381,"remaining_time":48.74739905,"test":[0.6705873967]}, +{"learn":[0.6600869973],"iteration":549,"passed_time":18.47010718,"remaining_time":48.69391893,"test":[0.6705755426]}, +{"learn":[0.6600667497],"iteration":550,"passed_time":18.5036553,"remaining_time":48.66024779,"test":[0.6705715731]}, +{"learn":[0.6600397508],"iteration":551,"passed_time":18.53164471,"remaining_time":48.61199556,"test":[0.6705757153]}, +{"learn":[0.660016863],"iteration":552,"passed_time":18.5577607,"remaining_time":48.55891452,"test":[0.6705516814]}, +{"learn":[0.6599933158],"iteration":553,"passed_time":18.58492994,"remaining_time":48.50867995,"test":[0.6705530864]}, +{"learn":[0.6599632649],"iteration":554,"passed_time":18.62562092,"remaining_time":48.49373376,"test":[0.6705552479]}, +{"learn":[0.6599446007],"iteration":555,"passed_time":18.65010209,"remaining_time":48.43659608,"test":[0.6705563336]}, +{"learn":[0.6599138126],"iteration":556,"passed_time":18.67796421,"remaining_time":48.38833458,"test":[0.6705718544]}, +{"learn":[0.6598965504],"iteration":557,"passed_time":18.70319381,"remaining_time":48.33334314,"test":[0.6705688384]}, +{"learn":[0.6598785723],"iteration":558,"passed_time":18.72995694,"remaining_time":48.28241136,"test":[0.6705641528]}, +{"learn":[0.659860838],"iteration":559,"passed_time":18.75657945,"remaining_time":48.23120429,"test":[0.6705628467]}, +{"learn":[0.6598408724],"iteration":560,"passed_time":18.78181322,"remaining_time":48.17652269,"test":[0.670558488]}, +{"learn":[0.6598244857],"iteration":561,"passed_time":18.80867415,"remaining_time":48.12610931,"test":[0.6705544404]}, +{"learn":[0.6598082469],"iteration":562,"passed_time":18.83488797,"remaining_time":48.0741279,"test":[0.6705617451]}, +{"learn":[0.6597851673],"iteration":563,"passed_time":18.86939449,"remaining_time":48.04335193,"test":[0.6705631717]}, +{"learn":[0.6597683521],"iteration":564,"passed_time":18.90235988,"remaining_time":48.00864854,"test":[0.6705636201]}, +{"learn":[0.6597479006],"iteration":565,"passed_time":18.93001053,"remaining_time":47.96048604,"test":[0.6705537522]}, +{"learn":[0.6597310938],"iteration":566,"passed_time":18.95858079,"remaining_time":47.91472006,"test":[0.670555083]}, +{"learn":[0.6597096581],"iteration":567,"passed_time":18.9833487,"remaining_time":47.85942842,"test":[0.6705524541]}, +{"learn":[0.6596862311],"iteration":568,"passed_time":19.0162481,"remaining_time":47.82469425,"test":[0.6705503132]}, +{"learn":[0.6596574779],"iteration":569,"passed_time":19.03781666,"remaining_time":47.76154004,"test":[0.6705354602]}, +{"learn":[0.6596385418],"iteration":570,"passed_time":19.0681355,"remaining_time":47.72043018,"test":[0.6705387012]}, +{"learn":[0.6596189903],"iteration":571,"passed_time":19.09073714,"remaining_time":47.66009201,"test":[0.6705411923]}, +{"learn":[0.65959275],"iteration":572,"passed_time":19.11146842,"remaining_time":47.59522765,"test":[0.6705390018]}, +{"learn":[0.6595730662],"iteration":573,"passed_time":19.141368,"remaining_time":47.55329403,"test":[0.6705354939]}, +{"learn":[0.6595566809],"iteration":574,"passed_time":19.16428373,"remaining_time":47.49409447,"test":[0.670531296]}, +{"learn":[0.6595365076],"iteration":575,"passed_time":19.19652276,"remaining_time":47.45807015,"test":[0.6705377163]}, +{"learn":[0.6595163446],"iteration":576,"passed_time":19.21727405,"remaining_time":47.39372785,"test":[0.6705248875]}, +{"learn":[0.6594816637],"iteration":577,"passed_time":19.24969594,"remaining_time":47.35824848,"test":[0.6705252902]}, +{"learn":[0.6594570142],"iteration":578,"passed_time":19.27445137,"remaining_time":47.30396442,"test":[0.6705181562]}, +{"learn":[0.6594353055],"iteration":579,"passed_time":19.29822455,"remaining_time":47.24737734,"test":[0.6705123446]}, +{"learn":[0.6594162362],"iteration":580,"passed_time":19.32403522,"remaining_time":47.19587948,"test":[0.6705128345]}, +{"learn":[0.659395036],"iteration":581,"passed_time":19.35739555,"remaining_time":47.16286408,"test":[0.6705173712]}, +{"learn":[0.6593798831],"iteration":582,"passed_time":19.39112791,"remaining_time":47.13075172,"test":[0.670541941]}, +{"learn":[0.6593556719],"iteration":583,"passed_time":19.42704318,"remaining_time":47.1039266,"test":[0.6705463243]}, +{"learn":[0.6593292627],"iteration":584,"passed_time":19.46022169,"remaining_time":47.07045077,"test":[0.6705513215]}, +{"learn":[0.6592976737],"iteration":585,"passed_time":19.48332075,"remaining_time":47.01265452,"test":[0.6705455889]}, +{"learn":[0.6592754841],"iteration":586,"passed_time":19.5115578,"remaining_time":46.9673444,"test":[0.6705408087]}, +{"learn":[0.6592510441],"iteration":587,"passed_time":19.54275193,"remaining_time":46.92919341,"test":[0.6705510193]}, +{"learn":[0.6592290326],"iteration":588,"passed_time":19.56411389,"remaining_time":46.86751222,"test":[0.6705456751]}, +{"learn":[0.6592097404],"iteration":589,"passed_time":19.59700884,"remaining_time":46.8335296,"test":[0.6705402427]}, +{"learn":[0.6591876204],"iteration":590,"passed_time":19.62169623,"remaining_time":46.77998306,"test":[0.6705443402]}, +{"learn":[0.6591705995],"iteration":591,"passed_time":19.64747626,"remaining_time":46.72913272,"test":[0.67054441]}, +{"learn":[0.6591456195],"iteration":592,"passed_time":19.67090184,"remaining_time":46.67278059,"test":[0.6705441955]}, +{"learn":[0.6591107122],"iteration":593,"passed_time":19.69910949,"remaining_time":46.62785848,"test":[0.6705319356]}, +{"learn":[0.6590819533],"iteration":594,"passed_time":19.72694709,"remaining_time":46.58211876,"test":[0.6705358843]}, +{"learn":[0.6590551327],"iteration":595,"passed_time":19.7530808,"remaining_time":46.53242523,"test":[0.6705334396]}, +{"learn":[0.6590373916],"iteration":596,"passed_time":19.77835609,"remaining_time":46.48079328,"test":[0.6705320462]}, +{"learn":[0.6590177149],"iteration":597,"passed_time":19.80378809,"remaining_time":46.4296169,"test":[0.6705332043]}, +{"learn":[0.6589946095],"iteration":598,"passed_time":19.83052585,"remaining_time":46.38158048,"test":[0.6705328363]}, +{"learn":[0.6589697628],"iteration":599,"passed_time":19.8579153,"remaining_time":46.33513569,"test":[0.6705315638]}, +{"learn":[0.6589442269],"iteration":600,"passed_time":19.89600309,"remaining_time":46.31365777,"test":[0.6705274435]}, +{"learn":[0.6589182437],"iteration":601,"passed_time":19.92518872,"remaining_time":46.27145155,"test":[0.670509808]}, +{"learn":[0.6588837179],"iteration":602,"passed_time":19.95754179,"remaining_time":46.23662666,"test":[0.6705077789]}, +{"learn":[0.6588674101],"iteration":603,"passed_time":19.99116426,"remaining_time":46.20474388,"test":[0.6705212132]}, +{"learn":[0.6588406916],"iteration":604,"passed_time":20.01900069,"remaining_time":46.15951398,"test":[0.6705098442]}, +{"learn":[0.6588149945],"iteration":605,"passed_time":20.04735837,"remaining_time":46.11554053,"test":[0.6705061509]}, +{"learn":[0.6587866031],"iteration":606,"passed_time":20.07232044,"remaining_time":46.06382599,"test":[0.6705003071]}, +{"learn":[0.6587636648],"iteration":607,"passed_time":20.09871086,"remaining_time":46.01546959,"test":[0.6705045031]}, +{"learn":[0.6587502469],"iteration":608,"passed_time":20.12348304,"remaining_time":45.96348917,"test":[0.6705083194]}, +{"learn":[0.6587292784],"iteration":609,"passed_time":20.14920752,"remaining_time":45.91376797,"test":[0.6705329997]}, +{"learn":[0.6587104112],"iteration":610,"passed_time":20.17662353,"remaining_time":45.86797068,"test":[0.6705269987]}, +{"learn":[0.6586953782],"iteration":611,"passed_time":20.20202219,"remaining_time":45.81765818,"test":[0.6705315607]}, +{"learn":[0.6586641191],"iteration":612,"passed_time":20.23050051,"remaining_time":45.77439512,"test":[0.6705142835]}, +{"learn":[0.6586450136],"iteration":613,"passed_time":20.25381994,"remaining_time":45.71953492,"test":[0.6705165015]}, +{"learn":[0.6586136263],"iteration":614,"passed_time":20.28518384,"remaining_time":45.68289369,"test":[0.6705001061]}, +{"learn":[0.6585862768],"iteration":615,"passed_time":20.3078175,"remaining_time":45.62665489,"test":[0.6705013916]}, +{"learn":[0.6585585235],"iteration":616,"passed_time":20.33878033,"remaining_time":45.5891948,"test":[0.6705037253]}, +{"learn":[0.6585371631],"iteration":617,"passed_time":20.36122842,"remaining_time":45.53271469,"test":[0.67049647]}, +{"learn":[0.6585092632],"iteration":618,"passed_time":20.3943397,"remaining_time":45.50013429,"test":[0.6705005632]}, +{"learn":[0.6584914317],"iteration":619,"passed_time":20.42384285,"remaining_time":45.45952119,"test":[0.6704957943]}, +{"learn":[0.6584662432],"iteration":620,"passed_time":20.45411533,"remaining_time":45.42065225,"test":[0.6704955333]}, +{"learn":[0.6584454668],"iteration":621,"passed_time":20.488223,"remaining_time":45.39030754,"test":[0.6704961207]}, +{"learn":[0.6584249408],"iteration":622,"passed_time":20.51043528,"remaining_time":45.33365872,"test":[0.6704921459]}, +{"learn":[0.6583931228],"iteration":623,"passed_time":20.54384208,"remaining_time":45.30180561,"test":[0.6704751713]}, +{"learn":[0.6583660767],"iteration":624,"passed_time":20.56912557,"remaining_time":45.25207624,"test":[0.6704753101]}, +{"learn":[0.658354264],"iteration":625,"passed_time":20.59414123,"remaining_time":45.20183714,"test":[0.6704620888]}, +{"learn":[0.6583253625],"iteration":626,"passed_time":20.61901142,"remaining_time":45.15135993,"test":[0.6704604282]}, +{"learn":[0.6582968632],"iteration":627,"passed_time":20.6468542,"remaining_time":45.10745855,"test":[0.6704663192]}, +{"learn":[0.6582687399],"iteration":628,"passed_time":20.67583093,"remaining_time":45.06607981,"test":[0.6704680085]}, +{"learn":[0.658242535],"iteration":629,"passed_time":20.7010198,"remaining_time":45.01650336,"test":[0.670453228]}, +{"learn":[0.6582199874],"iteration":630,"passed_time":20.72783977,"remaining_time":44.97054302,"test":[0.6704577785]}, +{"learn":[0.6581918101],"iteration":631,"passed_time":20.75222724,"remaining_time":44.91937795,"test":[0.67046675]}, +{"learn":[0.6581735218],"iteration":632,"passed_time":20.78264004,"remaining_time":44.88130954,"test":[0.6704731863]}, +{"learn":[0.6581445869],"iteration":633,"passed_time":20.80459182,"remaining_time":44.82503538,"test":[0.6704811116]}, +{"learn":[0.6581202427],"iteration":634,"passed_time":20.83717209,"remaining_time":44.79171637,"test":[0.6704839644]}, +{"learn":[0.6580977862],"iteration":635,"passed_time":20.86231353,"remaining_time":44.74244599,"test":[0.6704854798]}, +{"learn":[0.6580724179],"iteration":636,"passed_time":20.89269601,"remaining_time":44.70446572,"test":[0.6704835837]}, +{"learn":[0.6580426322],"iteration":637,"passed_time":20.93117347,"remaining_time":44.68379039,"test":[0.6704736198]}, +{"learn":[0.6580111256],"iteration":638,"passed_time":20.96066949,"remaining_time":44.64392985,"test":[0.6704640242]}, +{"learn":[0.6579834747],"iteration":639,"passed_time":20.9941179,"remaining_time":44.61250055,"test":[0.670465663]}, +{"learn":[0.6579541367],"iteration":640,"passed_time":21.0224519,"remaining_time":44.57022174,"test":[0.6704646829]}, +{"learn":[0.6579254503],"iteration":641,"passed_time":21.0522529,"remaining_time":44.53108946,"test":[0.6704600961]}, +{"learn":[0.657898555],"iteration":642,"passed_time":21.08260618,"remaining_time":44.49315178,"test":[0.6704643207]}, +{"learn":[0.6578676875],"iteration":643,"passed_time":21.10716702,"remaining_time":44.44304112,"test":[0.6704600533]}, +{"learn":[0.6578324163],"iteration":644,"passed_time":21.13594828,"remaining_time":44.40187584,"test":[0.6704614691]}, +{"learn":[0.6578062223],"iteration":645,"passed_time":21.1601277,"remaining_time":44.35110357,"test":[0.6704728212]}, +{"learn":[0.6577760631],"iteration":646,"passed_time":21.18552999,"remaining_time":44.30297075,"test":[0.6704758731]}, +{"learn":[0.6577483474],"iteration":647,"passed_time":21.21048648,"remaining_time":44.25397797,"test":[0.6704833026]}, +{"learn":[0.6577249642],"iteration":648,"passed_time":21.23686209,"remaining_time":44.20801337,"test":[0.6704767664]}, +{"learn":[0.6576974966],"iteration":649,"passed_time":21.26287585,"remaining_time":44.16135753,"test":[0.6704702727]}, +{"learn":[0.657675114],"iteration":650,"passed_time":21.28806218,"remaining_time":44.11305051,"test":[0.6704671372]}, +{"learn":[0.6576447891],"iteration":651,"passed_time":21.31506267,"remaining_time":44.06856515,"test":[0.6704699936]}, +{"learn":[0.6576102356],"iteration":652,"passed_time":21.3435081,"remaining_time":44.02711394,"test":[0.6704587989]}, +{"learn":[0.6575793887],"iteration":653,"passed_time":21.37776713,"remaining_time":43.99766753,"test":[0.6704637668]}, +{"learn":[0.6575543309],"iteration":654,"passed_time":21.40301154,"remaining_time":43.94969545,"test":[0.6704653717]}, +{"learn":[0.6575340787],"iteration":655,"passed_time":21.44023109,"remaining_time":43.92632711,"test":[0.6704598273]}, +{"learn":[0.6575061464],"iteration":656,"passed_time":21.4778965,"remaining_time":43.903828,"test":[0.6704522865]}, +{"learn":[0.657476113],"iteration":657,"passed_time":21.50245582,"remaining_time":43.85455275,"test":[0.6704558586]}, +{"learn":[0.6574447014],"iteration":658,"passed_time":21.53379663,"remaining_time":43.81915217,"test":[0.6704466331]}, +{"learn":[0.6574247361],"iteration":659,"passed_time":21.55955041,"remaining_time":43.77242053,"test":[0.6704405886]}, +{"learn":[0.6574034983],"iteration":660,"passed_time":21.58626671,"remaining_time":43.72770215,"test":[0.6704463767]}, +{"learn":[0.6573783832],"iteration":661,"passed_time":21.61183918,"remaining_time":43.68072633,"test":[0.6704475216]}, +{"learn":[0.657357694],"iteration":662,"passed_time":21.6373217,"remaining_time":43.63363366,"test":[0.6704572386]}, +{"learn":[0.6573411592],"iteration":663,"passed_time":21.66283476,"remaining_time":43.58666753,"test":[0.6704658153]}, +{"learn":[0.6573118559],"iteration":664,"passed_time":21.68841321,"remaining_time":43.5398972,"test":[0.6704600945]}, +{"learn":[0.6572819076],"iteration":665,"passed_time":21.71420973,"remaining_time":43.4936273,"test":[0.6704561998]}, +{"learn":[0.6572430097],"iteration":666,"passed_time":21.74213421,"remaining_time":43.45167151,"test":[0.6704535154]}, +{"learn":[0.6572160391],"iteration":667,"passed_time":21.77174463,"remaining_time":43.41311953,"test":[0.6704413781]}, +{"learn":[0.6571931413],"iteration":668,"passed_time":21.81895309,"remaining_time":43.40960622,"test":[0.6704450013]}, +{"learn":[0.6571737099],"iteration":669,"passed_time":21.84627583,"remaining_time":43.36648784,"test":[0.6704422199]}, +{"learn":[0.6571532872],"iteration":670,"passed_time":21.88834724,"remaining_time":43.35262814,"test":[0.67044342]}, +{"learn":[0.6571208939],"iteration":671,"passed_time":21.93403139,"remaining_time":43.34582395,"test":[0.6704415341]}, +{"learn":[0.6570887673],"iteration":672,"passed_time":21.9714274,"remaining_time":43.32256191,"test":[0.6704439539]}, +{"learn":[0.6570633692],"iteration":673,"passed_time":22.01942449,"remaining_time":43.32011406,"test":[0.6704498197]}, +{"learn":[0.6570454361],"iteration":674,"passed_time":22.05319867,"remaining_time":43.2896122,"test":[0.6704452194]}, +{"learn":[0.6570231031],"iteration":675,"passed_time":22.09079747,"remaining_time":43.26659149,"test":[0.6704366524]}, +{"learn":[0.6570052089],"iteration":676,"passed_time":22.14192346,"remaining_time":43.26996269,"test":[0.6704427124]}, +{"learn":[0.6569855794],"iteration":677,"passed_time":22.17624471,"remaining_time":43.24040635,"test":[0.6704395579]}, +{"learn":[0.6569579709],"iteration":678,"passed_time":22.213192,"remaining_time":43.21594497,"test":[0.6704401246]}, +{"learn":[0.6569333354],"iteration":679,"passed_time":22.23966403,"remaining_time":43.17111253,"test":[0.6704415621]}, +{"learn":[0.6569069617],"iteration":680,"passed_time":22.27051241,"remaining_time":43.13481039,"test":[0.6704341343]}, +{"learn":[0.6568931857],"iteration":681,"passed_time":22.29625075,"remaining_time":43.08864881,"test":[0.6704369615]}, +{"learn":[0.6568734532],"iteration":682,"passed_time":22.32160622,"remaining_time":43.04180877,"test":[0.6704357425]}, +{"learn":[0.6568435196],"iteration":683,"passed_time":22.35059872,"remaining_time":43.00202911,"test":[0.6704294622]}, +{"learn":[0.6568108038],"iteration":684,"passed_time":22.37956576,"remaining_time":42.96223208,"test":[0.6704289794]}, +{"learn":[0.6567811374],"iteration":685,"passed_time":22.41993338,"remaining_time":42.94430389,"test":[0.6704272409]}, +{"learn":[0.6567467284],"iteration":686,"passed_time":22.45285267,"remaining_time":42.91207504,"test":[0.6704101162]}, +{"learn":[0.6567172734],"iteration":687,"passed_time":22.4848431,"remaining_time":42.8780729,"test":[0.6704069439]}, +{"learn":[0.6566967606],"iteration":688,"passed_time":22.51193834,"remaining_time":42.83476221,"test":[0.6704100747]}, +{"learn":[0.6566720128],"iteration":689,"passed_time":22.53798671,"remaining_time":42.78951101,"test":[0.6704122261]}, +{"learn":[0.6566441608],"iteration":690,"passed_time":22.57108439,"remaining_time":42.75766928,"test":[0.6704137826]}, +{"learn":[0.6566172287],"iteration":691,"passed_time":22.59836588,"remaining_time":42.7148303,"test":[0.6704207952]}, +{"learn":[0.6565952549],"iteration":692,"passed_time":22.62447507,"remaining_time":42.66982528,"test":[0.6704154834]}, +{"learn":[0.6565702687],"iteration":693,"passed_time":22.65349415,"remaining_time":42.63035067,"test":[0.6704253514]}, +{"learn":[0.6565392213],"iteration":694,"passed_time":22.68028991,"remaining_time":42.58673141,"test":[0.6704155636]}, +{"learn":[0.6565157938],"iteration":695,"passed_time":22.70844406,"remaining_time":42.54570555,"test":[0.6704141298]}, +{"learn":[0.6564902789],"iteration":696,"passed_time":22.73944116,"remaining_time":42.51003133,"test":[0.6704207635]}, +{"learn":[0.6564644734],"iteration":697,"passed_time":22.7613976,"remaining_time":42.45750671,"test":[0.6704268341]}, +{"learn":[0.6564349549],"iteration":698,"passed_time":22.79216825,"remaining_time":42.42147482,"test":[0.6704243126]}, +{"learn":[0.6564046572],"iteration":699,"passed_time":22.8167121,"remaining_time":42.37389389,"test":[0.6704235165]}, +{"learn":[0.6563744107],"iteration":700,"passed_time":22.84507296,"remaining_time":42.33345189,"test":[0.6704257736]}, +{"learn":[0.6563525063],"iteration":701,"passed_time":22.87088832,"remaining_time":42.28833766,"test":[0.6704247758]}, +{"learn":[0.6563189867],"iteration":702,"passed_time":22.90238907,"remaining_time":42.25376759,"test":[0.6704331799]}, +{"learn":[0.6562939062],"iteration":703,"passed_time":22.94246813,"remaining_time":42.23499815,"test":[0.6704252722]}, +{"learn":[0.6562739297],"iteration":704,"passed_time":22.97441688,"remaining_time":42.20123385,"test":[0.6704146644]}, +{"learn":[0.656256438],"iteration":705,"passed_time":23.00262167,"remaining_time":42.16061253,"test":[0.6704164122]}, +{"learn":[0.6562366475],"iteration":706,"passed_time":23.033437,"remaining_time":42.12480062,"test":[0.6704118954]}, +{"learn":[0.6562073096],"iteration":707,"passed_time":23.0545813,"remaining_time":42.07135458,"test":[0.6704043129]}, +{"learn":[0.6561864222],"iteration":708,"passed_time":23.08699831,"remaining_time":42.03852584,"test":[0.6703978198]}, +{"learn":[0.6561578826],"iteration":709,"passed_time":23.11590694,"remaining_time":41.99932387,"test":[0.6703935976]}, +{"learn":[0.6561208567],"iteration":710,"passed_time":23.14362702,"remaining_time":41.9579961,"test":[0.6703839683]}, +{"learn":[0.6560924703],"iteration":711,"passed_time":23.16985155,"remaining_time":41.91400112,"test":[0.6703843723]}, +{"learn":[0.6560656907],"iteration":712,"passed_time":23.19510285,"remaining_time":41.86829925,"test":[0.6703879502]}, +{"learn":[0.6560362588],"iteration":713,"passed_time":23.23034771,"remaining_time":41.84065429,"test":[0.6703895978]}, +{"learn":[0.6560124527],"iteration":714,"passed_time":23.25923754,"remaining_time":41.80156678,"test":[0.6703894359]}, +{"learn":[0.6559875055],"iteration":715,"passed_time":23.28703452,"remaining_time":41.76054794,"test":[0.6703928777]}, +{"learn":[0.6559547281],"iteration":716,"passed_time":23.31161175,"remaining_time":41.71380457,"test":[0.6703933128]}, +{"learn":[0.6559230866],"iteration":717,"passed_time":23.34170355,"remaining_time":41.67696929,"test":[0.6703844355]}, +{"learn":[0.6558924823],"iteration":718,"passed_time":23.37263658,"remaining_time":41.64165155,"test":[0.6703825151]}, +{"learn":[0.6558676469],"iteration":719,"passed_time":23.40571088,"remaining_time":41.61015268,"test":[0.6703983542]}, +{"learn":[0.6558459277],"iteration":720,"passed_time":23.4389719,"remaining_time":41.57898067,"test":[0.670399556]}, +{"learn":[0.6558149638],"iteration":721,"passed_time":23.48304084,"remaining_time":41.56693379,"test":[0.6703931808]}, +{"learn":[0.6557812248],"iteration":722,"passed_time":23.50734531,"remaining_time":41.5198893,"test":[0.6703886918]}, +{"learn":[0.6557546502],"iteration":723,"passed_time":23.54055835,"remaining_time":41.48860836,"test":[0.6703847574]}, +{"learn":[0.6557274948],"iteration":724,"passed_time":23.56652491,"remaining_time":41.44457829,"test":[0.6703885941]}, +{"learn":[0.6557044723],"iteration":725,"passed_time":23.59580183,"remaining_time":41.40640708,"test":[0.6703788615]}, +{"learn":[0.6556751811],"iteration":726,"passed_time":23.62334313,"remaining_time":41.36522119,"test":[0.6703799906]}, +{"learn":[0.6556539158],"iteration":727,"passed_time":23.64879831,"remaining_time":41.32042782,"test":[0.6703774518]}, +{"learn":[0.6556182915],"iteration":728,"passed_time":23.67755213,"remaining_time":41.28143862,"test":[0.6703783496]}, +{"learn":[0.6555977079],"iteration":729,"passed_time":23.70012944,"remaining_time":41.23173204,"test":[0.6703648854]}, +{"learn":[0.6555667903],"iteration":730,"passed_time":23.72866102,"remaining_time":41.19243615,"test":[0.6703716654]}, +{"learn":[0.6555394075],"iteration":731,"passed_time":23.75226732,"remaining_time":41.14463793,"test":[0.6703550938]}, +{"learn":[0.6555122742],"iteration":732,"passed_time":23.7844108,"remaining_time":41.11166233,"test":[0.6703467057]}, +{"learn":[0.6554814941],"iteration":733,"passed_time":23.80747563,"remaining_time":41.06303017,"test":[0.6703484503]}, +{"learn":[0.6554517373],"iteration":734,"passed_time":23.84023587,"remaining_time":41.03115425,"test":[0.6703549183]}, +{"learn":[0.655429552],"iteration":735,"passed_time":23.87042124,"remaining_time":40.99485387,"test":[0.6703501504]}, +{"learn":[0.655396579],"iteration":736,"passed_time":23.9087808,"remaining_time":40.97257823,"test":[0.6703672622]}, +{"learn":[0.6553735864],"iteration":737,"passed_time":23.94161529,"remaining_time":40.94081097,"test":[0.6703560249]}, +{"learn":[0.6553472597],"iteration":738,"passed_time":23.97478791,"remaining_time":40.90961779,"test":[0.6703547155]}, +{"learn":[0.6553252832],"iteration":739,"passed_time":24.00628859,"remaining_time":40.87557247,"test":[0.6703593236]}, +{"learn":[0.6552971659],"iteration":740,"passed_time":24.03623034,"remaining_time":40.83888528,"test":[0.6703606827]}, +{"learn":[0.6552763852],"iteration":741,"passed_time":24.06404686,"remaining_time":40.79861313,"test":[0.6703511404]}, +{"learn":[0.6552488203],"iteration":742,"passed_time":24.09270947,"remaining_time":40.75980593,"test":[0.6703431646]}, +{"learn":[0.65521229],"iteration":743,"passed_time":24.12724624,"remaining_time":40.73094258,"test":[0.6703475116]}, +{"learn":[0.6551949744],"iteration":744,"passed_time":24.15397955,"remaining_time":40.68891857,"test":[0.6703483634]}, +{"learn":[0.6551673797],"iteration":745,"passed_time":24.17955779,"remaining_time":40.64499392,"test":[0.6703475713]}, +{"learn":[0.6551421856],"iteration":746,"passed_time":24.20715317,"remaining_time":40.60450191,"test":[0.670360457]}, +{"learn":[0.6551255516],"iteration":747,"passed_time":24.23336836,"remaining_time":40.5617342,"test":[0.6703664352]}, +{"learn":[0.6551019608],"iteration":748,"passed_time":24.2614437,"remaining_time":40.52211759,"test":[0.6703617612]}, +{"learn":[0.6550758728],"iteration":749,"passed_time":24.29512083,"remaining_time":40.49186805,"test":[0.6703669926]}, +{"learn":[0.655051966],"iteration":750,"passed_time":24.31839238,"remaining_time":40.44430371,"test":[0.6703670837]}, +{"learn":[0.6550351058],"iteration":751,"passed_time":24.34977118,"remaining_time":40.41025856,"test":[0.6703706628]}, +{"learn":[0.6549998756],"iteration":752,"passed_time":24.3762114,"remaining_time":40.36804198,"test":[0.670369618]}, +{"learn":[0.6549721212],"iteration":753,"passed_time":24.40831154,"remaining_time":40.3352204,"test":[0.6703692351]}, +{"learn":[0.6549401744],"iteration":754,"passed_time":24.44267281,"remaining_time":40.30612934,"test":[0.6703624433]}, +{"learn":[0.6549207325],"iteration":755,"passed_time":24.47460721,"remaining_time":40.27303091,"test":[0.6703686285]}, +{"learn":[0.6548900891],"iteration":756,"passed_time":24.50826603,"remaining_time":40.24276708,"test":[0.6703598432]}, +{"learn":[0.6548682731],"iteration":757,"passed_time":24.54826542,"remaining_time":40.22288345,"test":[0.6703618766]}, +{"learn":[0.6548418938],"iteration":758,"passed_time":24.57546587,"remaining_time":40.18201996,"test":[0.6703694148]}, +{"learn":[0.6548234717],"iteration":759,"passed_time":24.60502723,"remaining_time":40.14504442,"test":[0.6703683652]}, +{"learn":[0.6547996833],"iteration":760,"passed_time":24.63261096,"remaining_time":40.10486856,"test":[0.6703604855]}, +{"learn":[0.6547726174],"iteration":761,"passed_time":24.66001655,"remaining_time":40.06443634,"test":[0.6703758987]}, +{"learn":[0.6547509314],"iteration":762,"passed_time":24.68929907,"remaining_time":40.02708119,"test":[0.6703773302]}, +{"learn":[0.6547168175],"iteration":763,"passed_time":24.71425118,"remaining_time":39.98274144,"test":[0.6703641028]}, +{"learn":[0.6546907846],"iteration":764,"passed_time":24.74589169,"remaining_time":39.94924999,"test":[0.6703649602]}, +{"learn":[0.6546671611],"iteration":765,"passed_time":24.76625006,"remaining_time":39.89758822,"test":[0.6703567811]}, +{"learn":[0.6546475893],"iteration":766,"passed_time":24.79734832,"remaining_time":39.86327312,"test":[0.6703544688]}, +{"learn":[0.6546206223],"iteration":767,"passed_time":24.82531049,"remaining_time":39.82393558,"test":[0.6703611821]}, +{"learn":[0.6545874193],"iteration":768,"passed_time":24.85435247,"remaining_time":39.78635616,"test":[0.6703527821]}, +{"learn":[0.6545620629],"iteration":769,"passed_time":24.88095966,"remaining_time":39.74490958,"test":[0.6703523616]}, +{"learn":[0.6545346297],"iteration":770,"passed_time":24.90935211,"remaining_time":39.70634726,"test":[0.6703616298]}, +{"learn":[0.6545172316],"iteration":771,"passed_time":24.94098876,"remaining_time":39.67297175,"test":[0.6703603551]}, +{"learn":[0.6544943049],"iteration":772,"passed_time":24.97035098,"remaining_time":39.6359905,"test":[0.6703675655]}, +{"learn":[0.6544632323],"iteration":773,"passed_time":25.00434422,"remaining_time":39.60636436,"test":[0.6703582411]}, +{"learn":[0.6544384097],"iteration":774,"passed_time":25.03067441,"remaining_time":39.56461439,"test":[0.6703581437]}, +{"learn":[0.6544084745],"iteration":775,"passed_time":25.05692652,"remaining_time":39.522781,"test":[0.6703551885]}, +{"learn":[0.6543765257],"iteration":776,"passed_time":25.08660163,"remaining_time":39.48637554,"test":[0.6703608491]}, +{"learn":[0.6543536123],"iteration":777,"passed_time":25.10764591,"remaining_time":39.43643098,"test":[0.6703674554]}, +{"learn":[0.6543303593],"iteration":778,"passed_time":25.13940138,"remaining_time":39.40334928,"test":[0.6703679619]}, +{"learn":[0.6543005831],"iteration":779,"passed_time":25.15916899,"remaining_time":39.35152074,"test":[0.6703701757]}, +{"learn":[0.6542678123],"iteration":780,"passed_time":25.18841105,"remaining_time":39.31456219,"test":[0.6703603462]}, +{"learn":[0.6542439303],"iteration":781,"passed_time":25.21444083,"remaining_time":39.27262012,"test":[0.670359801]}, +{"learn":[0.6542100401],"iteration":782,"passed_time":25.24017824,"remaining_time":39.23026426,"test":[0.6703523669]}, +{"learn":[0.6541836178],"iteration":783,"passed_time":25.2660091,"remaining_time":39.18809574,"test":[0.6703365674]}, +{"learn":[0.654158129],"iteration":784,"passed_time":25.28891553,"remaining_time":39.1414425,"test":[0.6703486118]}, +{"learn":[0.6541343464],"iteration":785,"passed_time":25.31589904,"remaining_time":39.10114686,"test":[0.6703450011]}, +{"learn":[0.6541092921],"iteration":786,"passed_time":25.34123581,"remaining_time":39.05834694,"test":[0.6703473135]}, +{"learn":[0.6540812254],"iteration":787,"passed_time":25.36728606,"remaining_time":39.01668871,"test":[0.670350998]}, +{"learn":[0.654060259],"iteration":788,"passed_time":25.39177931,"remaining_time":38.97268028,"test":[0.6703417767]}, +{"learn":[0.6540467253],"iteration":789,"passed_time":25.41712461,"remaining_time":38.9300263,"test":[0.6703349821]}, +{"learn":[0.6540306837],"iteration":790,"passed_time":25.44804125,"remaining_time":38.89593157,"test":[0.6703457717]}, +{"learn":[0.6540103667],"iteration":791,"passed_time":25.48249341,"remaining_time":38.86723743,"test":[0.6703506266]}, +{"learn":[0.6539821302],"iteration":792,"passed_time":25.51450657,"remaining_time":38.83481643,"test":[0.6703596395]}, +{"learn":[0.6539577914],"iteration":793,"passed_time":25.54216564,"remaining_time":38.79578307,"test":[0.6703799895]}, +{"learn":[0.653923724],"iteration":794,"passed_time":25.56982738,"remaining_time":38.75678238,"test":[0.6703687687]}, +{"learn":[0.6539086888],"iteration":795,"passed_time":25.59539769,"remaining_time":38.71464675,"test":[0.6703780675]}, +{"learn":[0.6538798424],"iteration":796,"passed_time":25.61874122,"remaining_time":38.66919157,"test":[0.670374835]}, +{"learn":[0.6538566996],"iteration":797,"passed_time":25.64394874,"remaining_time":38.62659947,"test":[0.6703831387]}, +{"learn":[0.6538290752],"iteration":798,"passed_time":25.66776244,"remaining_time":38.58195581,"test":[0.670377656]}, +{"learn":[0.6538051255],"iteration":799,"passed_time":25.69593415,"remaining_time":38.54390122,"test":[0.6703689741]}, +{"learn":[0.6537917354],"iteration":800,"passed_time":25.71651353,"remaining_time":38.49450652,"test":[0.6703709756]}, +{"learn":[0.6537684302],"iteration":801,"passed_time":25.74304126,"remaining_time":38.45406912,"test":[0.6703737517]}, +{"learn":[0.6537402991],"iteration":802,"passed_time":25.77084871,"remaining_time":38.41557398,"test":[0.6703818964]}, +{"learn":[0.6537165427],"iteration":803,"passed_time":25.79028824,"remaining_time":38.36465763,"test":[0.6703812173]}, +{"learn":[0.6536853601],"iteration":804,"passed_time":25.82203653,"remaining_time":38.3320915,"test":[0.6703960068]}, +{"learn":[0.6536681479],"iteration":805,"passed_time":25.84395064,"remaining_time":38.28495914,"test":[0.6703976729]}, +{"learn":[0.6536409101],"iteration":806,"passed_time":25.87390688,"remaining_time":38.24977808,"test":[0.6704024604]}, +{"learn":[0.6536120189],"iteration":807,"passed_time":25.89606204,"remaining_time":38.20310143,"test":[0.6704085008]}, +{"learn":[0.6535912493],"iteration":808,"passed_time":25.92585483,"remaining_time":38.16772942,"test":[0.6704076633]}, +{"learn":[0.6535617421],"iteration":809,"passed_time":25.95539059,"remaining_time":38.13199358,"test":[0.6704111719]}, +{"learn":[0.6535315174],"iteration":810,"passed_time":25.98822968,"remaining_time":38.10111601,"test":[0.6704220803]}, +{"learn":[0.6534972927],"iteration":811,"passed_time":26.02835773,"remaining_time":38.08089777,"test":[0.6704265011]}, +{"learn":[0.6534818476],"iteration":812,"passed_time":26.0558565,"remaining_time":38.04219146,"test":[0.6704251162]}, +{"learn":[0.6534498323],"iteration":813,"passed_time":26.08151817,"remaining_time":38.00083606,"test":[0.6704375472]}, +{"learn":[0.6534305025],"iteration":814,"passed_time":26.10848988,"remaining_time":37.96142393,"test":[0.6704319336]}, +{"learn":[0.6534081059],"iteration":815,"passed_time":26.13143346,"remaining_time":37.91619757,"test":[0.670437614]}, +{"learn":[0.6533765804],"iteration":816,"passed_time":26.15923661,"remaining_time":37.87806231,"test":[0.6704554331]}, +{"learn":[0.6533441549],"iteration":817,"passed_time":26.18805523,"remaining_time":37.84141966,"test":[0.6704603317]}, +{"learn":[0.6533053405],"iteration":818,"passed_time":26.2140726,"remaining_time":37.8007567,"test":[0.6704548042]}, +{"learn":[0.6532838469],"iteration":819,"passed_time":26.24289367,"remaining_time":37.76416405,"test":[0.6704502654]}, +{"learn":[0.6532604302],"iteration":820,"passed_time":26.27260776,"remaining_time":37.72887277,"test":[0.6704512072]}, +{"learn":[0.6532364412],"iteration":821,"passed_time":26.29880394,"remaining_time":37.68855358,"test":[0.6704433481]}, +{"learn":[0.6532100089],"iteration":822,"passed_time":26.32785215,"remaining_time":37.65234749,"test":[0.6704095112]}, +{"learn":[0.6531782515],"iteration":823,"passed_time":26.35925682,"remaining_time":37.61952188,"test":[0.6704086019]}, +{"learn":[0.6531449701],"iteration":824,"passed_time":26.38596096,"remaining_time":37.580005,"test":[0.6703987131]}, +{"learn":[0.653115452],"iteration":825,"passed_time":26.40854839,"remaining_time":37.53466805,"test":[0.6704019708]}, +{"learn":[0.6530787602],"iteration":826,"passed_time":26.44419918,"remaining_time":37.50791492,"test":[0.6704046556]}, +{"learn":[0.653052397],"iteration":827,"passed_time":26.47784276,"remaining_time":37.47829917,"test":[0.6704091961]}, +{"learn":[0.6530313579],"iteration":828,"passed_time":26.51701028,"remaining_time":37.45647652,"test":[0.6704103204]}, +{"learn":[0.6530010363],"iteration":829,"passed_time":26.53963123,"remaining_time":37.41128739,"test":[0.6704074257]}, +{"learn":[0.6529752146],"iteration":830,"passed_time":26.57362226,"remaining_time":37.38214732,"test":[0.6704115335]}, +{"learn":[0.652954801],"iteration":831,"passed_time":26.59767057,"remaining_time":37.33903754,"test":[0.6704041275]}, +{"learn":[0.6529330351],"iteration":832,"passed_time":26.62378941,"remaining_time":37.29887425,"test":[0.6704004556]}, +{"learn":[0.6528993709],"iteration":833,"passed_time":26.65024746,"remaining_time":37.25921887,"test":[0.6704037097]}, +{"learn":[0.6528665883],"iteration":834,"passed_time":26.67774911,"remaining_time":37.22105115,"test":[0.6704035477]}, +{"learn":[0.6528413041],"iteration":835,"passed_time":26.70473813,"remaining_time":37.1821952,"test":[0.6704025281]}, +{"learn":[0.6528217161],"iteration":836,"passed_time":26.72833235,"remaining_time":37.13865056,"test":[0.6704024549]}, +{"learn":[0.6527978782],"iteration":837,"passed_time":26.76384162,"remaining_time":37.11167537,"test":[0.670405721]}, +{"learn":[0.6527789461],"iteration":838,"passed_time":26.79137369,"remaining_time":37.07364106,"test":[0.6703983189]}, +{"learn":[0.6527432001],"iteration":839,"passed_time":26.82295602,"remaining_time":37.04122498,"test":[0.6704035256]}, +{"learn":[0.6527139767],"iteration":840,"passed_time":26.87217031,"remaining_time":37.03310985,"test":[0.6704047613]}, +{"learn":[0.6526857244],"iteration":841,"passed_time":26.92488006,"remaining_time":37.0297044,"test":[0.6704139617]}, +{"learn":[0.652657086],"iteration":842,"passed_time":26.98258041,"remaining_time":37.03303147,"test":[0.6704066193]}, +{"learn":[0.6526355016],"iteration":843,"passed_time":27.05424841,"remaining_time":37.05534497,"test":[0.670402892]}, +{"learn":[0.6526054936],"iteration":844,"passed_time":27.09765154,"remaining_time":37.03880181,"test":[0.6704081961]}, +{"learn":[0.6525793707],"iteration":845,"passed_time":27.12038959,"remaining_time":36.99400661,"test":[0.6704029862]}, +{"learn":[0.6525584692],"iteration":846,"passed_time":27.14691224,"remaining_time":36.95441537,"test":[0.6704014281]}, +{"learn":[0.6525279747],"iteration":847,"passed_time":27.18096334,"remaining_time":36.92508227,"test":[0.6704036115]}, +{"learn":[0.6525038765],"iteration":848,"passed_time":27.20686017,"remaining_time":36.88468322,"test":[0.6704016777]}, +{"learn":[0.6524849104],"iteration":849,"passed_time":27.23465701,"remaining_time":36.8468889,"test":[0.6704085392]}, +{"learn":[0.6524610603],"iteration":850,"passed_time":27.26094834,"remaining_time":36.80708536,"test":[0.6704042952]}, +{"learn":[0.6524357337],"iteration":851,"passed_time":27.28945577,"remaining_time":36.77029957,"test":[0.670394789]}, +{"learn":[0.6524082286],"iteration":852,"passed_time":27.31865398,"remaining_time":36.73446203,"test":[0.6703885644]}, +{"learn":[0.65238051],"iteration":853,"passed_time":27.34791322,"remaining_time":36.69872195,"test":[0.6703946813]}, +{"learn":[0.6523557826],"iteration":854,"passed_time":27.3865535,"remaining_time":36.67555995,"test":[0.6704042137]}, +{"learn":[0.6523391233],"iteration":855,"passed_time":27.41370907,"remaining_time":36.63701306,"test":[0.6704077517]}, +{"learn":[0.652325347],"iteration":856,"passed_time":27.43905921,"remaining_time":36.5960848,"test":[0.6704118698]}, +{"learn":[0.6522924958],"iteration":857,"passed_time":27.47159295,"remaining_time":36.56475425,"test":[0.6704114259]}, +{"learn":[0.6522623584],"iteration":858,"passed_time":27.50124299,"remaining_time":36.52959052,"test":[0.6704157567]}, +{"learn":[0.6522343891],"iteration":859,"passed_time":27.53509105,"remaining_time":36.50000442,"test":[0.6703837005]}, +{"learn":[0.6522094424],"iteration":860,"passed_time":27.57211091,"remaining_time":36.47460432,"test":[0.6703829482]}, +{"learn":[0.6521841478],"iteration":861,"passed_time":27.59555719,"remaining_time":36.43125764,"test":[0.6703818491]}, +{"learn":[0.6521657946],"iteration":862,"passed_time":27.6272049,"remaining_time":36.39876242,"test":[0.6703826129]}, +{"learn":[0.6521304278],"iteration":863,"passed_time":27.65462267,"remaining_time":36.36070759,"test":[0.6703834487]}, +{"learn":[0.6521045712],"iteration":864,"passed_time":27.68321566,"remaining_time":36.3242194,"test":[0.6703868275]}, +{"learn":[0.6520753696],"iteration":865,"passed_time":27.71151671,"remaining_time":36.28736714,"test":[0.6703853357]}, +{"learn":[0.6520519528],"iteration":866,"passed_time":27.73884016,"remaining_time":36.2492571,"test":[0.670450644]}, +{"learn":[0.6520216555],"iteration":867,"passed_time":27.76583897,"remaining_time":36.21074851,"test":[0.6704556991]}, +{"learn":[0.6519926935],"iteration":868,"passed_time":27.79498714,"remaining_time":36.17506382,"test":[0.6704535742]}, +{"learn":[0.6519734186],"iteration":869,"passed_time":27.82082723,"remaining_time":36.13509744,"test":[0.6704495915]} +]} \ No newline at end of file diff --git a/ai-engine/catboost_info/learn/events.out.tfevents b/ai-engine/catboost_info/learn/events.out.tfevents new file mode 100644 index 0000000000000000000000000000000000000000..844ee9a40276379a886eee6f5572dabecc40d164 GIT binary patch literal 47720 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 a%OLhU8<^L|H}z$fN$mV9U^WN5CjLL2HS*p7 literal 0 HcmV?d00001 diff --git a/ai-engine/catboost_info/learn_error.tsv b/ai-engine/catboost_info/learn_error.tsv new file mode 100644 index 0000000..e001e08 --- /dev/null +++ b/ai-engine/catboost_info/learn_error.tsv @@ -0,0 +1,871 @@ +iter Logloss +0 0.692389481 +1 0.6916338586 +2 0.6910159214 +3 0.6903417151 +4 0.6896961461 +5 0.6890979366 +6 0.6884946167 +7 0.6879503686 +8 0.6874528094 +9 0.6869036785 +10 0.6863761921 +11 0.6859038678 +12 0.685410175 +13 0.6849483392 +14 0.6845417792 +15 0.6841038875 +16 0.6836957422 +17 0.6832947461 +18 0.6829014105 +19 0.6825264546 +20 0.6822106577 +21 0.6818649349 +22 0.6815467855 +23 0.6812293319 +24 0.6808837443 +25 0.6805816494 +26 0.6803209634 +27 0.6800350862 +28 0.6797703947 +29 0.6794926675 +30 0.6792251865 +31 0.6789670166 +32 0.678722402 +33 0.678476935 +34 0.6782297335 +35 0.6780226701 +36 0.6778291026 +37 0.6776045324 +38 0.6773969079 +39 0.6771819602 +40 0.6769816736 +41 0.6767984027 +42 0.6766201184 +43 0.6764394377 +44 0.6762698797 +45 0.6760974263 +46 0.6759245179 +47 0.6757673909 +48 0.6756172628 +49 0.675474531 +50 0.6753286933 +51 0.6751900513 +52 0.6750574835 +53 0.6749329567 +54 0.6748033265 +55 0.6746797823 +56 0.674535525 +57 0.6744256514 +58 0.674310819 +59 0.6741967947 +60 0.6740879654 +61 0.6739772476 +62 0.67388281 +63 0.6737789726 +64 0.6736812332 +65 0.6735930009 +66 0.6734947116 +67 0.6733961481 +68 0.6732990195 +69 0.6732133575 +70 0.673111539 +71 0.6730080451 +72 0.6729157861 +73 0.6728347949 +74 0.6727640693 +75 0.6726808811 +76 0.6726029645 +77 0.6725356026 +78 0.6724606887 +79 0.6723849561 +80 0.6723050519 +81 0.6722508802 +82 0.6721773904 +83 0.6721007598 +84 0.6720353564 +85 0.6719790902 +86 0.6719140024 +87 0.6718573633 +88 0.671795602 +89 0.6717369134 +90 0.6716711079 +91 0.6716070843 +92 0.6715517232 +93 0.6714957378 +94 0.6714364567 +95 0.6713881758 +96 0.6713336502 +97 0.6712700267 +98 0.6712154424 +99 0.6711600413 +100 0.6711060533 +101 0.6710494943 +102 0.6709936897 +103 0.6709472183 +104 0.6708914508 +105 0.6708388195 +106 0.6707885854 +107 0.6707454167 +108 0.6706973013 +109 0.6706577031 +110 0.67061108 +111 0.6705625485 +112 0.6705146484 +113 0.6704704423 +114 0.6704155922 +115 0.6703687117 +116 0.6703324232 +117 0.6702884624 +118 0.670253478 +119 0.6702140804 +120 0.6701682529 +121 0.6701320588 +122 0.6700939824 +123 0.6700655902 +124 0.6700190743 +125 0.6699792296 +126 0.6699379404 +127 0.669895454 +128 0.6698563938 +129 0.6698215571 +130 0.6697857067 +131 0.6697449303 +132 0.6697052425 +133 0.6696695553 +134 0.6696269265 +135 0.6695969271 +136 0.6695489786 +137 0.6695173859 +138 0.6694811164 +139 0.6694477439 +140 0.6694082161 +141 0.6693679185 +142 0.6693341916 +143 0.6692933159 +144 0.6692619696 +145 0.6692229289 +146 0.6691840164 +147 0.6691581406 +148 0.6691177196 +149 0.6690851126 +150 0.6690518144 +151 0.6690149711 +152 0.668993877 +153 0.6689596579 +154 0.6689372651 +155 0.6689003045 +156 0.6688680182 +157 0.6688348164 +158 0.6687947046 +159 0.6687605251 +160 0.668726253 +161 0.6686862718 +162 0.668663478 +163 0.6686399521 +164 0.6686058279 +165 0.6685761282 +166 0.6685469327 +167 0.6685157003 +168 0.6684805143 +169 0.6684485765 +170 0.6684144429 +171 0.6683849752 +172 0.6683568537 +173 0.6683266628 +174 0.6682937842 +175 0.6682657097 +176 0.6682301443 +177 0.6681995916 +178 0.6681658267 +179 0.6681422687 +180 0.6681216601 +181 0.6680899019 +182 0.6680676394 +183 0.6680413672 +184 0.6680088406 +185 0.6679873982 +186 0.6679663544 +187 0.6679417375 +188 0.6679100197 +189 0.667881208 +190 0.6678475427 +191 0.6678310341 +192 0.6678060257 +193 0.6677789336 +194 0.6677478773 +195 0.6677212408 +196 0.667704316 +197 0.6676819639 +198 0.6676554448 +199 0.6676318346 +200 0.6676074705 +201 0.6675849784 +202 0.6675631744 +203 0.6675397619 +204 0.6675169086 +205 0.6674864762 +206 0.6674670714 +207 0.6674375599 +208 0.6674148457 +209 0.6673974446 +210 0.6673812139 +211 0.6673515687 +212 0.6673197956 +213 0.6672900754 +214 0.6672550009 +215 0.6672271563 +216 0.667204521 +217 0.667181968 +218 0.6671640023 +219 0.66714351 +220 0.6671167156 +221 0.6670915937 +222 0.6670595279 +223 0.667033994 +224 0.6670008246 +225 0.6669858319 +226 0.6669553964 +227 0.6669274683 +228 0.666896348 +229 0.6668698686 +230 0.6668513411 +231 0.6668309985 +232 0.6668058585 +233 0.6667845908 +234 0.6667582863 +235 0.6667332943 +236 0.6667070085 +237 0.6666907315 +238 0.6666633028 +239 0.6666406707 +240 0.6666134624 +241 0.6665850522 +242 0.6665631193 +243 0.6665412643 +244 0.6665168385 +245 0.6664904845 +246 0.6664678274 +247 0.6664539777 +248 0.6664334121 +249 0.6664121724 +250 0.666392034 +251 0.666366899 +252 0.6663414098 +253 0.6663157816 +254 0.6662989799 +255 0.6662696102 +256 0.6662479711 +257 0.6662231874 +258 0.6661947927 +259 0.6661669951 +260 0.6661426137 +261 0.6661216749 +262 0.6660983123 +263 0.6660803402 +264 0.6660617842 +265 0.6660443878 +266 0.6660176079 +267 0.6659967546 +268 0.6659751467 +269 0.6659539329 +270 0.6659263951 +271 0.6659038921 +272 0.6658767418 +273 0.6658510507 +274 0.6658210119 +275 0.6657963011 +276 0.6657748552 +277 0.6657490013 +278 0.665732402 +279 0.6657118786 +280 0.665684467 +281 0.6656584634 +282 0.6656309991 +283 0.6656073482 +284 0.6655890957 +285 0.6655665563 +286 0.6655452454 +287 0.6655255286 +288 0.6655053548 +289 0.6654893396 +290 0.6654648912 +291 0.6654442759 +292 0.6654173127 +293 0.6653914518 +294 0.6653648946 +295 0.665344141 +296 0.6653140817 +297 0.665295365 +298 0.6652787488 +299 0.6652502991 +300 0.665231168 +301 0.6652136682 +302 0.6651903001 +303 0.6651697153 +304 0.6651525958 +305 0.6651322685 +306 0.6651113828 +307 0.6650886807 +308 0.6650622251 +309 0.6650429987 +310 0.665015513 +311 0.6650019022 +312 0.664979951 +313 0.6649549638 +314 0.6649340455 +315 0.6649162445 +316 0.6649048119 +317 0.6648796463 +318 0.6648605481 +319 0.6648429084 +320 0.6648238121 +321 0.6647969527 +322 0.6647854723 +323 0.6647589304 +324 0.6647429024 +325 0.6647237508 +326 0.6647059396 +327 0.664686288 +328 0.6646532527 +329 0.6646306438 +330 0.6646098516 +331 0.6645858284 +332 0.6645707188 +333 0.6645485788 +334 0.6645305696 +335 0.6645108881 +336 0.6644923286 +337 0.6644805222 +338 0.6644572776 +339 0.6644320741 +340 0.6644115048 +341 0.6643949013 +342 0.6643619789 +343 0.6643389502 +344 0.6643088915 +345 0.664286972 +346 0.664274149 +347 0.6642536926 +348 0.6642357634 +349 0.664207914 +350 0.6641853097 +351 0.6641654917 +352 0.664143804 +353 0.6641290647 +354 0.6641117244 +355 0.6640880219 +356 0.6640669415 +357 0.6640462999 +358 0.664030296 +359 0.6640028542 +360 0.6639813347 +361 0.6639597941 +362 0.6639429832 +363 0.6639222708 +364 0.6639065546 +365 0.6638823236 +366 0.6638648195 +367 0.6638436235 +368 0.6638208732 +369 0.6637956357 +370 0.6637718453 +371 0.663756918 +372 0.6637353525 +373 0.6637143112 +374 0.6636956547 +375 0.663680995 +376 0.66366728 +377 0.6636487567 +378 0.6636266904 +379 0.6636116064 +380 0.6635902746 +381 0.6635654896 +382 0.6635393029 +383 0.6635171734 +384 0.663500789 +385 0.663477743 +386 0.6634584806 +387 0.6634337499 +388 0.6634135584 +389 0.6633868455 +390 0.6633755323 +391 0.663356103 +392 0.6633337631 +393 0.663319422 +394 0.6632911566 +395 0.6632687875 +396 0.6632431997 +397 0.6632189331 +398 0.663201035 +399 0.6631898553 +400 0.6631712482 +401 0.663143025 +402 0.663121538 +403 0.6631087792 +404 0.6630859067 +405 0.663066483 +406 0.6630443652 +407 0.6630250376 +408 0.6630007822 +409 0.6629768728 +410 0.6629528093 +411 0.6629260936 +412 0.6629102182 +413 0.6628863488 +414 0.6628648972 +415 0.6628454339 +416 0.6628200274 +417 0.6627942591 +418 0.6627744647 +419 0.662765485 +420 0.6627503257 +421 0.6627323029 +422 0.6627111509 +423 0.6626785863 +424 0.6626576561 +425 0.6626363113 +426 0.6626181065 +427 0.66259794 +428 0.6625765658 +429 0.6625526572 +430 0.66253135 +431 0.6625035695 +432 0.662480212 +433 0.6624611632 +434 0.6624332625 +435 0.6624120584 +436 0.6623941719 +437 0.6623766304 +438 0.6623623329 +439 0.6623442925 +440 0.6623212715 +441 0.6623025941 +442 0.6622749791 +443 0.6622534499 +444 0.6622305473 +445 0.6622059333 +446 0.6621871707 +447 0.6621638454 +448 0.6621511296 +449 0.6621349978 +450 0.6621120424 +451 0.6620958271 +452 0.6620793528 +453 0.6620572713 +454 0.6620395025 +455 0.6620188044 +456 0.6620017347 +457 0.6619811454 +458 0.6619695569 +459 0.661952377 +460 0.6619237442 +461 0.6619089407 +462 0.6618886168 +463 0.6618831383 +464 0.6618690774 +465 0.661845878 +466 0.6618290213 +467 0.6618050064 +468 0.6617832833 +469 0.6617652311 +470 0.6617443144 +471 0.6617202619 +472 0.6617005831 +473 0.6616824419 +474 0.6616538226 +475 0.6616314155 +476 0.6616127861 +477 0.6616029072 +478 0.6615843751 +479 0.661563216 +480 0.6615432257 +481 0.6615263324 +482 0.6615033259 +483 0.661484293 +484 0.6614678231 +485 0.6614463024 +486 0.6614155436 +487 0.6613958945 +488 0.661380611 +489 0.6613677802 +490 0.6613530086 +491 0.6613248211 +492 0.6613059359 +493 0.6612729965 +494 0.6612624948 +495 0.6612401679 +496 0.6612191637 +497 0.6611912219 +498 0.6611773017 +499 0.6611638216 +500 0.6611450533 +501 0.6611179111 +502 0.6610959069 +503 0.6610728788 +504 0.6610436668 +505 0.6610188976 +506 0.6610030555 +507 0.6609831174 +508 0.6609586562 +509 0.660935882 +510 0.6609202024 +511 0.6609011137 +512 0.6608726737 +513 0.6608608849 +514 0.6608387256 +515 0.6608136063 +516 0.6607946343 +517 0.6607703935 +518 0.6607509625 +519 0.6607238109 +520 0.6606999858 +521 0.6606813873 +522 0.6606610372 +523 0.660638456 +524 0.6606156483 +525 0.6605968623 +526 0.6605735776 +527 0.6605517294 +528 0.6605309239 +529 0.6605086434 +530 0.6604803349 +531 0.6604566326 +532 0.6604430839 +533 0.6604273738 +534 0.6604048016 +535 0.6603845173 +536 0.6603669212 +537 0.6603488983 +538 0.6603176881 +539 0.6602953862 +540 0.6602672025 +541 0.6602568636 +542 0.660235705 +543 0.6602152295 +544 0.6601897709 +545 0.6601683731 +546 0.6601472267 +547 0.6601262337 +548 0.6601119991 +549 0.6600869973 +550 0.6600667497 +551 0.6600397508 +552 0.660016863 +553 0.6599933158 +554 0.6599632649 +555 0.6599446007 +556 0.6599138126 +557 0.6598965504 +558 0.6598785723 +559 0.659860838 +560 0.6598408724 +561 0.6598244857 +562 0.6598082469 +563 0.6597851673 +564 0.6597683521 +565 0.6597479006 +566 0.6597310938 +567 0.6597096581 +568 0.6596862311 +569 0.6596574779 +570 0.6596385418 +571 0.6596189903 +572 0.65959275 +573 0.6595730662 +574 0.6595566809 +575 0.6595365076 +576 0.6595163446 +577 0.6594816637 +578 0.6594570142 +579 0.6594353055 +580 0.6594162362 +581 0.659395036 +582 0.6593798831 +583 0.6593556719 +584 0.6593292627 +585 0.6592976737 +586 0.6592754841 +587 0.6592510441 +588 0.6592290326 +589 0.6592097404 +590 0.6591876204 +591 0.6591705995 +592 0.6591456195 +593 0.6591107122 +594 0.6590819533 +595 0.6590551327 +596 0.6590373916 +597 0.6590177149 +598 0.6589946095 +599 0.6589697628 +600 0.6589442269 +601 0.6589182437 +602 0.6588837179 +603 0.6588674101 +604 0.6588406916 +605 0.6588149945 +606 0.6587866031 +607 0.6587636648 +608 0.6587502469 +609 0.6587292784 +610 0.6587104112 +611 0.6586953782 +612 0.6586641191 +613 0.6586450136 +614 0.6586136263 +615 0.6585862768 +616 0.6585585235 +617 0.6585371631 +618 0.6585092632 +619 0.6584914317 +620 0.6584662432 +621 0.6584454668 +622 0.6584249408 +623 0.6583931228 +624 0.6583660767 +625 0.658354264 +626 0.6583253625 +627 0.6582968632 +628 0.6582687399 +629 0.658242535 +630 0.6582199874 +631 0.6581918101 +632 0.6581735218 +633 0.6581445869 +634 0.6581202427 +635 0.6580977862 +636 0.6580724179 +637 0.6580426322 +638 0.6580111256 +639 0.6579834747 +640 0.6579541367 +641 0.6579254503 +642 0.657898555 +643 0.6578676875 +644 0.6578324163 +645 0.6578062223 +646 0.6577760631 +647 0.6577483474 +648 0.6577249642 +649 0.6576974966 +650 0.657675114 +651 0.6576447891 +652 0.6576102356 +653 0.6575793887 +654 0.6575543309 +655 0.6575340787 +656 0.6575061464 +657 0.657476113 +658 0.6574447014 +659 0.6574247361 +660 0.6574034983 +661 0.6573783832 +662 0.657357694 +663 0.6573411592 +664 0.6573118559 +665 0.6572819076 +666 0.6572430097 +667 0.6572160391 +668 0.6571931413 +669 0.6571737099 +670 0.6571532872 +671 0.6571208939 +672 0.6570887673 +673 0.6570633692 +674 0.6570454361 +675 0.6570231031 +676 0.6570052089 +677 0.6569855794 +678 0.6569579709 +679 0.6569333354 +680 0.6569069617 +681 0.6568931857 +682 0.6568734532 +683 0.6568435196 +684 0.6568108038 +685 0.6567811374 +686 0.6567467284 +687 0.6567172734 +688 0.6566967606 +689 0.6566720128 +690 0.6566441608 +691 0.6566172287 +692 0.6565952549 +693 0.6565702687 +694 0.6565392213 +695 0.6565157938 +696 0.6564902789 +697 0.6564644734 +698 0.6564349549 +699 0.6564046572 +700 0.6563744107 +701 0.6563525063 +702 0.6563189867 +703 0.6562939062 +704 0.6562739297 +705 0.656256438 +706 0.6562366475 +707 0.6562073096 +708 0.6561864222 +709 0.6561578826 +710 0.6561208567 +711 0.6560924703 +712 0.6560656907 +713 0.6560362588 +714 0.6560124527 +715 0.6559875055 +716 0.6559547281 +717 0.6559230866 +718 0.6558924823 +719 0.6558676469 +720 0.6558459277 +721 0.6558149638 +722 0.6557812248 +723 0.6557546502 +724 0.6557274948 +725 0.6557044723 +726 0.6556751811 +727 0.6556539158 +728 0.6556182915 +729 0.6555977079 +730 0.6555667903 +731 0.6555394075 +732 0.6555122742 +733 0.6554814941 +734 0.6554517373 +735 0.655429552 +736 0.655396579 +737 0.6553735864 +738 0.6553472597 +739 0.6553252832 +740 0.6552971659 +741 0.6552763852 +742 0.6552488203 +743 0.65521229 +744 0.6551949744 +745 0.6551673797 +746 0.6551421856 +747 0.6551255516 +748 0.6551019608 +749 0.6550758728 +750 0.655051966 +751 0.6550351058 +752 0.6549998756 +753 0.6549721212 +754 0.6549401744 +755 0.6549207325 +756 0.6548900891 +757 0.6548682731 +758 0.6548418938 +759 0.6548234717 +760 0.6547996833 +761 0.6547726174 +762 0.6547509314 +763 0.6547168175 +764 0.6546907846 +765 0.6546671611 +766 0.6546475893 +767 0.6546206223 +768 0.6545874193 +769 0.6545620629 +770 0.6545346297 +771 0.6545172316 +772 0.6544943049 +773 0.6544632323 +774 0.6544384097 +775 0.6544084745 +776 0.6543765257 +777 0.6543536123 +778 0.6543303593 +779 0.6543005831 +780 0.6542678123 +781 0.6542439303 +782 0.6542100401 +783 0.6541836178 +784 0.654158129 +785 0.6541343464 +786 0.6541092921 +787 0.6540812254 +788 0.654060259 +789 0.6540467253 +790 0.6540306837 +791 0.6540103667 +792 0.6539821302 +793 0.6539577914 +794 0.653923724 +795 0.6539086888 +796 0.6538798424 +797 0.6538566996 +798 0.6538290752 +799 0.6538051255 +800 0.6537917354 +801 0.6537684302 +802 0.6537402991 +803 0.6537165427 +804 0.6536853601 +805 0.6536681479 +806 0.6536409101 +807 0.6536120189 +808 0.6535912493 +809 0.6535617421 +810 0.6535315174 +811 0.6534972927 +812 0.6534818476 +813 0.6534498323 +814 0.6534305025 +815 0.6534081059 +816 0.6533765804 +817 0.6533441549 +818 0.6533053405 +819 0.6532838469 +820 0.6532604302 +821 0.6532364412 +822 0.6532100089 +823 0.6531782515 +824 0.6531449701 +825 0.653115452 +826 0.6530787602 +827 0.653052397 +828 0.6530313579 +829 0.6530010363 +830 0.6529752146 +831 0.652954801 +832 0.6529330351 +833 0.6528993709 +834 0.6528665883 +835 0.6528413041 +836 0.6528217161 +837 0.6527978782 +838 0.6527789461 +839 0.6527432001 +840 0.6527139767 +841 0.6526857244 +842 0.652657086 +843 0.6526355016 +844 0.6526054936 +845 0.6525793707 +846 0.6525584692 +847 0.6525279747 +848 0.6525038765 +849 0.6524849104 +850 0.6524610603 +851 0.6524357337 +852 0.6524082286 +853 0.65238051 +854 0.6523557826 +855 0.6523391233 +856 0.652325347 +857 0.6522924958 +858 0.6522623584 +859 0.6522343891 +860 0.6522094424 +861 0.6521841478 +862 0.6521657946 +863 0.6521304278 +864 0.6521045712 +865 0.6520753696 +866 0.6520519528 +867 0.6520216555 +868 0.6519926935 +869 0.6519734186 diff --git a/ai-engine/catboost_info/test/events.out.tfevents b/ai-engine/catboost_info/test/events.out.tfevents new file mode 100644 index 0000000000000000000000000000000000000000..24bc0a9e0c69fa80f10ee287310f1ad3acd34d0c GIT binary patch literal 47720 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 Vfy_#;^8lG85OYK}-fmWx{|5(UdE)>8 literal 0 HcmV?d00001 diff --git a/ai-engine/catboost_info/test_error.tsv b/ai-engine/catboost_info/test_error.tsv new file mode 100644 index 0000000..676f094 --- /dev/null +++ b/ai-engine/catboost_info/test_error.tsv @@ -0,0 +1,871 @@ +iter Logloss +0 0.6924099937 +1 0.6916660956 +2 0.691108145 +3 0.6904585078 +4 0.689812816 +5 0.689192261 +6 0.6886032715 +7 0.6880706742 +8 0.6876192378 +9 0.6870868859 +10 0.6865493528 +11 0.686105086 +12 0.6856345086 +13 0.6852027185 +14 0.6848238481 +15 0.6844045699 +16 0.6840077621 +17 0.6836197496 +18 0.6832475033 +19 0.6829012069 +20 0.6825880966 +21 0.6822424968 +22 0.6819180513 +23 0.6816384467 +24 0.6813262593 +25 0.6810353411 +26 0.6808138172 +27 0.6805550049 +28 0.680347991 +29 0.680089679 +30 0.6798451919 +31 0.6796090443 +32 0.6793890865 +33 0.6791683772 +34 0.6789766369 +35 0.6787930242 +36 0.6786087714 +37 0.6784161299 +38 0.6782227897 +39 0.6780242369 +40 0.6778499631 +41 0.6776975784 +42 0.6775231674 +43 0.6773582124 +44 0.6772234666 +45 0.6770659843 +46 0.6769049529 +47 0.6767664194 +48 0.6766584917 +49 0.6765507257 +50 0.6764489911 +51 0.6763947956 +52 0.6762778712 +53 0.6761865366 +54 0.6760679685 +55 0.6759774874 +56 0.6758500622 +57 0.6757625065 +58 0.6756876412 +59 0.6756151069 +60 0.6755303655 +61 0.6754565036 +62 0.6753738983 +63 0.6752897299 +64 0.6752115539 +65 0.6751595431 +66 0.6750764658 +67 0.6750179194 +68 0.6749408803 +69 0.6748795802 +70 0.674790372 +71 0.6747239773 +72 0.6746701254 +73 0.6746120937 +74 0.6745550085 +75 0.6744855074 +76 0.6744264172 +77 0.674381715 +78 0.6743331681 +79 0.67428564 +80 0.6742202413 +81 0.6741620971 +82 0.6741109453 +83 0.6740556003 +84 0.6740146772 +85 0.673983295 +86 0.6739595301 +87 0.6739336659 +88 0.673890361 +89 0.673863586 +90 0.6738190616 +91 0.6737799295 +92 0.6737364374 +93 0.6737093719 +94 0.6736630475 +95 0.67364367 +96 0.6735998081 +97 0.6735526984 +98 0.6735012924 +99 0.6734818024 +100 0.6734379341 +101 0.6734059869 +102 0.6733740852 +103 0.6733330971 +104 0.6733060254 +105 0.6732755898 +106 0.6732294722 +107 0.6732035176 +108 0.673196437 +109 0.6731652709 +110 0.673138808 +111 0.6731062725 +112 0.6730726625 +113 0.6730285927 +114 0.6729872702 +115 0.6729721425 +116 0.6729564624 +117 0.6729312424 +118 0.6729354345 +119 0.6729085401 +120 0.6728898322 +121 0.6728773638 +122 0.6728618874 +123 0.6728540413 +124 0.6728441291 +125 0.672815631 +126 0.6728082021 +127 0.6727900064 +128 0.6727649552 +129 0.6727467657 +130 0.6727396032 +131 0.6727245271 +132 0.6726955143 +133 0.67269209 +134 0.672677932 +135 0.6726540285 +136 0.6726288583 +137 0.6725863431 +138 0.6725837967 +139 0.6725772977 +140 0.6725685594 +141 0.6725553829 +142 0.6725484347 +143 0.6725306172 +144 0.672543149 +145 0.6725196247 +146 0.6725226452 +147 0.6725056913 +148 0.6724771476 +149 0.6724439435 +150 0.672442532 +151 0.6724303064 +152 0.6724235788 +153 0.6724294499 +154 0.6724285935 +155 0.6724172017 +156 0.6724130745 +157 0.6723860878 +158 0.6723707604 +159 0.6723566111 +160 0.6723469906 +161 0.6723287161 +162 0.6723155898 +163 0.6722970834 +164 0.6722872244 +165 0.6722800481 +166 0.6722550973 +167 0.6722394313 +168 0.6722204135 +169 0.6721982148 +170 0.6721971176 +171 0.6721880705 +172 0.672179176 +173 0.6721769709 +174 0.6721693215 +175 0.6721581386 +176 0.6721638661 +177 0.6721598475 +178 0.6721433342 +179 0.6721335599 +180 0.6721300594 +181 0.6721153533 +182 0.6721076397 +183 0.6721009911 +184 0.6720999252 +185 0.6720953028 +186 0.6720942505 +187 0.6720856237 +188 0.6720876136 +189 0.6720880182 +190 0.6720743856 +191 0.6720598415 +192 0.6720563492 +193 0.6720389527 +194 0.6720317324 +195 0.672000736 +196 0.6719895017 +197 0.6719725302 +198 0.6719770493 +199 0.6719667172 +200 0.6719511616 +201 0.6719427289 +202 0.6719299116 +203 0.6719106583 +204 0.6718967065 +205 0.671890967 +206 0.6718896293 +207 0.6718883534 +208 0.6718827289 +209 0.6718763224 +210 0.67187262 +211 0.6718590402 +212 0.6718455115 +213 0.6718253747 +214 0.671794877 +215 0.6717873786 +216 0.6717765089 +217 0.6717616726 +218 0.6717499215 +219 0.6717326052 +220 0.6717161937 +221 0.6717056951 +222 0.6717021438 +223 0.6716868488 +224 0.6716751909 +225 0.671670116 +226 0.6716558757 +227 0.6716559962 +228 0.6716487875 +229 0.6716427451 +230 0.6716323255 +231 0.6716303547 +232 0.6716309509 +233 0.6716215401 +234 0.6716162103 +235 0.6716135097 +236 0.6716156696 +237 0.6716020054 +238 0.6715921704 +239 0.6715804466 +240 0.6715882966 +241 0.6715753942 +242 0.6715752261 +243 0.6715625509 +244 0.6715628214 +245 0.6715601629 +246 0.6715576255 +247 0.6715550274 +248 0.6715448645 +249 0.6715308166 +250 0.671519334 +251 0.6715184071 +252 0.6715163019 +253 0.6715096094 +254 0.6714992963 +255 0.6714917256 +256 0.671477406 +257 0.6714741542 +258 0.6714576155 +259 0.6714473645 +260 0.6714427232 +261 0.6714364275 +262 0.6714339587 +263 0.6714336287 +264 0.6714283568 +265 0.6714271895 +266 0.671413471 +267 0.6714072396 +268 0.6714002677 +269 0.6714001163 +270 0.6713933952 +271 0.6713926761 +272 0.6713836619 +273 0.6713772112 +274 0.6713603715 +275 0.6713560246 +276 0.6713837913 +277 0.6713684274 +278 0.6713619356 +279 0.6713584836 +280 0.6713673572 +281 0.6713625568 +282 0.6713542652 +283 0.6713512017 +284 0.671342038 +285 0.6713279798 +286 0.6713123285 +287 0.6713035326 +288 0.6713022203 +289 0.671296041 +290 0.6712829551 +291 0.6712769751 +292 0.6712702915 +293 0.6712379343 +294 0.6712192006 +295 0.6712074061 +296 0.6711953324 +297 0.6711891001 +298 0.6711870526 +299 0.6711812809 +300 0.6711768946 +301 0.6711845012 +302 0.6711869636 +303 0.671186884 +304 0.6711890401 +305 0.6711868603 +306 0.6711900892 +307 0.6711884242 +308 0.6711837119 +309 0.6711766645 +310 0.671172959 +311 0.6711740433 +312 0.6711715069 +313 0.6711589843 +314 0.6711446402 +315 0.6711415366 +316 0.6711359351 +317 0.671143361 +318 0.6711353638 +319 0.6711444387 +320 0.6711487352 +321 0.67114436 +322 0.6711444722 +323 0.6711325635 +324 0.6711269403 +325 0.6711154078 +326 0.6711203043 +327 0.6711241333 +328 0.6711213497 +329 0.6711231641 +330 0.6711049215 +331 0.6711031963 +332 0.6710996314 +333 0.6710867309 +334 0.6710914578 +335 0.6710929585 +336 0.6710984779 +337 0.6710923199 +338 0.6710893917 +339 0.6710923306 +340 0.6710927901 +341 0.6711092802 +342 0.6711012995 +343 0.6711015305 +344 0.6710975574 +345 0.6710899474 +346 0.671085152 +347 0.6710814533 +348 0.6710701892 +349 0.67105503 +350 0.6710527861 +351 0.6710508715 +352 0.6710560803 +353 0.6710465693 +354 0.6710440741 +355 0.6710496913 +356 0.6710404659 +357 0.6710293986 +358 0.6710353817 +359 0.6710271815 +360 0.6710288077 +361 0.6710169894 +362 0.6710119848 +363 0.6710114775 +364 0.6710013614 +365 0.6709985657 +366 0.6709948954 +367 0.6709970591 +368 0.6709739289 +369 0.6709754911 +370 0.6709717066 +371 0.67096845 +372 0.6709739445 +373 0.6709728881 +374 0.6709694284 +375 0.6709604166 +376 0.6709605025 +377 0.6709603727 +378 0.670944339 +379 0.6709447187 +380 0.6709538679 +381 0.6709640912 +382 0.6709534847 +383 0.6709471555 +384 0.6709506783 +385 0.6709546729 +386 0.670930774 +387 0.6709287322 +388 0.6709198643 +389 0.6709220389 +390 0.6709230923 +391 0.670930414 +392 0.6709354296 +393 0.6709351544 +394 0.6709414935 +395 0.6709445943 +396 0.6709475685 +397 0.6709533591 +398 0.6709592222 +399 0.6709508704 +400 0.6709479912 +401 0.6709417519 +402 0.6709476082 +403 0.6709480979 +404 0.6709448724 +405 0.6709421934 +406 0.6709386261 +407 0.6709461564 +408 0.670934384 +409 0.6709312987 +410 0.670931806 +411 0.6709286111 +412 0.6709224729 +413 0.6709236504 +414 0.6709245901 +415 0.6709463437 +416 0.6709567049 +417 0.670945606 +418 0.6709479298 +419 0.6709464351 +420 0.6709414048 +421 0.6709414427 +422 0.6709296343 +423 0.670924721 +424 0.670906284 +425 0.6708996826 +426 0.6708987677 +427 0.670909526 +428 0.6709033226 +429 0.6708750209 +430 0.6708752079 +431 0.6708776566 +432 0.6708736133 +433 0.6708754298 +434 0.6708751084 +435 0.6708642042 +436 0.6708610465 +437 0.6708574768 +438 0.6708557953 +439 0.670871378 +440 0.6708640187 +441 0.6708700565 +442 0.6708667534 +443 0.6708675383 +444 0.6708740175 +445 0.6708774523 +446 0.6708697231 +447 0.6708614971 +448 0.6708607946 +449 0.6708740865 +450 0.6708729562 +451 0.6708674017 +452 0.6708693088 +453 0.6708712037 +454 0.6708703905 +455 0.6708577595 +456 0.6708493546 +457 0.6708523777 +458 0.6708454134 +459 0.6708404483 +460 0.6708274771 +461 0.6708244992 +462 0.6708344314 +463 0.6708279081 +464 0.6708258106 +465 0.6708049714 +466 0.670810989 +467 0.6708212237 +468 0.6708221741 +469 0.6708259658 +470 0.6708159692 +471 0.6708136212 +472 0.6708224942 +473 0.6708363084 +474 0.670850875 +475 0.6708527236 +476 0.6708453401 +477 0.6708413844 +478 0.6708364569 +479 0.6708251774 +480 0.6708154393 +481 0.6708111613 +482 0.6708102339 +483 0.6707929623 +484 0.6707900226 +485 0.6707832384 +486 0.6707739118 +487 0.6707737538 +488 0.6707730234 +489 0.6707796291 +490 0.670791408 +491 0.6707944906 +492 0.6707835635 +493 0.6707908928 +494 0.670796262 +495 0.6707877825 +496 0.6707854132 +497 0.6707756206 +498 0.6707707899 +499 0.6707704386 +500 0.6707621465 +501 0.6707661931 +502 0.6707651988 +503 0.6707607827 +504 0.670760242 +505 0.6707506008 +506 0.6707452886 +507 0.6707355189 +508 0.6707312551 +509 0.6707199485 +510 0.6707131947 +511 0.6707154112 +512 0.6706982346 +513 0.6706988941 +514 0.6706989098 +515 0.670693306 +516 0.6706944515 +517 0.6706899688 +518 0.6706909374 +519 0.6706855074 +520 0.6706787779 +521 0.6706737082 +522 0.6706761225 +523 0.670685455 +524 0.6706693855 +525 0.6706647216 +526 0.6706569188 +527 0.6706549134 +528 0.6706547978 +529 0.6706564214 +530 0.6706559196 +531 0.6706515072 +532 0.6706474616 +533 0.6706424204 +534 0.6706520008 +535 0.6706448306 +536 0.6706415789 +537 0.6706305359 +538 0.6706152774 +539 0.670616585 +540 0.6705963243 +541 0.6706027368 +542 0.6706003522 +543 0.6706044301 +544 0.6706047241 +545 0.6706038235 +546 0.6706026913 +547 0.6705845786 +548 0.6705873967 +549 0.6705755426 +550 0.6705715731 +551 0.6705757153 +552 0.6705516814 +553 0.6705530864 +554 0.6705552479 +555 0.6705563336 +556 0.6705718544 +557 0.6705688384 +558 0.6705641528 +559 0.6705628467 +560 0.670558488 +561 0.6705544404 +562 0.6705617451 +563 0.6705631717 +564 0.6705636201 +565 0.6705537522 +566 0.670555083 +567 0.6705524541 +568 0.6705503132 +569 0.6705354602 +570 0.6705387012 +571 0.6705411923 +572 0.6705390018 +573 0.6705354939 +574 0.670531296 +575 0.6705377163 +576 0.6705248875 +577 0.6705252902 +578 0.6705181562 +579 0.6705123446 +580 0.6705128345 +581 0.6705173712 +582 0.670541941 +583 0.6705463243 +584 0.6705513215 +585 0.6705455889 +586 0.6705408087 +587 0.6705510193 +588 0.6705456751 +589 0.6705402427 +590 0.6705443402 +591 0.67054441 +592 0.6705441955 +593 0.6705319356 +594 0.6705358843 +595 0.6705334396 +596 0.6705320462 +597 0.6705332043 +598 0.6705328363 +599 0.6705315638 +600 0.6705274435 +601 0.670509808 +602 0.6705077789 +603 0.6705212132 +604 0.6705098442 +605 0.6705061509 +606 0.6705003071 +607 0.6705045031 +608 0.6705083194 +609 0.6705329997 +610 0.6705269987 +611 0.6705315607 +612 0.6705142835 +613 0.6705165015 +614 0.6705001061 +615 0.6705013916 +616 0.6705037253 +617 0.67049647 +618 0.6705005632 +619 0.6704957943 +620 0.6704955333 +621 0.6704961207 +622 0.6704921459 +623 0.6704751713 +624 0.6704753101 +625 0.6704620888 +626 0.6704604282 +627 0.6704663192 +628 0.6704680085 +629 0.670453228 +630 0.6704577785 +631 0.67046675 +632 0.6704731863 +633 0.6704811116 +634 0.6704839644 +635 0.6704854798 +636 0.6704835837 +637 0.6704736198 +638 0.6704640242 +639 0.670465663 +640 0.6704646829 +641 0.6704600961 +642 0.6704643207 +643 0.6704600533 +644 0.6704614691 +645 0.6704728212 +646 0.6704758731 +647 0.6704833026 +648 0.6704767664 +649 0.6704702727 +650 0.6704671372 +651 0.6704699936 +652 0.6704587989 +653 0.6704637668 +654 0.6704653717 +655 0.6704598273 +656 0.6704522865 +657 0.6704558586 +658 0.6704466331 +659 0.6704405886 +660 0.6704463767 +661 0.6704475216 +662 0.6704572386 +663 0.6704658153 +664 0.6704600945 +665 0.6704561998 +666 0.6704535154 +667 0.6704413781 +668 0.6704450013 +669 0.6704422199 +670 0.67044342 +671 0.6704415341 +672 0.6704439539 +673 0.6704498197 +674 0.6704452194 +675 0.6704366524 +676 0.6704427124 +677 0.6704395579 +678 0.6704401246 +679 0.6704415621 +680 0.6704341343 +681 0.6704369615 +682 0.6704357425 +683 0.6704294622 +684 0.6704289794 +685 0.6704272409 +686 0.6704101162 +687 0.6704069439 +688 0.6704100747 +689 0.6704122261 +690 0.6704137826 +691 0.6704207952 +692 0.6704154834 +693 0.6704253514 +694 0.6704155636 +695 0.6704141298 +696 0.6704207635 +697 0.6704268341 +698 0.6704243126 +699 0.6704235165 +700 0.6704257736 +701 0.6704247758 +702 0.6704331799 +703 0.6704252722 +704 0.6704146644 +705 0.6704164122 +706 0.6704118954 +707 0.6704043129 +708 0.6703978198 +709 0.6703935976 +710 0.6703839683 +711 0.6703843723 +712 0.6703879502 +713 0.6703895978 +714 0.6703894359 +715 0.6703928777 +716 0.6703933128 +717 0.6703844355 +718 0.6703825151 +719 0.6703983542 +720 0.670399556 +721 0.6703931808 +722 0.6703886918 +723 0.6703847574 +724 0.6703885941 +725 0.6703788615 +726 0.6703799906 +727 0.6703774518 +728 0.6703783496 +729 0.6703648854 +730 0.6703716654 +731 0.6703550938 +732 0.6703467057 +733 0.6703484503 +734 0.6703549183 +735 0.6703501504 +736 0.6703672622 +737 0.6703560249 +738 0.6703547155 +739 0.6703593236 +740 0.6703606827 +741 0.6703511404 +742 0.6703431646 +743 0.6703475116 +744 0.6703483634 +745 0.6703475713 +746 0.670360457 +747 0.6703664352 +748 0.6703617612 +749 0.6703669926 +750 0.6703670837 +751 0.6703706628 +752 0.670369618 +753 0.6703692351 +754 0.6703624433 +755 0.6703686285 +756 0.6703598432 +757 0.6703618766 +758 0.6703694148 +759 0.6703683652 +760 0.6703604855 +761 0.6703758987 +762 0.6703773302 +763 0.6703641028 +764 0.6703649602 +765 0.6703567811 +766 0.6703544688 +767 0.6703611821 +768 0.6703527821 +769 0.6703523616 +770 0.6703616298 +771 0.6703603551 +772 0.6703675655 +773 0.6703582411 +774 0.6703581437 +775 0.6703551885 +776 0.6703608491 +777 0.6703674554 +778 0.6703679619 +779 0.6703701757 +780 0.6703603462 +781 0.670359801 +782 0.6703523669 +783 0.6703365674 +784 0.6703486118 +785 0.6703450011 +786 0.6703473135 +787 0.670350998 +788 0.6703417767 +789 0.6703349821 +790 0.6703457717 +791 0.6703506266 +792 0.6703596395 +793 0.6703799895 +794 0.6703687687 +795 0.6703780675 +796 0.670374835 +797 0.6703831387 +798 0.670377656 +799 0.6703689741 +800 0.6703709756 +801 0.6703737517 +802 0.6703818964 +803 0.6703812173 +804 0.6703960068 +805 0.6703976729 +806 0.6704024604 +807 0.6704085008 +808 0.6704076633 +809 0.6704111719 +810 0.6704220803 +811 0.6704265011 +812 0.6704251162 +813 0.6704375472 +814 0.6704319336 +815 0.670437614 +816 0.6704554331 +817 0.6704603317 +818 0.6704548042 +819 0.6704502654 +820 0.6704512072 +821 0.6704433481 +822 0.6704095112 +823 0.6704086019 +824 0.6703987131 +825 0.6704019708 +826 0.6704046556 +827 0.6704091961 +828 0.6704103204 +829 0.6704074257 +830 0.6704115335 +831 0.6704041275 +832 0.6704004556 +833 0.6704037097 +834 0.6704035477 +835 0.6704025281 +836 0.6704024549 +837 0.670405721 +838 0.6703983189 +839 0.6704035256 +840 0.6704047613 +841 0.6704139617 +842 0.6704066193 +843 0.670402892 +844 0.6704081961 +845 0.6704029862 +846 0.6704014281 +847 0.6704036115 +848 0.6704016777 +849 0.6704085392 +850 0.6704042952 +851 0.670394789 +852 0.6703885644 +853 0.6703946813 +854 0.6704042137 +855 0.6704077517 +856 0.6704118698 +857 0.6704114259 +858 0.6704157567 +859 0.6703837005 +860 0.6703829482 +861 0.6703818491 +862 0.6703826129 +863 0.6703834487 +864 0.6703868275 +865 0.6703853357 +866 0.670450644 +867 0.6704556991 +868 0.6704535742 +869 0.6704495915 diff --git a/ai-engine/catboost_info/time_left.tsv b/ai-engine/catboost_info/time_left.tsv new file mode 100644 index 0000000..effbfd2 --- /dev/null +++ b/ai-engine/catboost_info/time_left.tsv @@ -0,0 +1,871 @@ +iter Passed Remaining +0 46 93548 +1 83 83419 +2 132 88415 +3 162 81250 +4 196 78573 +5 230 76747 +6 269 76701 +7 319 79674 +8 364 80653 +9 411 81918 +10 456 82497 +11 491 81432 +12 522 79809 +13 555 78774 +14 595 78777 +15 630 78123 +16 662 77290 +17 700 77124 +18 730 76120 +19 764 75651 +20 804 75774 +21 835 75128 +22 886 76169 +23 920 75764 +24 960 75853 +25 989 75130 +26 1025 74941 +27 1060 74714 +28 1104 75079 +29 1141 74976 +30 1180 74975 +31 1213 74640 +32 1245 74260 +33 1287 74434 +34 1327 74528 +35 1376 75071 +36 1427 75741 +37 1468 75804 +38 1508 75857 +39 1549 75922 +40 1586 75781 +41 1621 75590 +42 1663 75705 +43 1701 75621 +44 1739 75591 +45 1776 75460 +46 1819 75616 +47 1869 76025 +48 1916 76288 +49 1953 76191 +50 1993 76197 +51 2038 76381 +52 2080 76420 +53 2158 77788 +54 2220 78529 +55 2286 79390 +56 2328 79372 +57 2367 79254 +58 2409 79257 +59 2444 79049 +60 2484 78985 +61 2521 78820 +62 2554 78528 +63 2593 78466 +64 2623 78111 +65 2660 77969 +66 2695 77776 +67 2725 77446 +68 2761 77291 +69 2791 76975 +70 2824 76739 +71 2861 76611 +72 2897 76476 +73 2935 76408 +74 3040 78027 +75 3097 78411 +76 3152 78741 +77 3216 79248 +78 3256 79195 +79 3305 79336 +80 3348 79320 +81 3381 79089 +82 3416 78911 +83 3480 79399 +84 3535 79649 +85 3581 79716 +86 3612 79428 +87 3644 79185 +88 3678 78975 +89 3712 78785 +90 3743 78531 +91 3775 78297 +92 3806 78047 +93 3837 77821 +94 3871 77629 +95 3913 77618 +96 3945 77403 +97 3989 77433 +98 4020 77204 +99 4053 77020 +100 4084 76789 +101 4116 76597 +102 4148 76401 +103 4176 76141 +104 4202 75845 +105 4232 75634 +106 4261 75390 +107 4290 75168 +108 4324 75018 +109 4351 74766 +110 4386 74648 +111 4424 74577 +112 4458 74455 +113 4497 74400 +114 4533 74307 +115 4564 74136 +116 4596 73981 +117 4628 73818 +118 4668 73786 +119 4692 73509 +120 4723 73354 +121 4756 73220 +122 4788 73065 +123 4815 72854 +124 4843 72647 +125 4875 72514 +126 4916 72515 +127 4952 72436 +128 4991 72397 +129 5028 72327 +130 5059 72180 +131 5096 72116 +132 5125 71946 +133 5156 71804 +134 5190 71704 +135 5221 71564 +136 5251 71407 +137 5274 71165 +138 5309 71084 +139 5344 71008 +140 5377 70902 +141 5416 70866 +142 5452 70803 +143 5490 70760 +144 5521 70641 +145 5553 70522 +146 5582 70365 +147 5611 70217 +148 5636 70026 +149 5673 69975 +150 5706 69874 +151 5738 69764 +152 5765 69605 +153 5795 69471 +154 5817 69246 +155 5853 69191 +156 5888 69122 +157 5924 69070 +158 5964 69061 +159 5996 68963 +160 6022 68789 +161 6050 68650 +162 6079 68510 +163 6108 68385 +164 6140 68292 +165 6169 68162 +166 6202 68074 +167 6231 67953 +168 6263 67858 +169 6295 67764 +170 6325 67656 +171 6356 67561 +172 6395 67545 +173 6437 67554 +174 6472 67495 +175 6503 67395 +176 6533 67291 +177 6562 67174 +178 6590 67049 +179 6624 66982 +180 6655 66882 +181 6687 66804 +182 6718 66703 +183 6751 66632 +184 6784 66559 +185 6810 66424 +186 6832 66246 +187 6867 66187 +188 6918 66294 +189 6969 66393 +190 7018 66470 +191 7074 66614 +192 7117 66635 +193 7191 66943 +194 7242 67036 +195 7282 67027 +196 7317 66967 +197 7351 66903 +198 7389 66879 +199 7432 66896 +200 7471 66869 +201 7506 66814 +202 7540 66752 +203 7568 66628 +204 7605 66596 +205 7638 66519 +206 7665 66397 +207 7700 66340 +208 7734 66276 +209 7766 66197 +210 7796 66106 +211 7831 66053 +212 7871 66037 +213 7910 66016 +214 7951 66014 +215 7989 65983 +216 8025 65946 +217 8058 65872 +218 8087 65768 +219 8112 65638 +220 8148 65594 +221 8197 65655 +222 8239 65655 +223 8268 65556 +224 8298 65466 +225 8327 65366 +226 8357 65278 +227 8384 65167 +228 8418 65103 +229 8453 65058 +230 8490 65020 +231 8523 64958 +232 8550 64848 +233 8575 64718 +234 8607 64648 +235 8635 64545 +236 8660 64426 +237 8691 64345 +238 8719 64250 +239 8746 64137 +240 8773 64038 +241 8803 63951 +242 8833 63873 +243 8862 63779 +244 8892 63698 +245 8932 63688 +246 8962 63611 +247 8991 63521 +248 9021 63442 +249 9051 63358 +250 9085 63306 +251 9110 63193 +252 9137 63093 +253 9174 63066 +254 9196 62935 +255 9238 62934 +256 9267 62855 +257 9297 62776 +258 9324 62681 +259 9357 62625 +260 9388 62552 +261 9427 62536 +262 9461 62491 +263 9496 62443 +264 9524 62356 +265 9553 62278 +266 9590 62247 +267 9620 62172 +268 9645 62071 +269 9682 62040 +270 9711 61962 +271 9739 61872 +272 9768 61797 +273 9804 61761 +274 9848 61777 +275 9886 61755 +276 9925 61740 +277 9965 61728 +278 9995 61656 +279 10022 61564 +280 10055 61516 +281 10080 61410 +282 10111 61344 +283 10147 61311 +284 10175 61230 +285 10202 61141 +286 10234 61084 +287 10264 61018 +288 10299 60977 +289 10323 60874 +290 10353 60804 +291 10394 60803 +292 10431 60773 +293 10471 60763 +294 10503 60707 +295 10534 60645 +296 10576 60646 +297 10612 60612 +298 10639 60525 +299 10668 60453 +300 10702 60411 +301 10729 60326 +302 10764 60290 +303 10801 60263 +304 10829 60182 +305 10857 60108 +306 10892 60067 +307 10930 60047 +308 10972 60045 +309 11002 59983 +310 11030 59902 +311 11058 59828 +312 11092 59788 +313 11117 59696 +314 11149 59641 +315 11187 59617 +316 11211 59525 +317 11243 59468 +318 11274 59413 +319 11304 59346 +320 11334 59287 +321 11362 59209 +322 11394 59158 +323 11436 59158 +324 11477 59153 +325 11513 59122 +326 11547 59081 +327 11572 58991 +328 11607 58956 +329 11637 58894 +330 11668 58833 +331 11700 58785 +332 11724 58694 +333 11757 58648 +334 11780 58550 +335 11815 58515 +336 11844 58451 +337 11869 58364 +338 11905 58335 +339 11941 58302 +340 11986 58315 +341 12020 58274 +342 12066 58292 +343 12122 58358 +344 12177 58415 +345 12221 58422 +346 12264 58423 +347 12300 58394 +348 12324 58304 +349 12354 58243 +350 12401 58262 +351 12438 58232 +352 12479 58228 +353 12512 58179 +354 12541 58116 +355 12569 58044 +356 12597 57977 +357 12628 57920 +358 12653 57839 +359 12682 57775 +360 12720 57752 +361 12744 57666 +362 12770 57592 +363 12811 57583 +364 12841 57522 +365 12870 57460 +366 12897 57386 +367 12938 57378 +368 12974 57347 +369 13009 57313 +370 13038 57249 +371 13078 57235 +372 13117 57216 +373 13147 57159 +374 13181 57118 +375 13205 57036 +376 13235 56979 +377 13274 56960 +378 13306 56911 +379 13333 56841 +380 13366 56798 +381 13396 56741 +382 13421 56666 +383 13467 56674 +384 13508 56664 +385 13540 56616 +386 13569 56559 +387 13598 56496 +388 13627 56438 +389 13656 56376 +390 13685 56317 +391 13717 56271 +392 13750 56227 +393 13771 56135 +394 13804 56090 +395 13825 55999 +396 13858 55957 +397 13888 55904 +398 13917 55843 +399 13953 55812 +400 13994 55802 +401 14025 55752 +402 14048 55670 +403 14076 55607 +404 14105 55551 +405 14142 55526 +406 14182 55511 +407 14214 55464 +408 14240 55394 +409 14267 55328 +410 14299 55284 +411 14324 55213 +412 14351 55146 +413 14379 55086 +414 14410 55036 +415 14451 55025 +416 14484 54984 +417 14513 54929 +418 14536 54851 +419 14565 54793 +420 14587 54710 +421 14615 54650 +422 14642 54588 +423 14666 54515 +424 14690 54441 +425 14719 54384 +426 14739 54297 +427 14772 54257 +428 14790 54164 +429 14824 54125 +430 14844 54039 +431 14876 53995 +432 14906 53946 +433 14938 53902 +434 14980 53894 +435 15006 53829 +436 15033 53770 +437 15059 53706 +438 15085 53639 +439 15110 53574 +440 15134 53503 +441 15160 53438 +442 15184 53369 +443 15211 53308 +444 15234 53236 +445 15266 53193 +446 15287 53114 +447 15316 53059 +448 15336 52978 +449 15366 52929 +450 15393 52870 +451 15429 52843 +452 15469 52828 +453 15490 52748 +454 15523 52712 +455 15550 52653 +456 15577 52594 +457 15604 52536 +458 15630 52476 +459 15656 52414 +460 15682 52353 +461 15711 52304 +462 15736 52238 +463 15765 52188 +464 15786 52112 +465 15817 52068 +466 15839 51996 +467 15873 51961 +468 15903 51916 +469 15935 51873 +470 15969 51840 +471 15994 51779 +472 16022 51726 +473 16047 51663 +474 16073 51605 +475 16099 51546 +476 16128 51495 +477 16152 51431 +478 16176 51367 +479 16205 51317 +480 16228 51250 +481 16255 51194 +482 16277 51123 +483 16305 51071 +484 16328 51005 +485 16362 50973 +486 16392 50928 +487 16426 50894 +488 16459 50860 +489 16480 50787 +490 16510 50743 +491 16530 50668 +492 16561 50625 +493 16585 50562 +494 16613 50510 +495 16638 50453 +496 16663 50393 +497 16690 50339 +498 16716 50282 +499 16740 50222 +500 16773 50186 +501 16802 50139 +502 16836 50107 +503 16873 50085 +504 16921 50094 +505 16989 50163 +506 17038 50173 +507 17069 50132 +508 17110 50121 +509 17145 50091 +510 17190 50091 +511 17219 50044 +512 17247 49994 +513 17271 49932 +514 17298 49878 +515 17343 49878 +516 17373 49836 +517 17417 49831 +518 17460 49823 +519 17490 49781 +520 17518 49731 +521 17546 49680 +522 17571 49622 +523 17600 49577 +524 17625 49520 +525 17655 49474 +526 17679 49414 +527 17707 49366 +528 17729 49300 +529 17758 49254 +530 17781 49191 +531 17808 49141 +532 17829 49071 +533 17862 49038 +534 17905 49031 +535 18028 49241 +536 18072 49236 +537 18106 49203 +538 18135 49157 +539 18165 49114 +540 18200 49083 +541 18223 49022 +542 18254 48980 +543 18280 48927 +544 18307 48876 +545 18338 48834 +546 18367 48790 +547 18411 48783 +548 18444 48747 +549 18470 48693 +550 18503 48660 +551 18531 48611 +552 18557 48558 +553 18584 48508 +554 18625 48493 +555 18650 48436 +556 18677 48388 +557 18703 48333 +558 18729 48282 +559 18756 48231 +560 18781 48176 +561 18808 48126 +562 18834 48074 +563 18869 48043 +564 18902 48008 +565 18930 47960 +566 18958 47914 +567 18983 47859 +568 19016 47824 +569 19037 47761 +570 19068 47720 +571 19090 47660 +572 19111 47595 +573 19141 47553 +574 19164 47494 +575 19196 47458 +576 19217 47393 +577 19249 47358 +578 19274 47303 +579 19298 47247 +580 19324 47195 +581 19357 47162 +582 19391 47130 +583 19427 47103 +584 19460 47070 +585 19483 47012 +586 19511 46967 +587 19542 46929 +588 19564 46867 +589 19597 46833 +590 19621 46779 +591 19647 46729 +592 19670 46672 +593 19699 46627 +594 19726 46582 +595 19753 46532 +596 19778 46480 +597 19803 46429 +598 19830 46381 +599 19857 46335 +600 19896 46313 +601 19925 46271 +602 19957 46236 +603 19991 46204 +604 20019 46159 +605 20047 46115 +606 20072 46063 +607 20098 46015 +608 20123 45963 +609 20149 45913 +610 20176 45867 +611 20202 45817 +612 20230 45774 +613 20253 45719 +614 20285 45682 +615 20307 45626 +616 20338 45589 +617 20361 45532 +618 20394 45500 +619 20423 45459 +620 20454 45420 +621 20488 45390 +622 20510 45333 +623 20543 45301 +624 20569 45252 +625 20594 45201 +626 20619 45151 +627 20646 45107 +628 20675 45066 +629 20701 45016 +630 20727 44970 +631 20752 44919 +632 20782 44881 +633 20804 44825 +634 20837 44791 +635 20862 44742 +636 20892 44704 +637 20931 44683 +638 20960 44643 +639 20994 44612 +640 21022 44570 +641 21052 44531 +642 21082 44493 +643 21107 44443 +644 21135 44401 +645 21160 44351 +646 21185 44302 +647 21210 44253 +648 21236 44208 +649 21262 44161 +650 21288 44113 +651 21315 44068 +652 21343 44027 +653 21377 43997 +654 21403 43949 +655 21440 43926 +656 21477 43903 +657 21502 43854 +658 21533 43819 +659 21559 43772 +660 21586 43727 +661 21611 43680 +662 21637 43633 +663 21662 43586 +664 21688 43539 +665 21714 43493 +666 21742 43451 +667 21771 43413 +668 21818 43409 +669 21846 43366 +670 21888 43352 +671 21934 43345 +672 21971 43322 +673 22019 43320 +674 22053 43289 +675 22090 43266 +676 22141 43269 +677 22176 43240 +678 22213 43215 +679 22239 43171 +680 22270 43134 +681 22296 43088 +682 22321 43041 +683 22350 43002 +684 22379 42962 +685 22419 42944 +686 22452 42912 +687 22484 42878 +688 22511 42834 +689 22537 42789 +690 22571 42757 +691 22598 42714 +692 22624 42669 +693 22653 42630 +694 22680 42586 +695 22708 42545 +696 22739 42510 +697 22761 42457 +698 22792 42421 +699 22816 42373 +700 22845 42333 +701 22870 42288 +702 22902 42253 +703 22942 42234 +704 22974 42201 +705 23002 42160 +706 23033 42124 +707 23054 42071 +708 23086 42038 +709 23115 41999 +710 23143 41957 +711 23169 41914 +712 23195 41868 +713 23230 41840 +714 23259 41801 +715 23287 41760 +716 23311 41713 +717 23341 41676 +718 23372 41641 +719 23405 41610 +720 23438 41578 +721 23483 41566 +722 23507 41519 +723 23540 41488 +724 23566 41444 +725 23595 41406 +726 23623 41365 +727 23648 41320 +728 23677 41281 +729 23700 41231 +730 23728 41192 +731 23752 41144 +732 23784 41111 +733 23807 41063 +734 23840 41031 +735 23870 40994 +736 23908 40972 +737 23941 40940 +738 23974 40909 +739 24006 40875 +740 24036 40838 +741 24064 40798 +742 24092 40759 +743 24127 40730 +744 24153 40688 +745 24179 40644 +746 24207 40604 +747 24233 40561 +748 24261 40522 +749 24295 40491 +750 24318 40444 +751 24349 40410 +752 24376 40368 +753 24408 40335 +754 24442 40306 +755 24474 40273 +756 24508 40242 +757 24548 40222 +758 24575 40182 +759 24605 40145 +760 24632 40104 +761 24660 40064 +762 24689 40027 +763 24714 39982 +764 24745 39949 +765 24766 39897 +766 24797 39863 +767 24825 39823 +768 24854 39786 +769 24880 39744 +770 24909 39706 +771 24940 39672 +772 24970 39635 +773 25004 39606 +774 25030 39564 +775 25056 39522 +776 25086 39486 +777 25107 39436 +778 25139 39403 +779 25159 39351 +780 25188 39314 +781 25214 39272 +782 25240 39230 +783 25266 39188 +784 25288 39141 +785 25315 39101 +786 25341 39058 +787 25367 39016 +788 25391 38972 +789 25417 38930 +790 25448 38895 +791 25482 38867 +792 25514 38834 +793 25542 38795 +794 25569 38756 +795 25595 38714 +796 25618 38669 +797 25643 38626 +798 25667 38581 +799 25695 38543 +800 25716 38494 +801 25743 38454 +802 25770 38415 +803 25790 38364 +804 25822 38332 +805 25843 38284 +806 25873 38249 +807 25896 38203 +808 25925 38167 +809 25955 38131 +810 25988 38101 +811 26028 38080 +812 26055 38042 +813 26081 38000 +814 26108 37961 +815 26131 37916 +816 26159 37878 +817 26188 37841 +818 26214 37800 +819 26242 37764 +820 26272 37728 +821 26298 37688 +822 26327 37652 +823 26359 37619 +824 26385 37580 +825 26408 37534 +826 26444 37507 +827 26477 37478 +828 26517 37456 +829 26539 37411 +830 26573 37382 +831 26597 37339 +832 26623 37298 +833 26650 37259 +834 26677 37221 +835 26704 37182 +836 26728 37138 +837 26763 37111 +838 26791 37073 +839 26822 37041 +840 26872 37033 +841 26924 37029 +842 26982 37033 +843 27054 37055 +844 27097 37038 +845 27120 36994 +846 27146 36954 +847 27180 36925 +848 27206 36884 +849 27234 36846 +850 27260 36807 +851 27289 36770 +852 27318 36734 +853 27347 36698 +854 27386 36675 +855 27413 36637 +856 27439 36596 +857 27471 36564 +858 27501 36529 +859 27535 36500 +860 27572 36474 +861 27595 36431 +862 27627 36398 +863 27654 36360 +864 27683 36324 +865 27711 36287 +866 27738 36249 +867 27765 36210 +868 27794 36175 +869 27820 36135 diff --git a/ai-engine/features/rolling_features.py b/ai-engine/features/rolling_features.py new file mode 100644 index 0000000..4bf49b8 --- /dev/null +++ b/ai-engine/features/rolling_features.py @@ -0,0 +1,243 @@ +""" +V27 Rolling Window Feature Calculator +====================================== +Computes rolling averages over 5/10/20 match windows, +with home/away splits and trend detection. +""" +from __future__ import annotations +from typing import Dict, List, Tuple +import math + + +def calc_rolling_features( + team_matches: List[Tuple], # [(mst, is_home, team_goals, opp_goals, opp_id), ...] + before_date: int, + team_is_home: bool, +) -> Dict[str, float]: + """Calculate rolling window features for a team before a given date.""" + valid = [m for m in team_matches if m[0] < before_date] + + defaults = { + "rolling5_goals_avg": 1.3, "rolling5_conceded_avg": 1.2, + "rolling10_goals_avg": 1.3, "rolling10_conceded_avg": 1.2, + "rolling20_goals_avg": 1.3, "rolling20_conceded_avg": 1.2, + "rolling5_clean_sheets": 0.25, + "venue_goals_avg": 1.3, "venue_conceded_avg": 1.2, + "goal_trend": 0.0, + } + + if len(valid) < 3: + return defaults + + result = {} + + for window in [5, 10, 20]: + recent = valid[-window:] if len(valid) >= window else valid + n = len(recent) + g_sum = sum(m[2] for m in recent) + c_sum = sum(m[3] for m in recent) + result[f"rolling{window}_goals_avg"] = g_sum / n + result[f"rolling{window}_conceded_avg"] = c_sum / n + + # Clean sheet rate (last 5) + r5 = valid[-5:] if len(valid) >= 5 else valid + result["rolling5_clean_sheets"] = sum(1 for m in r5 if m[3] == 0) / len(r5) + + # Venue-specific (home-only or away-only) + venue_matches = [m for m in valid if m[1] == team_is_home] + if venue_matches: + vm = venue_matches[-10:] if len(venue_matches) >= 10 else venue_matches + result["venue_goals_avg"] = sum(m[2] for m in vm) / len(vm) + result["venue_conceded_avg"] = sum(m[3] for m in vm) / len(vm) + else: + result["venue_goals_avg"] = defaults["venue_goals_avg"] + result["venue_conceded_avg"] = defaults["venue_conceded_avg"] + + # Goal trend: compare last 3 vs previous 3 + if len(valid) >= 6: + last3 = sum(m[2] for m in valid[-3:]) / 3 + prev3 = sum(m[2] for m in valid[-6:-3]) / 3 + result["goal_trend"] = last3 - prev3 + else: + result["goal_trend"] = 0.0 + + return result + + +def calc_league_quality( + all_matches: List[Tuple], # all FT matches in this league +) -> Dict[str, float]: + """Calculate league-level quality features.""" + defaults = { + "league_home_win_rate": 0.45, + "league_draw_rate": 0.25, + "league_btts_rate": 0.50, + "league_ou25_rate": 0.50, + "league_reliability_score": 0.50, + } + + if len(all_matches) < 20: + return defaults + + n = len(all_matches) + home_wins = sum(1 for m in all_matches if m[2] > m[3]) + draws = sum(1 for m in all_matches if m[2] == m[3]) + btts = sum(1 for m in all_matches if m[2] > 0 and m[3] > 0) + ou25 = sum(1 for m in all_matches if (m[2] + m[3]) > 2.5) + + hw_rate = home_wins / n + dr_rate = draws / n + btts_rate = btts / n + ou25_rate = ou25 / n + + # Reliability: leagues closer to averages are more predictable + predictability = 1.0 - abs(hw_rate - 0.45) - abs(dr_rate - 0.27) * 0.5 + reliability = max(0.2, min(0.95, predictability)) + + return { + "league_home_win_rate": round(hw_rate, 4), + "league_draw_rate": round(dr_rate, 4), + "league_btts_rate": round(btts_rate, 4), + "league_ou25_rate": round(ou25_rate, 4), + "league_reliability_score": round(reliability, 4), + } + + +def calc_time_features( + team_matches: List[Tuple], + match_mst: int, +) -> Dict[str, float]: + """Calculate time-based features.""" + from datetime import datetime + + # Days since last match + valid = [m for m in team_matches if m[0] < match_mst] + if valid: + last_mst = valid[-1][0] + days_rest = (match_mst - last_mst) / 86_400_000 # ms to days + days_rest = min(days_rest, 60.0) # cap at 60 days + else: + days_rest = 14.0 + + # Month and season flags + try: + dt = datetime.utcfromtimestamp(match_mst / 1000) + month = dt.month + is_season_start = 1.0 if month in (7, 8) else 0.0 + is_season_end = 1.0 if month in (5, 6) else 0.0 + except Exception: + month = 6 + is_season_start = 0.0 + is_season_end = 0.0 + + return { + "days_rest": round(days_rest, 2), + "match_month": month, + "is_season_start": is_season_start, + "is_season_end": is_season_end, + } + + +def calc_advanced_h2h( + team_matches: List[Tuple], + home_id: int, + away_id: int, + before_date: int, +) -> Dict[str, float]: + """Calculate advanced H2H features.""" + defaults = { + "h2h_home_goals_avg": 1.3, + "h2h_away_goals_avg": 1.1, + "h2h_recent_trend": 0.0, + "h2h_venue_advantage": 0.0, + } + + h2h = [m for m in team_matches if m[4] == away_id and m[0] < before_date] + if not h2h: + return defaults + + recent = h2h[-10:] + home_goals_total = 0 + away_goals_total = 0 + venue_home_wins = 0 + venue_total = 0 + + for mst, is_home, team_goals, opp_goals, _ in recent: + if is_home: + home_goals_total += team_goals + away_goals_total += opp_goals + venue_total += 1 + if team_goals > opp_goals: + venue_home_wins += 1 + else: + home_goals_total += opp_goals + away_goals_total += team_goals + + n = len(recent) + result = { + "h2h_home_goals_avg": home_goals_total / n, + "h2h_away_goals_avg": away_goals_total / n, + "h2h_venue_advantage": venue_home_wins / venue_total if venue_total > 0 else 0.5, + } + + # Recent trend: last 3 vs overall + if len(h2h) >= 4: + last3_pts = sum( + 1.0 if m[2] > m[3] else (0.5 if m[2] == m[3] else 0.0) + for m in h2h[-3:] + ) / 3 + overall_pts = sum( + 1.0 if m[2] > m[3] else (0.5 if m[2] == m[3] else 0.0) + for m in h2h + ) / len(h2h) + result["h2h_recent_trend"] = round(last3_pts - overall_pts, 4) + else: + result["h2h_recent_trend"] = 0.0 + + return result + + +def calc_strength_diff( + home_form: Dict[str, float], + away_form: Dict[str, float], + home_elo: Dict[str, float], + away_elo: Dict[str, float], + home_momentum: float, + away_momentum: float, + upset_potential: float, +) -> Dict[str, float]: + """Calculate strength differential features.""" + # Attack vs Defense mismatches + h_attack = home_form.get("goals_avg", 1.3) + a_defense = away_form.get("conceded_avg", 1.2) + a_attack = away_form.get("goals_avg", 1.3) + h_defense = home_form.get("conceded_avg", 1.2) + + atk_def_home = h_attack - a_defense # positive = home attack > away defense + atk_def_away = a_attack - h_defense + + # XG diff approximation + xg_diff = (h_attack + a_defense) / 2 - (a_attack + h_defense) / 2 + + # Form × Momentum interaction + form_mom = (home_momentum - away_momentum) * ( + home_form.get("scoring_rate", 0.75) - away_form.get("scoring_rate", 0.75) + ) + + # ELO-Form consistency + elo_diff = home_elo.get("overall", 1500) - away_elo.get("overall", 1500) + form_diff = h_attack - a_attack + elo_form_consistency = 1.0 if (elo_diff > 0 and form_diff > 0) or (elo_diff < 0 and form_diff < 0) else 0.0 + + # Upset × ELO gap + elo_gap = abs(elo_diff) + upset_x_elo = upset_potential * (elo_gap / 400.0) + + return { + "attack_vs_defense_home": round(atk_def_home, 4), + "attack_vs_defense_away": round(atk_def_away, 4), + "xg_diff": round(xg_diff, 4), + "form_momentum_interaction": round(form_mom, 4), + "elo_form_consistency": elo_form_consistency, + "upset_x_elo_gap": round(upset_x_elo, 4), + } diff --git a/ai-engine/scripts/backtest_niche.py b/ai-engine/scripts/backtest_niche.py new file mode 100644 index 0000000..09be2e4 --- /dev/null +++ b/ai-engine/scripts/backtest_niche.py @@ -0,0 +1,215 @@ +""" +V27 FINAL BACKTEST — Conservative Flat Bet +Only the strongest validated edges. No Kelly compounding. +""" +import pandas as pd, numpy as np + +df = pd.read_csv('data/training_data_v27.csv', low_memory=False) +for c in df.columns: + if c not in ['match_id','league_name','home_team','away_team']: + df[c] = pd.to_numeric(df[c], errors='coerce') +df = df.dropna(subset=['odds_ms_h','odds_ms_d','odds_ms_a']) +df = df[(df.odds_ms_h>1.01)&(df.odds_ms_d>1.01)&(df.odds_ms_a>1.01)] + +n = len(df) +# 5-fold walk-forward: train on 60%, validate patterns, test on remaining +folds = 5 +fold_size = n // folds +all_results = [] + +print("="*65) +print(" V27 WALK-FORWARD FLAT-BET BACKTEST") +print("="*65) + +for fold in range(2, folds): # start from fold 2 so we have enough training data + train_end = fold * fold_size + test_start = train_end + test_end = (fold+1)*fold_size if fold < folds-1 else n + + train_df = df.iloc[:train_end] + test_df = df.iloc[test_start:test_end] + + print(f"\n --- Fold {fold}: train={len(train_df)}, test={len(test_df)} ---") + + # Discover REST edges from training data + strategies = [] + + for hr in [5, 7, 10, 14]: + for ar in [3, 4, 5]: + for cls, col in [(0,'odds_ms_h'), (2,'odds_ms_a')]: + idx = (train_df.home_days_rest > hr) & (train_df.away_days_rest < ar) + sub = train_df[idx] + if len(sub) < 50: + continue + rate = (sub.label_ms == cls).mean() + avg_odds = sub[col].mean() + ev = rate * avg_odds + if ev > 1.02: # only strong edges (>2% edge) + strategies.append((hr, ar, cls, rate, avg_odds, ev, len(sub))) + + if not strategies: + print(" No strong edges found in training data") + continue + + # Apply best strategies to test + strategies.sort(key=lambda x: x[5], reverse=True) + best = strategies[:3] # top 3 only + + fold_bets = 0 + fold_wins = 0 + fold_pnl = 0 + stake = 10 # flat 10 units + + for _, row in test_df.iterrows(): + for hr, ar, cls, est_p, _, _, _ in best: + if pd.isna(row.home_days_rest) or pd.isna(row.away_days_rest): + continue + if row.home_days_rest <= hr or row.away_days_rest >= ar: + continue + odds_col = ['odds_ms_h','odds_ms_d','odds_ms_a'][cls] + odds_val = row[odds_col] + if pd.isna(odds_val) or odds_val < 1.50 or odds_val > 5.0: + continue + # Additional filter: only bet when odds give reasonable EV + if est_p * odds_val < 1.0: + continue + + won = (row.label_ms == cls) + pnl = stake * (odds_val - 1) if won else -stake + fold_bets += 1 + if won: + fold_wins += 1 + fold_pnl += pnl + all_results.append({'fold': fold, 'won': won, 'pnl': pnl, + 'odds': odds_val, 'stake': stake, + 'cls': ['H','D','A'][cls]}) + + if fold_bets > 0: + roi = fold_pnl / (fold_bets * stake) * 100 + print(f" Best strategies: {[(h,a,['H','D','A'][c],f'EV={e:.3f}') for h,a,c,_,_,e,_ in best]}") + print(f" Bets: {fold_bets}, Wins: {fold_wins} ({fold_wins/fold_bets*100:.1f}%), " + f"ROI: {roi:+.1f}%, PnL: {fold_pnl:+.0f}") + +# Overall +print("\n" + "="*65) +print(" OVERALL RESULTS") +print("="*65) +if all_results: + total = len(all_results) + wins = sum(1 for r in all_results if r['won']) + total_pnl = sum(r['pnl'] for r in all_results) + total_staked = sum(r['stake'] for r in all_results) + roi = total_pnl / total_staked * 100 + + print(f" Total bets: {total}") + print(f" Wins: {wins} ({wins/total*100:.1f}%)") + print(f" Total staked: {total_staked:.0f}") + print(f" PnL: {total_pnl:+.0f}") + print(f" ROI: {roi:+.1f}%") + print(f" Avg odds: {np.mean([r['odds'] for r in all_results]):.2f}") + + # By class + print("\n --- By Bet Type ---") + for cls in ['H','A']: + cb = [r for r in all_results if r['cls'] == cls] + if cb: + cw = sum(1 for r in cb if r['won']) + cp = sum(r['pnl'] for r in cb) + cs = sum(r['stake'] for r in cb) + print(f" {cls}: {len(cb)} bets, hit={cw/len(cb)*100:.1f}%, ROI={cp/cs*100:+.1f}%") + + # Cumulative PnL curve + print("\n --- Cumulative PnL ---") + cum = 0 + step = max(1, total // 15) + for j in range(0, total, step): + cum = sum(r['pnl'] for r in all_results[:j+1]) + print(f" After bet {j+1:4d}: PnL={cum:+.0f}") + cum = sum(r['pnl'] for r in all_results) + print(f" After bet {total:4d}: PnL={cum:+.0f} (FINAL)") +else: + print(" No bets placed!") + +# ── Now combine with MODEL for smarter filtering ── +print("\n" + "="*65) +print(" COMBINED: Rest Rules + Fundamentals Model") +print("="*65) + +import pickle, json +from pathlib import Path +MODELS_DIR = Path("models/v27") + +feat_cols = json.load(open(MODELS_DIR / "v27_feature_cols.json")) +ms_models = {} +for name in ['xgb','lgb','cb']: + p = MODELS_DIR / f"v27_ms_{name}.pkl" + if p.exists(): + with open(p,'rb') as f: + ms_models[name] = pickle.load(f) + +if ms_models: + test_df = df.iloc[int(n*0.8):].copy() + X_test = test_df[feat_cols].values + + # Get model predictions + preds = [] + for name, m in ms_models.items(): + if name == 'xgb': + import xgboost as xgb + dm = xgb.DMatrix(X_test, feature_names=feat_cols) + preds.append(m.predict(dm)) + elif name == 'lgb': + preds.append(m.predict(X_test)) + elif name == 'cb': + preds.append(m.predict_proba(X_test)) + model_probs = np.mean(preds, axis=0) # (n, 3) + + # Now apply rest rules + model agreement + margin = 1/test_df.odds_ms_h.values + 1/test_df.odds_ms_d.values + 1/test_df.odds_ms_a.values + impl = np.column_stack([ + (1/test_df.odds_ms_h.values)/margin, + (1/test_df.odds_ms_d.values)/margin, + (1/test_df.odds_ms_a.values)/margin, + ]) + + combo_bets = 0 + combo_wins = 0 + combo_pnl = 0 + + for j in range(len(test_df)): + row = test_df.iloc[j] + for hr, ar in [(14,5),(10,5),(7,5),(5,5)]: + if pd.isna(row.home_days_rest) or pd.isna(row.away_days_rest): + continue + if row.home_days_rest <= hr or row.away_days_rest >= ar: + continue + for cls in [0, 2]: + odds_val = [row.odds_ms_h, row.odds_ms_d, row.odds_ms_a][cls] + if pd.isna(odds_val) or odds_val < 1.50 or odds_val > 5.0: + continue + + model_p = model_probs[j, cls] + impl_p = impl[j, cls] + + # DOUBLE FILTER: rest rule + model agrees (model_prob > implied) + if model_p <= impl_p: + continue # model disagrees, skip + edge = model_p - impl_p + if edge < 0.03: + continue # too small + + won = (row.label_ms == cls) + pnl = 10 * (odds_val - 1) if won else -10 + combo_bets += 1 + if won: + combo_wins += 1 + combo_pnl += pnl + + if combo_bets > 0: + roi = combo_pnl / (combo_bets * 10) * 100 + print(f" Bets: {combo_bets}") + print(f" Wins: {combo_wins} ({combo_wins/combo_bets*100:.1f}%)") + print(f" PnL: {combo_pnl:+.0f}") + print(f" ROI: {roi:+.1f}%") + else: + print(" No combined bets triggered") diff --git a/ai-engine/scripts/conditional_frequency_engine.py b/ai-engine/scripts/conditional_frequency_engine.py new file mode 100644 index 0000000..3fdac9e --- /dev/null +++ b/ai-engine/scripts/conditional_frequency_engine.py @@ -0,0 +1,312 @@ +""" +V28 — CONDITIONAL FREQUENCY ENGINE +==================================== +User's strategy automated at scale: + +For every match (e.g. Beşiktaş vs Konya): + 1. Look at Beşiktaş's HOME history when their MS1 odds were in the same band (e.g. 1.30-1.40) + → What % of those matches ended OU 1.5 over? OU 2.5 over? MS1? + 2. Look at Konya's AWAY history when their MS2 odds were in the same band (e.g. 2.00-2.20) + → Same questions + 3. COMBINE both signals: + → If BOTH teams historically produce >80% OU1.5 over at these odds → BET OU1.5 over + → This is the user's exact Excel strategy, now running on 104K matches + +CRITICAL: Only uses PAST matches for each prediction (no future leakage) +""" +import pandas as pd +import numpy as np +from collections import defaultdict +import warnings +warnings.filterwarnings('ignore') + +# ─── Load Data ─── +print("Loading data...") +df = pd.read_csv('data/training_data_v27.csv', low_memory=False) +KEEP_STR = ['match_id', 'league_name', 'home_team', 'away_team', + 'home_team_id', 'away_team_id', 'league_id', 'mst_utc'] +for c in df.columns: + if c not in KEEP_STR: + df[c] = pd.to_numeric(df[c], errors='coerce') + +# Ensure chronological order (by match_id or date) +if 'mst_utc' in df.columns: + df['mst_utc'] = pd.to_datetime(df['mst_utc'], errors='coerce') + df = df.sort_values('mst_utc').reset_index(drop=True) + +# Filter: need valid odds + scores +df = df.dropna(subset=['odds_ms_h', 'odds_ms_a', 'score_home', 'score_away', + 'home_team_id', 'away_team_id', 'label_ms']) + +# Compute actual goal labels +df['total_goals'] = df['score_home'] + df['score_away'] +df['ou15_actual'] = (df['total_goals'] > 1.5).astype(int) +df['ou25_actual'] = (df['total_goals'] > 2.5).astype(int) +df['ou35_actual'] = (df['total_goals'] > 3.5).astype(int) +df['btts_actual'] = ((df['score_home'] > 0) & (df['score_away'] > 0)).astype(int) +df['ms_result'] = df['label_ms'].astype(int) # 0=H, 1=D, 2=A + +N = len(df) +print(f"Total matches: {N}") +print(f"Unique home teams: {df.home_team_id.nunique()}") +print(f"Unique away teams: {df.away_team_id.nunique()}") + +# ─── Odds Band Helper ─── +def get_odds_band(odds, band_width=0.10): + """Round odds to nearest band. E.g. 1.35 → (1.30, 1.40)""" + lower = round(np.floor(odds / band_width) * band_width, 2) + upper = round(lower + band_width, 2) + return (lower, upper) + +def get_odds_band_wide(odds): + """Wider band for less common teams. E.g. 1.35 → (1.20, 1.50)""" + if odds < 1.50: + return (1.01, 1.50) + elif odds < 2.00: + return (1.50, 2.00) + elif odds < 2.50: + return (2.00, 2.50) + elif odds < 3.00: + return (2.50, 3.00) + elif odds < 4.00: + return (3.00, 4.00) + elif odds < 6.00: + return (4.00, 6.00) + else: + return (6.00, 20.00) + +# ─── Build Conditional Frequency Lookup (Expanding Window) ─── +print("\nBuilding conditional frequency features (expanding window)...") + +# We'll compute features for each match using only past data +MIN_MATCHES = 5 # minimum historical matches to generate a signal + +# Pre-allocate feature arrays +feat_names = [ + 'home_ou15_rate_at_band', 'home_ou25_rate_at_band', 'home_ou35_rate_at_band', + 'home_btts_rate_at_band', 'home_win_rate_at_band', 'home_n_at_band', + 'away_ou15_rate_at_band', 'away_ou25_rate_at_band', 'away_ou35_rate_at_band', + 'away_btts_rate_at_band', 'away_win_rate_at_band', 'away_n_at_band', + 'combined_ou15', 'combined_ou25', 'combined_ou35', 'combined_btts', + 'home_goals_at_band', 'away_goals_at_band', 'combined_goals_at_band', + 'home_conceded_at_band', 'away_conceded_at_band', +] +features = np.full((N, len(feat_names)), np.nan) + +# Historical ledger: team_id → list of (odds_band, ou15, ou25, ou35, btts, ms_result, goals_scored, goals_conceded) +home_history = defaultdict(list) # team performances when playing HOME +away_history = defaultdict(list) # team performances when playing AWAY + +for i in range(N): + row = df.iloc[i] + ht_id = row.home_team_id + at_id = row.away_team_id + h_odds = row.odds_ms_h + a_odds = row.odds_ms_a + + if pd.isna(h_odds) or pd.isna(a_odds): + continue + + h_band = get_odds_band_wide(h_odds) + a_band = get_odds_band_wide(a_odds) + + # ── Look up HOME team's historical performance at this odds band ── + h_hist = [x for x in home_history[ht_id] if h_band[0] <= x[0] < h_band[1]] + if len(h_hist) >= MIN_MATCHES: + features[i, 0] = np.mean([x[1] for x in h_hist]) # ou15 rate + features[i, 1] = np.mean([x[2] for x in h_hist]) # ou25 rate + features[i, 2] = np.mean([x[3] for x in h_hist]) # ou35 rate + features[i, 3] = np.mean([x[4] for x in h_hist]) # btts rate + features[i, 4] = np.mean([x[5] for x in h_hist]) # win rate (home win = 1 if ms==0) + features[i, 5] = len(h_hist) + features[i, 16] = np.mean([x[6] for x in h_hist]) # avg goals scored + features[i, 19] = np.mean([x[7] for x in h_hist]) # avg goals conceded + + # ── Look up AWAY team's historical performance at this odds band ── + a_hist = [x for x in away_history[at_id] if a_band[0] <= x[0] < a_band[1]] + if len(a_hist) >= MIN_MATCHES: + features[i, 6] = np.mean([x[1] for x in a_hist]) # ou15 rate + features[i, 7] = np.mean([x[2] for x in a_hist]) # ou25 rate + features[i, 8] = np.mean([x[3] for x in a_hist]) # ou35 rate + features[i, 9] = np.mean([x[4] for x in a_hist]) # btts rate + features[i, 10] = np.mean([x[5] for x in a_hist]) # away win rate + features[i, 11] = len(a_hist) + features[i, 17] = np.mean([x[6] for x in a_hist]) # avg goals scored (away) + features[i, 20] = np.mean([x[7] for x in a_hist]) # avg goals conceded (away) + + # ── Combined signals ── + if not np.isnan(features[i, 0]) and not np.isnan(features[i, 6]): + features[i, 12] = (features[i, 0] + features[i, 6]) / 2 # combined ou15 + features[i, 13] = (features[i, 1] + features[i, 7]) / 2 # combined ou25 + features[i, 14] = (features[i, 2] + features[i, 8]) / 2 # combined ou35 + features[i, 15] = (features[i, 3] + features[i, 9]) / 2 # combined btts + features[i, 18] = features[i, 16] + features[i, 17] # combined goals + + # ── Add THIS match to history (for future lookups) ── + ou15 = int(row.total_goals > 1.5) + ou25 = int(row.total_goals > 2.5) + ou35 = int(row.total_goals > 3.5) + btts = int(row.score_home > 0 and row.score_away > 0) + h_won = int(row.label_ms == 0) + a_won = int(row.label_ms == 2) + + home_history[ht_id].append((h_odds, ou15, ou25, ou35, btts, h_won, + row.score_home, row.score_away)) + away_history[at_id].append((a_odds, ou15, ou25, ou35, btts, a_won, + row.score_away, row.score_home)) + + if (i+1) % 20000 == 0: + valid = np.sum(~np.isnan(features[:i+1, 12])) + print(f" Processed {i+1}/{N} matches, {valid} with combined signals") + +# Count valid features +valid_mask = ~np.isnan(features[:, 12]) +print(f"\nMatches with combined conditional signals: {valid_mask.sum()} / {N}") + +# ─── BACKTEST: Walk-Forward ─── +print("\n" + "="*70) +print(" CONDITIONAL FREQUENCY BACKTEST") +print("="*70) + +# Only test on last 20% of data (to avoid early sparse data) +test_start = int(N * 0.7) +test_idx = range(test_start, N) +test_valid = [i for i in test_idx if valid_mask[i]] +print(f"Test window: matches {test_start}-{N} ({len(test_valid)} with signals)") + +# Strategy: bet on OU1.5 over when combined_ou15 > threshold +markets = [ + ('OU 1.5 Over', 'combined_ou15', 12, 'ou15_actual', 'odds_ou15_o'), + ('OU 2.5 Over', 'combined_ou25', 13, 'ou25_actual', 'odds_ou25_o'), + ('OU 3.5 Over', 'combined_ou35', 14, 'ou35_actual', 'odds_ou35_o'), + ('BTTS Yes', 'combined_btts', 15, 'btts_actual', 'odds_btts_y'), +] + +for market_name, feat_key, feat_idx, label_col, odds_col in markets: + print(f"\n ── {market_name} ──") + + if odds_col not in df.columns: + print(f" No odds column '{odds_col}', skipping") + continue + + for threshold in [0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90]: + bets = 0 + wins = 0 + pnl = 0.0 + + for i in test_valid: + signal = features[i, feat_idx] + if np.isnan(signal) or signal < threshold: + continue + odds_val = df.iloc[i][odds_col] + if pd.isna(odds_val) or odds_val < 1.05: + continue + actual = df.iloc[i][label_col] + if pd.isna(actual): + continue + + bets += 1 + if actual == 1: + wins += 1 + pnl += odds_val - 1 + else: + pnl -= 1 + + if bets >= 20: + roi = pnl / bets * 100 + hit = wins / bets * 100 + ev = (wins/bets) * (pnl/wins + 1) if wins > 0 else 0 + marker = " *** PROFITABLE ***" if roi > 0 else "" + print(f" Threshold>{threshold:.2f}: {bets:5d} bets, " + f"hit={hit:.1f}%, ROI={roi:+.1f}%{marker}") + +# Also test MS (1X2) market +print(f"\n ── Maç Sonucu (1X2) ──") +# Home win when home_win_rate_at_band > X AND away team loses often at that band +for threshold in [0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80]: + bets = wins = 0 + pnl = 0.0 + for i in test_valid: + h_wr = features[i, 4] # home win rate at band + a_lr = 1 - features[i, 10] if not np.isnan(features[i, 10]) else np.nan # away loss rate + if np.isnan(h_wr) or np.isnan(a_lr): + continue + combined = (h_wr + a_lr) / 2 + if combined < threshold: + continue + odds_val = df.iloc[i].odds_ms_h + if pd.isna(odds_val) or odds_val < 1.10 or odds_val > 5.0: + continue + bets += 1 + if df.iloc[i].label_ms == 0: + wins += 1 + pnl += odds_val - 1 + else: + pnl -= 1 + if bets >= 20: + roi = pnl / bets * 100 + hit = wins / bets * 100 + marker = " *** PROFITABLE ***" if roi > 0 else "" + print(f" Home win comb>{threshold:.2f}: {bets:5d} bets, " + f"hit={hit:.1f}%, ROI={roi:+.1f}%{marker}") + +# ─── DEEP DIVE: Best performing niches ─── +print("\n" + "="*70) +print(" DEEP DIVE: Combined OU15 + Odds Value Filter") +print("="*70) + +# The user's strategy: high confidence + the odds must pay enough +for threshold in [0.75, 0.80, 0.85, 0.90]: + for min_odds in [1.10, 1.20, 1.30, 1.40]: + bets = wins = 0 + pnl = 0.0 + for i in test_valid: + signal = features[i, 12] # combined ou15 + if np.isnan(signal) or signal < threshold: + continue + odds_val = df.iloc[i].get('odds_ou15_o', np.nan) if 'odds_ou15_o' in df.columns else np.nan + if pd.isna(odds_val) or odds_val < min_odds: + continue + actual = df.iloc[i].ou15_actual + + bets += 1 + if actual == 1: + wins += 1 + pnl += odds_val - 1 + else: + pnl -= 1 + + if bets >= 30: + roi = pnl / bets * 100 + hit = wins / bets * 100 + if roi > -5: # show near-profitable too + marker = " *** PROFITABLE ***" if roi > 0 else "" + print(f" OU15 sig>{threshold:.2f} odds>{min_odds}: " + f"{bets:5d} bets, hit={hit:.1f}%, ROI={roi:+.1f}%{marker}") + +# ─── Additional: Goal expectation accuracy ─── +print("\n" + "="*70) +print(" GOAL PREDICTION ACCURACY") +print("="*70) +valid_goals = [i for i in test_valid if not np.isnan(features[i, 18])] +if valid_goals: + pred_goals = [features[i, 18] for i in valid_goals] + actual_goals = [df.iloc[i].total_goals for i in valid_goals] + from sklearn.metrics import mean_absolute_error + mae = mean_absolute_error(actual_goals, pred_goals) + corr = np.corrcoef(pred_goals, actual_goals)[0, 1] + print(f" Combined goal prediction MAE: {mae:.3f}") + print(f" Correlation: {corr:.4f}") + print(f" Avg predicted: {np.mean(pred_goals):.2f}, Avg actual: {np.mean(actual_goals):.2f}") + + # Bucket analysis + print("\n Goal prediction buckets:") + for low, high in [(0, 1.5), (1.5, 2.0), (2.0, 2.5), (2.5, 3.0), (3.0, 3.5), (3.5, 5.0)]: + bucket = [i for i, pg in zip(valid_goals, pred_goals) if low <= pg < high] + if len(bucket) >= 20: + avg_actual = np.mean([df.iloc[i].total_goals for i in bucket]) + ou25_rate = np.mean([df.iloc[i].ou25_actual for i in bucket]) + print(f" Predicted {low:.1f}-{high:.1f}: n={len(bucket)}, " + f"actual_avg={avg_actual:.2f}, OU25%={ou25_rate*100:.1f}%") + +print("\nDone!") diff --git a/ai-engine/scripts/extract_training_data.py b/ai-engine/scripts/extract_training_data.py index 8a6fda2..87dc015 100755 --- a/ai-engine/scripts/extract_training_data.py +++ b/ai-engine/scripts/extract_training_data.py @@ -1071,13 +1071,13 @@ class FeatureExtractor: for mst, poss, sot, total_shots, corners, team_goals in rows: if poss and poss > 0: - poss_sum += poss + poss_sum += float(poss) poss_count += 1 - sot_sum += sot or 0 - shots_sum += total_shots or 0 - corners_sum += corners or 0 + sot_sum += float(sot or 0) + shots_sum += float(total_shots or 0) + corners_sum += float(corners or 0) - goals_scored += team_goals or 0 + goals_scored += float(team_goals or 0) return { "possession": (poss_sum / poss_count / 100) if poss_count > 0 else 0.50, diff --git a/ai-engine/scripts/extract_training_data_v27.py b/ai-engine/scripts/extract_training_data_v27.py new file mode 100644 index 0000000..fc975c6 --- /dev/null +++ b/ai-engine/scripts/extract_training_data_v27.py @@ -0,0 +1,305 @@ +""" +V27 Training Data Extraction - Value Sniper +Extends V25 to ALL matches with odds (~104K). +Adds rolling window, league quality, time, H2H, strength features. +Usage: python3 scripts/extract_training_data_v27.py +""" +import os, sys, csv, time +from collections import defaultdict + +AI_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, AI_DIR) + +from scripts.extract_training_data import ( + BatchDataLoader as V25Loader, + FeatureExtractor as V25Extractor, + FEATURE_COLS as V25_COLS, + get_conn, +) +from features.rolling_features import ( + calc_rolling_features, calc_league_quality, + calc_time_features, calc_advanced_h2h, calc_strength_diff, +) + +OUTPUT = os.path.join(AI_DIR, "data", "training_data_v27.csv") +os.makedirs(os.path.dirname(OUTPUT), exist_ok=True) + +V27_NEW = [ + "home_rolling5_goals","home_rolling5_conceded", + "home_rolling10_goals","home_rolling10_conceded", + "home_rolling20_goals","home_rolling20_conceded", + "away_rolling5_goals","away_rolling5_conceded", + "away_rolling10_goals","away_rolling10_conceded", + "home_rolling5_cs","away_rolling5_cs", + "home_venue_goals","home_venue_conceded", + "away_venue_goals","away_venue_conceded", + "home_goal_trend","away_goal_trend", + "league_home_win_rate","league_draw_rate", + "league_btts_rate","league_ou25_rate", + "league_reliability_score", + "home_days_rest","away_days_rest", + "match_month","is_season_start","is_season_end", + "h2h_home_goals_avg","h2h_away_goals_avg", + "h2h_recent_trend","h2h_venue_advantage", + "attack_vs_defense_home","attack_vs_defense_away", + "xg_diff","form_momentum_interaction", + "elo_form_consistency","upset_x_elo_gap", +] +ALL_COLS = V25_COLS + V27_NEW + + +class V27Loader(V25Loader): + """Load ALL matches with odds, not just top leagues.""" + def __init__(self, conn): + super().__init__(conn, []) + self.league_matches_cache = {} + + def _load_matches(self): + self.cur.execute(""" + SELECT m.id, m.home_team_id, m.away_team_id, + m.score_home, m.score_away, + m.ht_score_home, m.ht_score_away, + m.mst_utc, m.league_id, + ht.name, at.name, l.name + FROM matches m + JOIN teams ht ON m.home_team_id = ht.id + JOIN teams at ON m.away_team_id = at.id + JOIN leagues l ON m.league_id = l.id + WHERE m.status='FT' AND m.score_home IS NOT NULL + AND m.sport='football' + AND EXISTS(SELECT 1 FROM odd_categories oc WHERE oc.match_id=m.id) + ORDER BY m.mst_utc ASC + """) + self.matches = self.cur.fetchall() + + def _load_odds(self): + self.cur.execute(""" + SELECT oc.match_id, oc.name, os.name, os.odd_value + FROM odd_selections os + JOIN odd_categories oc ON os.odd_category_db_id=oc.db_id + JOIN matches m ON oc.match_id=m.id + WHERE m.status='FT' AND m.sport='football' + """) + for mid, cat, sel, val in self.cur.fetchall(): + try: + v = float(val) if val else 0 + if v <= 0 or not cat or not sel: continue + if mid not in self.odds_cache: self.odds_cache[mid] = {} + c = cat.lower().strip() + s = sel.lower().strip() + o = self.odds_cache[mid] + if c == 'maç sonucu': + if sel=='1': o['ms_h']=v + elif sel in('0','X'): o['ms_d']=v + elif sel=='2': o['ms_a']=v + elif c == '1. yarı sonucu': + if sel=='1': o['ht_ms_h']=v + elif sel in('0','X'): o['ht_ms_d']=v + elif sel=='2': o['ht_ms_a']=v + elif c == 'karşılıklı gol': + if 'var' in s: o['btts_y']=v + elif 'yok' in s: o['btts_n']=v + elif c == '2,5 alt/üst': + if 'alt' in s: o['ou25_u']=v + elif 'üst' in s: o['ou25_o']=v + elif c == '1,5 alt/üst': + if 'alt' in s: o['ou15_u']=v + elif 'üst' in s: o['ou15_o']=v + elif c == '3,5 alt/üst': + if 'alt' in s: o['ou35_u']=v + elif 'üst' in s: o['ou35_o']=v + elif c == '0,5 alt/üst': + if 'alt' in s: o['ou05_u']=v + elif 'üst' in s: o['ou05_o']=v + elif c == '1. yarı 0,5 alt/üst': + if 'alt' in s: o['ht_ou05_u']=v + elif 'üst' in s: o['ht_ou05_o']=v + elif c == '1. yarı 1,5 alt/üst': + if 'alt' in s: o['ht_ou15_u']=v + elif 'üst' in s: o['ht_ou15_o']=v + except (ValueError, TypeError): pass + + def _load_league_stats(self): + self.cur.execute(""" + SELECT league_id, + AVG(score_home+score_away), AVG(CASE WHEN score_home=0 AND score_away=0 THEN 1.0 ELSE 0.0 END), + COUNT(*) + FROM matches WHERE status='FT' AND score_home IS NOT NULL AND sport='football' + GROUP BY league_id + """) + for lid, ag, zr, cnt in self.cur.fetchall(): + self.league_stats_cache[lid] = { + "avg_goals": float(ag) if ag else 2.5, + "zero_rate": float(zr) if zr else 0.07, + "match_count": cnt + } + + def _load_squad_data(self): + self.cur.execute(""" + SELECT mpp.match_id, mpp.team_id, + COUNT(*) FILTER(WHERE mpp.is_starting=true), + COUNT(*), + COUNT(*) FILTER(WHERE mpp.is_starting=true + AND LOWER(COALESCE(mpp.position::TEXT,''))~'(forward|fwd|forvet|striker)') + FROM match_player_participation mpp + JOIN matches m ON mpp.match_id=m.id + WHERE m.status='FT' AND m.sport='football' + GROUP BY mpp.match_id, mpp.team_id + """) + part = {} + for mid,tid,st,tot,fwd in self.cur.fetchall(): + part[(mid,tid)]={'starting_count':st or 0,'total_squad':tot or 0,'fwd_count':fwd or 0} + + self.cur.execute(""" + SELECT mpe.match_id, mpe.team_id, + COUNT(*) FILTER(WHERE mpe.event_type='goal' AND COALESCE(mpe.event_subtype,'') NOT ILIKE '%%penaltı kaçırma%%'), + COUNT(DISTINCT mpe.assist_player_id) FILTER(WHERE mpe.event_type='goal' AND mpe.assist_player_id IS NOT NULL), + COUNT(DISTINCT mpe.player_id) FILTER(WHERE mpe.event_type='goal' AND COALESCE(mpe.event_subtype,'') NOT ILIKE '%%penaltı kaçırma%%') + FROM match_player_events mpe + JOIN matches m ON mpe.match_id=m.id + WHERE m.status='FT' AND m.sport='football' + GROUP BY mpe.match_id, mpe.team_id + """) + evts = {} + for mid,tid,g,a,sc in self.cur.fetchall(): + evts[(mid,tid)]={'goals':g or 0,'assists':a or 0,'unique_scorers':sc or 0} + + self.cur.execute(""" + SELECT mpe.team_id, mpe.player_id, COUNT(*) + FROM match_player_events mpe JOIN matches m ON mpe.match_id=m.id + WHERE m.status='FT' AND m.sport='football' AND mpe.event_type='goal' + AND COALESCE(mpe.event_subtype,'') NOT ILIKE '%%penaltı kaçırma%%' + GROUP BY mpe.team_id, mpe.player_id HAVING COUNT(*)>=3 + """) + kp_by_team = defaultdict(set) + for tid,pid,_ in self.cur.fetchall(): kp_by_team[tid].add(pid) + + self.cur.execute(""" + SELECT mpp.match_id, mpp.team_id, mpp.player_id + FROM match_player_participation mpp JOIN matches m ON mpp.match_id=m.id + WHERE mpp.is_starting=true AND m.status='FT' AND m.sport='football' + """) + starters = defaultdict(list) + for mid,tid,pid in self.cur.fetchall(): starters[(mid,tid)].append(pid) + + for key in set(part)|set(evts): + mid,tid = key + p = part.get(key,{'starting_count':0,'total_squad':0,'fwd_count':0}) + e = evts.get(key,{'goals':0,'assists':0,'unique_scorers':0}) + s = starters.get(key,[]) + kp_in = sum(1 for x in s if x in kp_by_team.get(tid,set())) + kp_tot = len(kp_by_team.get(tid,set())) + kp_miss = max(0, kp_tot - kp_in) + sq = p['starting_count']*0.3 + e['goals']*2.0 + e['assists']*1.0 + kp_in*3.0 + p['fwd_count']*1.5 + mi = min(kp_miss/max(kp_tot,1), 1.0) + self.squad_cache[key] = {'squad_quality':sq,'key_players':kp_in,'missing_impact':mi,'goals_form':e['goals']} + + def _load_cards_data(self): + self.cur.execute(""" + SELECT mpe.match_id, + SUM(CASE WHEN mpe.event_type::text LIKE '%%yellow_card%%' THEN 1 + WHEN mpe.event_type::text LIKE '%%red_card%%' THEN 2 ELSE 1 END) + FROM match_player_events mpe JOIN matches m ON mpe.match_id=m.id + WHERE m.status='FT' AND m.sport='football' AND mpe.event_type::text LIKE '%%card%%' + GROUP BY mpe.match_id + """) + for mid, cw in self.cur.fetchall(): + self.cards_cache[mid] = float(cw) if cw else 0.0 + + def load_league_matches(self): + for m in self.matches: + lid = m[8] + if lid not in self.league_matches_cache: + self.league_matches_cache[lid] = [] + self.league_matches_cache[lid].append((m[7],None,m[3],m[4],None)) + + +class V27Extractor(V25Extractor): + """Adds V27 features on top of V25.""" + def _extract_one(self, mid, hid, aid, sh, sa, hth, hta, mst, lid, + hn, an, ln): + row = super()._extract_one(mid,hid,aid,sh,sa,hth,hta,mst,lid,hn,an,ln) + if not row: return None + + hm = self.loader.team_matches.get(hid,[]) + am = self.loader.team_matches.get(aid,[]) + + hr = calc_rolling_features(hm, mst, True) + ar = calc_rolling_features(am, mst, False) + for pfx,r in [("home",hr),("away",ar)]: + row[f"{pfx}_rolling5_goals"]=r["rolling5_goals_avg"] + row[f"{pfx}_rolling5_conceded"]=r["rolling5_conceded_avg"] + row[f"{pfx}_rolling10_goals"]=r["rolling10_goals_avg"] + row[f"{pfx}_rolling10_conceded"]=r["rolling10_conceded_avg"] + row[f"{pfx}_rolling20_goals"]=r["rolling20_goals_avg"] + row[f"{pfx}_rolling20_conceded"]=r["rolling20_conceded_avg"] + row[f"{pfx}_rolling5_cs"]=r["rolling5_clean_sheets"] + row[f"{pfx}_venue_goals"]=r["venue_goals_avg"] + row[f"{pfx}_venue_conceded"]=r["venue_conceded_avg"] + row[f"{pfx}_goal_trend"]=r["goal_trend"] + + lb = [x for x in self.loader.league_matches_cache.get(lid,[]) if x[0]0) + md = defaultdict(int) + for r in rows: md[r["label_ms"]]+=1 + print(f"\n📊 Summary:") + print(f" Rows: {n}") + print(f" With odds: {wo} ({wo/n*100:.1f}%)") + print(f" Features: {len(ALL_COLS)} ({len(V25_COLS)} V25 + {len(V27_NEW)} new)") + print(f" MS: H={md[0]/n*100:.1f}% D={md[1]/n*100:.1f}% A={md[2]/n*100:.1f}%") + print(f" Time: {(time.time()-t0)/60:.1f}min") + print(f"\n✅ Done! → {OUTPUT}") + conn.close() + +if __name__=="__main__": + main() diff --git a/ai-engine/scripts/strategy_generator.py b/ai-engine/scripts/strategy_generator.py new file mode 100644 index 0000000..0ebbfe6 --- /dev/null +++ b/ai-engine/scripts/strategy_generator.py @@ -0,0 +1,317 @@ +""" +Strategy Generator — Senin Excel mantığını DB üzerinde otomatize eder. + +Mantık: +1. Ev sahibi takım X, evinde oran bandı Y'de oynadığında → OU1.5/OU2.5/BTTS oranları +2. Deplasman takım Z, deplasmanda oran bandı W'de oynadığında → OU1.5/OU2.5/BTTS oranları +3. İkisi de yüksekse → STRATEJİ ÜRET + +Çıktı: Her maç için hangi bahis oynanabilir, neden, ve geçmiş başarı oranı +""" +import psycopg2 +import pandas as pd +import numpy as np +from collections import defaultdict +from datetime import datetime + +# DB connection +conn = psycopg2.connect( + host="localhost", + port=15432, + dbname="boilerplate_db", + user="suggestbet", + password="SuGGesT2026SecuRe" +) + +print("=" * 70) +print(" STRATEGY GENERATOR — Veritabanından Strateji Üretimi") +print("=" * 70) + +# 1. Tüm biten maçları, takım adları ve MS oranlarıyla çek +query = """ +SELECT + m.id as match_id, + m.home_team_id, + m.away_team_id, + m.league_id, + m.score_home, + m.score_away, + m.mst_utc, + ht.name as home_team, + at.name as away_team, + l.name as league_name +FROM matches m +JOIN teams ht ON m.home_team_id = ht.id +JOIN teams at ON m.away_team_id = at.id +JOIN leagues l ON m.league_id = l.id +WHERE m.status = 'FT' +AND m.score_home IS NOT NULL +ORDER BY m.mst_utc ASC +""" +df = pd.read_sql(query, conn) +print(f"\nToplam biten maç: {len(df):,}") + +# 2. Tüm oranları çek (MS, OU25, BTTS, OU15) +odds_query = """ +SELECT + oc.match_id, + oc.name as market, + os.name as selection, + CAST(os.odd_value AS DECIMAL) as odds +FROM odd_categories oc +JOIN odd_selections os ON os.odd_category_db_id = oc.db_id +WHERE oc.name IN ( + 'Maç Sonucu', + '2,5 Alt/Üst', + '1,5 Alt/Üst', + '3,5 Alt/Üst', + 'Karşılıklı Gol' +) +""" +odds_df = pd.read_sql(odds_query, conn) +print(f"Toplam oran kaydı: {len(odds_df):,}") + +# Pivot: her maç için oranları sütunlara çevir +def get_odds(match_id, market, selection): + mask = (odds_df.match_id == match_id) & (odds_df.market == market) & (odds_df.selection == selection) + vals = odds_df.loc[mask, 'odds'] + return float(vals.iloc[0]) if len(vals) > 0 else None + +# Daha verimli: oran lookup dict oluştur +print("Oran lookup oluşturuluyor...") +odds_lookup = {} +for _, row in odds_df.iterrows(): + key = (row.match_id, row.market, row.selection) + odds_lookup[key] = float(row.odds) + +def get_o(mid, market, sel): + return odds_lookup.get((mid, market, sel)) + +# 3. Her maça oranları ekle +print("Maçlara oranlar ekleniyor...") +df['odds_ms_h'] = df.match_id.map(lambda x: get_o(x, 'Maç Sonucu', '1')) +df['odds_ms_a'] = df.match_id.map(lambda x: get_o(x, 'Maç Sonucu', '2')) +df['odds_ms_d'] = df.match_id.map(lambda x: get_o(x, 'Maç Sonucu', '0')) +df['odds_ou25_o'] = df.match_id.map(lambda x: get_o(x, '2,5 Alt/Üst', 'Üst')) +df['odds_ou25_u'] = df.match_id.map(lambda x: get_o(x, '2,5 Alt/Üst', 'Alt')) +df['odds_ou15_o'] = df.match_id.map(lambda x: get_o(x, '1,5 Alt/Üst', 'Üst')) +df['odds_ou15_u'] = df.match_id.map(lambda x: get_o(x, '1,5 Alt/Üst', 'Alt')) +df['odds_ou35_o'] = df.match_id.map(lambda x: get_o(x, '3,5 Alt/Üst', 'Üst')) +df['odds_ou35_u'] = df.match_id.map(lambda x: get_o(x, '3,5 Alt/Üst', 'Alt')) +df['odds_btts_y'] = df.match_id.map(lambda x: get_o(x, 'Karşılıklı Gol', 'Var')) +df['odds_btts_n'] = df.match_id.map(lambda x: get_o(x, 'Karşılıklı Gol', 'Yok')) + +# Sonuç hesapla +df['total_goals'] = df.score_home + df.score_away +df['ou15'] = (df.total_goals > 1).astype(int) +df['ou25'] = (df.total_goals > 2).astype(int) +df['ou35'] = (df.total_goals > 3).astype(int) +df['btts'] = ((df.score_home > 0) & (df.score_away > 0)).astype(int) + +print(f"Oranı olan maç sayısı: {df.odds_ms_h.notna().sum():,}") + +# 4. ORAN BANDI fonksiyonu +def odds_band(odds): + if pd.isna(odds): return None + if odds < 1.30: return '1.00-1.30' + if odds < 1.50: return '1.30-1.50' + if odds < 1.80: return '1.50-1.80' + if odds < 2.20: return '1.80-2.20' + if odds < 2.80: return '2.20-2.80' + if odds < 4.00: return '2.80-4.00' + if odds < 6.00: return '4.00-6.00' + return '6.00+' + +# 5. STRATEJİ: Expanding window — sadece geçmiş veriye bakarak tahmin +print("\n" + "=" * 70) +print(" STRATEJİ BACKTEST — Expanding Window") +print("=" * 70) + +# Ev sahibi geçmişi: {team_id: {odds_band: [ou15, ou25, btts, ou35, ...]}} +home_history = defaultdict(lambda: defaultdict(list)) +away_history = defaultdict(lambda: defaultdict(list)) + +MIN_MATCHES = 8 # Minimum geçmiş maç sayısı +TEST_PCT = 0.30 # Son %30 test +N = len(df) +test_start = int(N * (1 - TEST_PCT)) + +results = { + 'ou15_over': [], 'ou25_over': [], 'ou35_over': [], + 'btts_yes': [], 'btts_no': [], + 'ou25_under': [], 'ou15_under': [], + 'ms_home': [] +} + +for i in range(N): + row = df.iloc[i] + h_odds = row.odds_ms_h + a_odds = row.odds_ms_a + + if pd.isna(h_odds) or pd.isna(a_odds): + continue + + h_band = odds_band(h_odds) + a_band = odds_band(a_odds) + + # TEST: sadece test bölümünde bahis yap + if i >= test_start: + h_hist = home_history[row.home_team_id][h_band] + a_hist = away_history[row.away_team_id][a_band] + + if len(h_hist) >= MIN_MATCHES and len(a_hist) >= MIN_MATCHES: + # Ev sahibi bu oran bandında ne yapmış? + h_ou15 = np.mean([x[0] for x in h_hist]) + h_ou25 = np.mean([x[1] for x in h_hist]) + h_ou35 = np.mean([x[2] for x in h_hist]) + h_btts = np.mean([x[3] for x in h_hist]) + h_win = np.mean([x[4] for x in h_hist]) + + # Deplasman bu oran bandında ne yapmış? + a_ou15 = np.mean([x[0] for x in a_hist]) + a_ou25 = np.mean([x[1] for x in a_hist]) + a_ou35 = np.mean([x[2] for x in a_hist]) + a_btts = np.mean([x[3] for x in a_hist]) + a_loss = np.mean([x[4] for x in a_hist]) # deplasman kaybetme oranı + + # KOMBİNE SİNYAL + sig_ou15 = (h_ou15 + a_ou15) / 2 + sig_ou25 = (h_ou25 + a_ou25) / 2 + sig_ou35 = (h_ou35 + a_ou35) / 2 + sig_btts = (h_btts + a_btts) / 2 + sig_hw = (h_win + a_loss) / 2 # ev kazanma + deplasman kaybetme + + base = { + 'match': f"{row.home_team} vs {row.away_team}", + 'league': row.league_name, + 'home_team': row.home_team, + 'away_team': row.away_team, + 'h_band': h_band, + 'a_band': a_band, + 'h_n': len(h_hist), + 'a_n': len(a_hist), + } + + # OU 1.5 OVER + if sig_ou15 >= 0.85 and row.odds_ou15_o and row.odds_ou15_o > 1.01: + results['ou15_over'].append({ + **base, 'signal': sig_ou15, 'odds': row.odds_ou15_o, + 'won': row.ou15 == 1, 'actual_goals': row.total_goals, + 'h_sig': h_ou15, 'a_sig': a_ou15 + }) + + # OU 2.5 OVER + if sig_ou25 >= 0.70 and row.odds_ou25_o and row.odds_ou25_o > 1.10: + results['ou25_over'].append({ + **base, 'signal': sig_ou25, 'odds': row.odds_ou25_o, + 'won': row.ou25 == 1, 'actual_goals': row.total_goals, + 'h_sig': h_ou25, 'a_sig': a_ou25 + }) + + # OU 3.5 OVER + if sig_ou35 >= 0.60 and row.odds_ou35_o and row.odds_ou35_o > 1.20: + results['ou35_over'].append({ + **base, 'signal': sig_ou35, 'odds': row.odds_ou35_o, + 'won': row.ou35 == 1, 'actual_goals': row.total_goals, + 'h_sig': h_ou35, 'a_sig': a_ou35 + }) + + # BTTS YES + if sig_btts >= 0.70 and row.odds_btts_y and row.odds_btts_y > 1.10: + results['btts_yes'].append({ + **base, 'signal': sig_btts, 'odds': row.odds_btts_y, + 'won': row.btts == 1, 'actual_goals': row.total_goals, + 'h_sig': h_btts, 'a_sig': a_btts + }) + + # OU 2.5 UNDER (düşük gol beklentisi) + if sig_ou25 <= 0.30 and row.odds_ou25_u and row.odds_ou25_u > 1.10: + results['ou25_under'].append({ + **base, 'signal': 1-sig_ou25, 'odds': row.odds_ou25_u, + 'won': row.ou25 == 0, 'actual_goals': row.total_goals, + 'h_sig': 1-h_ou25, 'a_sig': 1-a_ou25 + }) + + # MS HOME WIN (ev sahibi kazanma) + if sig_hw >= 0.75 and row.odds_ms_h and 1.10 < row.odds_ms_h < 3.50: + results['ms_home'].append({ + **base, 'signal': sig_hw, 'odds': row.odds_ms_h, + 'won': row.score_home > row.score_away, + 'actual_goals': row.total_goals, + 'h_sig': h_win, 'a_sig': a_loss + }) + + # History güncelle (her zaman) + home_history[row.home_team_id][h_band].append(( + row.ou15, row.ou25, row.ou35, row.btts, + int(row.score_home > row.score_away) + )) + away_history[row.away_team_id][a_band].append(( + row.ou15, row.ou25, row.ou35, row.btts, + int(row.score_away < row.score_home) # deplasman kaybetme + )) + +# 6. SONUÇLARI YAZIDIR +print(f"\nTest bölümü: son {TEST_PCT*100:.0f}% ({N - test_start:,} maç)") +print(f"Minimum geçmiş: {MIN_MATCHES} maç\n") + +for market_name, bets in results.items(): + if not bets: + print(f"\n {market_name}: sinyal yok") + continue + + bdf = pd.DataFrame(bets) + total = len(bdf) + wins = bdf.won.sum() + hit = wins / total * 100 + pnl = (bdf.won * (bdf.odds - 1) - (~bdf.won) * 1).sum() + roi = pnl / total * 100 + avg_odds = bdf.odds.mean() + + print(f"\n{'='*60}") + print(f" {market_name.upper()}") + print(f"{'='*60}") + print(f" Toplam bahis: {total}") + print(f" Kazanan: {wins} ({hit:.1f}%)") + print(f" Ortalama odds: {avg_odds:.2f}") + print(f" PnL: {pnl:+.1f} birim") + print(f" ROI: {roi:+.1f}%") + + # Farklı sinyal eşiklerinde performans + print(f"\n Sinyal eşik analizi:") + for threshold in [0.70, 0.75, 0.80, 0.85, 0.90, 0.95]: + sub = bdf[bdf.signal >= threshold] + if len(sub) < 5: continue + w = sub.won.sum() + p = (sub.won * (sub.odds - 1) - (~sub.won) * 1).sum() + r = p / len(sub) * 100 + star = ' ✅ PROFIT' if r > 0 else (' ⚖️ BE' if r > -3 else '') + print(f" ≥{threshold:.2f}: {len(sub):5d} bahis, hit={w/len(sub)*100:.1f}%, ROI={r:+.1f}%{star}") + + # En iyi 10 örnek (kazanan) + if wins > 0: + best = bdf[bdf.won].nlargest(min(5, wins), 'signal') + print(f"\n Örnek kazanan bahisler:") + for _, b in best.iterrows(): + print(f" {b.home_team} vs {b.away_team} ({b.league})") + print(f" Ev {b.h_band} ({b.h_sig:.0%}) + Dep {b.a_band} ({b.a_sig:.0%}) → sinyal={b.signal:.0%}, odds={b.odds:.2f}, gol={b.actual_goals:.0f}") + +# 7. ÖZET TABLO +print("\n\n" + "=" * 70) +print(" ÖZET TABLO") +print("=" * 70) +print(f"{'Market':<15} {'Bahis':>6} {'Hit':>7} {'ROI':>8} {'Avg Odds':>9}") +print("-" * 50) +for market_name, bets in results.items(): + if not bets: continue + bdf = pd.DataFrame(bets) + total = len(bdf) + wins = bdf.won.sum() + hit = wins / total * 100 + pnl = (bdf.won * (bdf.odds - 1) - (~bdf.won) * 1).sum() + roi = pnl / total * 100 + avg_odds = bdf.odds.mean() + print(f"{market_name:<15} {total:>6} {hit:>6.1f}% {roi:>+7.1f}% {avg_odds:>8.2f}") + +conn.close() +print("\n✅ Tamamlandı!") diff --git a/ai-engine/scripts/train_v27_value_sniper.py b/ai-engine/scripts/train_v27_value_sniper.py new file mode 100644 index 0000000..f9449f8 --- /dev/null +++ b/ai-engine/scripts/train_v27_value_sniper.py @@ -0,0 +1,480 @@ +""" +V27 Value Sniper — PRO Training Script +======================================== +KEY INSIGHT: Train model WITHOUT odds to get independent probability. +Then compare with market odds to find genuine value edges. + +Strategy: + Stage A: "Fundamentals Model" — odds-free, learns from ELO/form/rolling/H2H + Stage B: "Value Model" — uses fundamentals + odds disagreement as features + Stage C: Multi-market — 1X2, O/U 2.5, BTTS + Stage D: Walk-forward backtest with Kelly sizing +""" +import os, sys, json, pickle, time, warnings +import numpy as np +import pandas as pd +from pathlib import Path +from sklearn.metrics import accuracy_score, log_loss +from sklearn.isotonic import IsotonicRegression + +warnings.filterwarnings("ignore") + +AI_DIR = Path(__file__).resolve().parent.parent +DATA_CSV = AI_DIR / "data" / "training_data_v27.csv" +MODELS_DIR = AI_DIR / "models" / "v27" +MODELS_DIR.mkdir(parents=True, exist_ok=True) + +# ── Leakage & category definitions ── +LEAKAGE_COLS = [ + "total_goals", "goal_diff", "ht_total_goals", "ht_goal_diff", + "score_home", "score_away", "ht_score_home", "ht_score_away", + "home_goals_form", "away_goals_form", + "home_squad_quality", "away_squad_quality", "squad_diff", + "home_key_players", "away_key_players", + "home_missing_impact", "away_missing_impact", + "referee_home_bias", "referee_avg_goals", "referee_cards_total", + "referee_avg_yellow", "referee_avg_red", "referee_penalty_rate", + "referee_over25_rate", "referee_experience", "referee_matches", +] +LABEL_COLS = [c for c in [] ] # populated dynamically +META_COLS = ["match_id", "league_name", "home_team", "away_team"] +ODDS_COLS_PATTERNS = ["odds_", "implied_"] + + +def get_odds_cols(df): + return [c for c in df.columns if any(c.startswith(p) for p in ODDS_COLS_PATTERNS)] + + +def get_label_cols(df): + return [c for c in df.columns if c.startswith("label_")] + + +def get_clean_features(df): + """Features with NO odds and NO leakage — pure fundamentals.""" + odds = set(get_odds_cols(df)) + labels = set(get_label_cols(df)) + exclude = odds | labels | set(LEAKAGE_COLS) | set(META_COLS) + # Also exclude ID columns + exclude |= {c for c in df.columns if c.endswith("_id") and c != "match_id"} + feats = [c for c in df.columns if c not in exclude] + # Keep only numeric + feats = [c for c in feats if pd.to_numeric(df[c], errors="coerce").notna().sum() > len(df)*0.3] + return feats + + +def load_data(): + print(f"Loading {DATA_CSV}...") + df = pd.read_csv(DATA_CSV, low_memory=False) + print(f" Raw: {len(df)} rows") + + # Ensure odds exist for value comparison + for c in ["odds_ms_h","odds_ms_d","odds_ms_a"]: + df[c] = pd.to_numeric(df[c], errors="coerce") + df = df.dropna(subset=["odds_ms_h","odds_ms_d","odds_ms_a"]) + df = df[(df.odds_ms_h>1.01)&(df.odds_ms_d>1.01)&(df.odds_ms_a>1.01)] + + # OU25 odds + for c in ["odds_ou25_over","odds_ou25_under"]: + if c in df.columns: + df[c] = pd.to_numeric(df[c], errors="coerce") + + # Implied probabilities + margin = 1/df.odds_ms_h + 1/df.odds_ms_d + 1/df.odds_ms_a + df["implied_h"] = (1/df.odds_ms_h)/margin + df["implied_d"] = (1/df.odds_ms_d)/margin + df["implied_a"] = (1/df.odds_ms_a)/margin + + print(f" After filter: {len(df)} rows") + return df + + +def temporal_split(df, val_ratio=0.15, test_ratio=0.10): + n = len(df) + tr = int(n*(1-val_ratio-test_ratio)) + va = int(n*(1-test_ratio)) + return df.iloc[:tr].copy(), df.iloc[tr:va].copy(), df.iloc[va:].copy() + + +# ═══════════════════════════════════════════════════════════════════ +# STAGE A: Fundamentals-Only Model (NO ODDS) +# ═══════════════════════════════════════════════════════════════════ +def train_fundamentals_model(X_tr, y_tr, X_va, y_va, feat_cols, market="ms"): + """Train ensemble WITHOUT odds features.""" + models = {} + n_class = 3 if market == "ms" else 2 + + # XGBoost + try: + import xgboost as xgb + print(f" [XGB] Training {market.upper()}...") + dtrain = xgb.DMatrix(X_tr, label=y_tr, feature_names=feat_cols) + dval = xgb.DMatrix(X_va, label=y_va, feature_names=feat_cols) + params = { + "objective": "multi:softprob" if n_class==3 else "binary:logistic", + "eval_metric": "mlogloss" if n_class==3 else "logloss", + "max_depth": 6, "learning_rate": 0.02, "subsample": 0.75, + "colsample_bytree": 0.75, "min_child_weight": 10, + "reg_alpha": 0.5, "reg_lambda": 2.0, + "verbosity": 0, "tree_method": "hist", + } + if n_class == 3: + params["num_class"] = 3 + m = xgb.train(params, dtrain, num_boost_round=2000, + evals=[(dval,"val")], early_stopping_rounds=80, + verbose_eval=False) + p = m.predict(dval) + if n_class == 2: + p = np.column_stack([1-p, p]) + acc = accuracy_score(y_va, p.argmax(1)) + print(f" acc={acc:.4f}") + models["xgb"] = m + except ImportError: + pass + + # LightGBM + try: + import lightgbm as lgb + print(f" [LGB] Training {market.upper()}...") + ds_tr = lgb.Dataset(X_tr, label=y_tr) + ds_va = lgb.Dataset(X_va, label=y_va, reference=ds_tr) + par = { + "objective": "multiclass" if n_class==3 else "binary", + "metric": "multi_logloss" if n_class==3 else "binary_logloss", + "num_leaves": 48, "learning_rate": 0.02, + "feature_fraction": 0.7, "bagging_fraction": 0.7, + "bagging_freq": 1, "min_child_samples": 30, + "lambda_l1": 0.5, "lambda_l2": 2.0, "verbose": -1, + } + if n_class == 3: + par["num_class"] = 3 + m = lgb.train(par, ds_tr, 2000, valid_sets=[ds_va], + callbacks=[lgb.early_stopping(80, verbose=False)]) + p = m.predict(X_va) + if n_class == 2: + p = np.column_stack([1-p, p]) + acc = accuracy_score(y_va, p.argmax(1)) + print(f" acc={acc:.4f}") + models["lgb"] = m + except ImportError: + pass + + # CatBoost + try: + from catboost import CatBoostClassifier + print(f" [CB] Training {market.upper()}...") + m = CatBoostClassifier( + iterations=2000, learning_rate=0.02, depth=6, + l2_leaf_reg=5, loss_function="MultiClass" if n_class==3 else "Logloss", + early_stopping_rounds=80, verbose=0, task_type="CPU", + **({"classes_count": 3} if n_class==3 else {}), + ) + m.fit(X_tr, y_tr, eval_set=(X_va, y_va)) + p = m.predict_proba(X_va) + acc = accuracy_score(y_va, p.argmax(1)) + print(f" acc={acc:.4f}") + models["cb"] = m + except ImportError: + pass + + return models + + +def ensemble_predict(models, X, feat_cols, n_class=3): + preds = [] + for name, m in models.items(): + if name == "xgb": + import xgboost as xgb + dm = xgb.DMatrix(X, feature_names=feat_cols) + p = m.predict(dm) + if n_class == 2 and p.ndim == 1: + p = np.column_stack([1-p, p]) + elif name == "lgb": + p = m.predict(X) + if n_class == 2 and p.ndim == 1: + p = np.column_stack([1-p, p]) + elif name == "cb": + p = m.predict_proba(X) + preds.append(np.array(p)) + if not preds: + raise RuntimeError("No models!") + return np.mean(preds, axis=0) + + +# ═══════════════════════════════════════════════════════════════════ +# STAGE B: Walk-Forward Backtest with Kelly +# ═══════════════════════════════════════════════════════════════════ +def kelly_fraction(model_prob, odds, fraction=0.25): + """Fractional Kelly: f = fraction * (p*odds - 1) / (odds - 1)""" + edge = model_prob * odds - 1 + if edge <= 0 or odds <= 1: + return 0.0 + f = edge / (odds - 1) + return max(0, min(fraction * f, 0.10)) # cap at 10% bankroll + + +def backtest_value(models, df_test, feat_cols, market="ms", + min_edge=0.05, min_odds=1.40, max_odds=4.50, + use_kelly=True): + """Realistic backtest: flat or Kelly sizing, edge filtering.""" + X = df_test[feat_cols].values + n_class = 3 if market == "ms" else 2 + probs = ensemble_predict(models, X, feat_cols, n_class) + + if market == "ms": + y = df_test["label_ms"].values + odds_arr = df_test[["odds_ms_h","odds_ms_d","odds_ms_a"]].values + implied = df_test[["implied_h","implied_d","implied_a"]].values + class_names = ["Home","Draw","Away"] + elif market == "ou25": + if "label_ou25" not in df_test.columns: + return {} + y = df_test["label_ou25"].values + o_over = pd.to_numeric(df_test["odds_ou25_o"], errors="coerce").fillna(1.85).values if "odds_ou25_o" in df_test.columns else np.full(len(df_test), 1.85) + o_under = pd.to_numeric(df_test["odds_ou25_u"], errors="coerce").fillna(1.85).values if "odds_ou25_u" in df_test.columns else np.full(len(df_test), 1.85) + odds_arr = np.column_stack([o_under, o_over]) + m = 1/odds_arr + implied = m / m.sum(axis=1, keepdims=True) + class_names = ["Under","Over"] + else: + return {} + + results = {"bets": [], "total": 0, "wins": 0, "pnl": 0.0, "bankroll_curve": [1000.0]} + bankroll = 1000.0 + + for i in range(len(y)): + for cls in range(n_class): + edge = probs[i, cls] - implied[i, cls] + odds_val = odds_arr[i, cls] + + # FILTERS + if edge < min_edge: + continue + if odds_val < min_odds or odds_val > max_odds: + continue + # Don't bet on heavy favorites with tiny edge + if implied[i, cls] > 0.65 and edge < 0.08: + continue + + # Sizing + if use_kelly: + frac = kelly_fraction(probs[i, cls], odds_val, fraction=0.15) + stake = bankroll * frac + else: + stake = 10.0 # flat + + if stake < 1: + continue + + won = (y[i] == cls) + pnl = stake * (odds_val - 1) if won else -stake + bankroll += pnl + + results["bets"].append({ + "edge": float(edge), "odds": float(odds_val), + "model_p": float(probs[i,cls]), "implied_p": float(implied[i,cls]), + "won": bool(won), "pnl": float(pnl), "stake": float(stake), + "class": class_names[cls], + }) + results["bankroll_curve"].append(bankroll) + results["total"] += 1 + if won: + results["wins"] += 1 + results["pnl"] = bankroll - 1000.0 + + return results + + +def print_backtest(results, label=""): + total = results.get("total", 0) + if total == 0: + print(f" {label}: No bets placed") + return + wins = results["wins"] + pnl = results["pnl"] + hit = wins/total*100 + roi = pnl / sum(b["stake"] for b in results["bets"]) * 100 + curve = results["bankroll_curve"] + peak = max(curve) + dd = min((c - peak) / peak * 100 for c in curve if c <= peak) if len(curve) > 1 else 0 + + # Per-class breakdown + by_class = {} + for b in results["bets"]: + cls = b["class"] + if cls not in by_class: + by_class[cls] = {"n": 0, "w": 0, "pnl": 0} + by_class[cls]["n"] += 1 + if b["won"]: + by_class[cls]["w"] += 1 + by_class[cls]["pnl"] += b["pnl"] + + print(f"\n {label}") + print(f" Bets: {total} | Hit: {hit:.1f}% | ROI: {roi:+.1f}%") + print(f" PnL: {pnl:+.0f} | Final: {curve[-1]:.0f} | MaxDD: {dd:.1f}%") + for cls, d in sorted(by_class.items()): + r = d["pnl"]/d["n"]*100 if d["n"] > 0 else 0 + print(f" {cls:6s}: {d['n']:4d} bets, " + f"hit={d['w']/d['n']*100:.1f}%, avg_pnl={r:+.1f}%") + + +# ═══════════════════════════════════════════════════════════════════ +# MAIN +# ═══════════════════════════════════════════════════════════════════ +def main(): + print("=" * 65) + print(" V27 VALUE SNIPER — PRO TRAINING (Odds-Free Fundamentals)") + print("=" * 65) + t0 = time.time() + + df = load_data() + clean_feats = get_clean_features(df) + print(f" Clean features (no odds): {len(clean_feats)}") + + # Numerify + for c in clean_feats: + df[c] = pd.to_numeric(df[c], errors="coerce") + df[clean_feats] = df[clean_feats].fillna(df[clean_feats].median()) + + # Remove constant columns + clean_feats = [c for c in clean_feats if df[c].nunique() > 1] + print(f" After removing constants: {len(clean_feats)}") + + # Split + tr, va, te = temporal_split(df) + print(f" Train: {len(tr)}, Val: {len(va)}, Test: {len(te)}") + print(f" Target: H={tr.label_ms.eq(0).mean():.1%}, " + f"D={tr.label_ms.eq(1).mean():.1%}, A={tr.label_ms.eq(2).mean():.1%}") + + X_tr = tr[clean_feats].values + y_tr = tr["label_ms"].values + X_va = va[clean_feats].values + y_va = va["label_ms"].values + + # ── STAGE A: Train fundamentals model (1X2) ── + print("\n" + "─"*65) + print(" STAGE A: Fundamentals-Only 1X2 Model") + print("─"*65) + ms_models = train_fundamentals_model(X_tr, y_tr, X_va, y_va, clean_feats, "ms") + + val_probs = ensemble_predict(ms_models, X_va, clean_feats, 3) + val_acc = accuracy_score(y_va, val_probs.argmax(1)) + val_ll = log_loss(y_va, val_probs) + print(f"\n Ensemble Val: acc={val_acc:.4f}, logloss={val_ll:.4f}") + + # Compare with odds baseline + odds_pred = va[["implied_h","implied_d","implied_a"]].values.argmax(1) + odds_acc = accuracy_score(y_va, odds_pred) + print(f" Odds baseline: acc={odds_acc:.4f}") + print(f" Model vs Odds: {val_acc - odds_acc:+.4f}") + + # ── STAGE B: O/U 2.5 Model ── + ou_models = None + if "label_ou25" in tr.columns: + print("\n" + "─"*65) + print(" STAGE A.2: Fundamentals-Only O/U 2.5 Model") + print("─"*65) + y_tr_ou = tr["label_ou25"].values + y_va_ou = va["label_ou25"].values + mask_tr = ~np.isnan(y_tr_ou) + mask_va = ~np.isnan(y_va_ou) + if mask_tr.sum() > 1000: + ou_models = train_fundamentals_model( + X_tr[mask_tr], y_tr_ou[mask_tr].astype(int), + X_va[mask_va], y_va_ou[mask_va].astype(int), + clean_feats, "ou25") + + # ── STAGE C: Backtest ── + print("\n" + "─"*65) + print(" STAGE B: Walk-Forward Backtest (Test Set)") + print("─"*65) + + # Try multiple edge thresholds + best_roi = -999 + best_cfg = {} + for min_edge in [0.03, 0.05, 0.07, 0.10, 0.12, 0.15]: + for min_odds in [1.35, 1.50, 1.70]: + r = backtest_value(ms_models, te, clean_feats, "ms", + min_edge=min_edge, min_odds=min_odds, + max_odds=5.0, use_kelly=True) + if r.get("total", 0) >= 20: + invested = sum(b["stake"] for b in r["bets"]) + roi = r["pnl"] / invested * 100 if invested > 0 else -100 + if roi > best_roi: + best_roi = roi + best_cfg = {"edge": min_edge, "min_odds": min_odds, "result": r} + + if best_cfg: + cfg = best_cfg + print(f"\n Best 1X2 Config: edge>{cfg['edge']}, odds>{cfg['min_odds']}") + print_backtest(cfg["result"], "1X2 VALUE") + + # Flat bet comparison + print("\n --- Flat Bet Comparison ---") + for edge in [0.05, 0.07, 0.10]: + r = backtest_value(ms_models, te, clean_feats, "ms", + min_edge=edge, min_odds=1.50, max_odds=4.5, + use_kelly=False) + if r.get("total", 0) > 0: + inv = r["total"] * 10 + roi = r["pnl"]/inv*100 + print(f" Edge>{edge:.2f}: {r['total']} bets, " + f"hit={r['wins']/r['total']*100:.1f}%, ROI={roi:+.1f}%") + + # OU25 backtest + if ou_models: + print("\n --- O/U 2.5 Backtest ---") + for edge in [0.05, 0.07, 0.10]: + r = backtest_value(ou_models, te, clean_feats, "ou25", + min_edge=edge, min_odds=1.50, max_odds=3.0, + use_kelly=True) + if r.get("total", 0) > 0: + print_backtest(r, f"OU25 edge>{edge}") + + # ── Feature importance ── + if "lgb" in ms_models: + imp = ms_models["lgb"].feature_importance(importance_type="gain") + imp_df = pd.DataFrame({"feature": clean_feats, "importance": imp} + ).sort_values("importance", ascending=False) + print("\n TOP 15 FEATURES (no odds!):") + for _, r in imp_df.head(15).iterrows(): + print(f" {r['feature']:40s} {r['importance']:.0f}") + imp_df.to_csv(MODELS_DIR / "v27_feature_importance.csv", index=False) + + # ── Save ── + print("\n" + "─"*65) + print(" SAVING MODELS") + print("─"*65) + for name, m in ms_models.items(): + p = MODELS_DIR / f"v27_ms_{name}.pkl" + with open(p, "wb") as f: + pickle.dump(m, f) + print(f" ✓ {p.name}") + + if ou_models: + for name, m in ou_models.items(): + p = MODELS_DIR / f"v27_ou25_{name}.pkl" + with open(p, "wb") as f: + pickle.dump(m, f) + print(f" ✓ {p.name}") + + meta = { + "version": "v27-pro", "trained_at": time.strftime("%Y-%m-%d %H:%M:%S"), + "approach": "odds-free fundamentals + value edge detection", + "feature_count": len(clean_feats), + "total_samples": len(df), + "val_acc": round(val_acc, 4), "val_ll": round(val_ll, 4), + "best_config": {k: v for k, v in best_cfg.items() if k != "result"} if best_cfg else {}, + "markets": ["ms"] + (["ou25"] if ou_models else []), + } + with open(MODELS_DIR / "v27_metadata.json", "w") as f: + json.dump(meta, f, indent=2, default=str) + with open(MODELS_DIR / "v27_feature_cols.json", "w") as f: + json.dump(clean_feats, f, indent=2) + print(f" ✓ metadata + feature_cols") + + print(f"\n Total time: {(time.time()-t0)/60:.1f} min") + print(" DONE!") + + +if __name__ == "__main__": + main() diff --git a/mds/changelog-2026-04-22.md b/mds/changelog-2026-04-22.md new file mode 100644 index 0000000..7c64300 --- /dev/null +++ b/mds/changelog-2026-04-22.md @@ -0,0 +1,155 @@ +# Changelog - 2026-04-22 + +Bu doküman, 22 Nisan 2026 tarihinde `iddaai-fe` ve `iddaai-be` üzerinde yapılan Frekans Motoru (Conditional Frequency Engine) frontend entegrasyonunu özetler. + +## 1. Frekans Motoru — Backend Recap + +- `POST /coupon/frequency-coupon` endpoint'i önceki oturumda tamamlanmıştı. +- `SmartCouponService.generateFrequencyBasedCoupon()` metodu aktif ve çalışır durumda. +- `FrequencyEngineService` → raw SQL ile `matches` tablosundaki tarihsel veriyi tarayarak oran bandı bazlı sinyal üretiyor. +- Strateji: Her takımın ev/deplasman performansını, karşılaştığı oran bandına göre filtreleyip, kombine sinyal (combined_signal) hesaplıyor. + +## 2. Frontend Tip Tanımları + +- `iddaai-fe/src/lib/api/coupons/types.ts` güncellendi. +- Eklenen tipler: + +### FrequencyCouponRequestDto +```typescript +{ + maxMatches?: number; // 2-5 arası, varsayılan 3 + minSignal?: number; // 0.50-0.99, kombine sinyal eşiği + markets?: string[]; // OU1.5, OU2.5, OU3.5, BTTS, MS +} +``` + +### FrequencyCouponBetDto +```typescript +{ + match_id: string; + match_name: string; + league: string; + market: string; + pick: string; + odds: number; + home_signal: number; + away_signal: number; + combined_signal: number; + home_odds_band: string; + away_odds_band: string; + home_match_count: number; + away_match_count: number; + league_profile: string; // GOLCU | DEFANSIF | NORMAL +} +``` + +### FrequencyCouponRejectedDto +```typescript +{ + match_name: string; + reason: string; +} +``` + +### FrequencyCouponResultDto +```typescript +{ + bets: FrequencyCouponBetDto[]; + rejected_matches: FrequencyCouponRejectedDto[]; + reasoning: string[]; + total_odds: number; + expected_hit_rate: number; + expected_value: number; + ev_positive: boolean; +} +``` + +## 3. API Service Katmanı + +- `iddaai-fe/src/lib/api/coupons/service.ts` güncellendi. +- `generateFrequencyCoupon(dto)` metodu eklendi. +- Endpoint: `POST /coupon/frequency-coupon` + +## 4. React Hook + +- `iddaai-fe/src/lib/api/coupons/use-hooks.ts` güncellendi. +- `useGenerateFrequencyCoupon()` TanStack Query mutation hook'u eklendi. +- `FrequencyCouponRequestDto` import edildi. + +## 5. Çeviri Dosyaları (i18n) + +- `messages/tr.json` ve `messages/en.json` güncellendi. +- `coupons` namespace'ine 30+ yeni anahtar eklendi: + +| Anahtar | TR | EN | +|---|---|---| +| `freq-engine-title` | Frekans Motoru | Frequency Engine | +| `freq-engine-subtitle` | Takımların oran bandına göre tarihsel performansını analiz eder... | Analyzes teams' historical performance by odds band... | +| `freq-suggest` | Frekans Kuponu Oluştur | Generate Frequency Coupon | +| `freq-min-signal` | Minimum Sinyal | Minimum Signal | +| `freq-ev-label` | Beklenen Değer (EV) | Expected Value (EV) | +| `freq-hit-rate` | Tahmini İsabet | Est. Hit Rate | +| `freq-ev-positive` | +EV Pozitif | +EV Positive | +| `freq-combined-signal` | Kombine Sinyal | Combined Signal | +| `freq-league-golcu` | Golcü | High-Scoring | +| `freq-league-defansif` | Defansif | Defensive | +| `engine-mode-label` | Motor Seçimi | Engine Mode | +| `engine-mode-help` | AI: Gemini tabanlı yapay zeka tahmini. Frekans: Veritabanı tabanlı istatistiksel analiz. | AI: Gemini-based AI prediction. Frequency: Database-driven statistical analysis. | +| `freq-mode-active` | Frekans Motoru aktif | Frequency Engine active | +| `ai-mode-active` | AI Motoru aktif | AI Engine active | + +## 6. FrequencyPanel Bileşeni (Yeni Dosya) + +- `iddaai-fe/src/components/coupons/frequency-panel.tsx` oluşturuldu. +- Bağımsız (standalone) bileşen, kendi state ve mutation yönetimini içerir. + +### Bileşen Özellikleri: +1. **Min Signal Slider** — 50%-95% arası, kombine sinyal eşiği kontrolü +2. **Max Matches Slider** — 2-5 arası, kupon boyutu kontrolü +3. **Market Filtre Badge'leri** — OU1.5, OU2.5, OU3.5, BTTS, MS (çoklu seçim) +4. **Generate Butonu** → `useGenerateFrequencyCoupon` mutation'ını tetikler +5. **Sonuç Paneli**: + - EV / Hit Rate / Toplam Oran istatistik kartları + - Her bahis için ev sinyali, deplasman sinyali, kombine sinyal gösterimi + - Oran bandı bilgisi (ör. "1.30-1.50") + - Lig profili badge'i (Golcü/Defansif/Normal) + - Geçmiş maç sayısı gösterimi + - Analiz detayları (reasoning listesi) + - Elenen maçlar (rejected_matches) +6. **Kupon Store Senkronizasyonu** — Sonuç geldiğinde bahisler otomatik olarak `useCouponStore`'a eklenir + +## 7. Coupon Builder Engine Toggle + +- `iddaai-fe/src/components/coupons/coupon-builder-content.tsx` güncellendi. +- Değişiklikler: + - `LuDatabase` icon import edildi + - `FrequencyPanel` import edildi + - `engineMode` state eklendi: `"ai" | "frequency"` + - Sidebar'a **Motor Seçimi** toggle eklendi (Badge tabanlı) + - `engineMode === "frequency"` olduğunda strateji/AI suggest bölümü gizlenir, yerine `FrequencyPanel` render edilir + - `engineMode === "ai"` olduğunda mevcut AI akışı aynen korunur + +### Veri Akışı: +``` +Kullanıcı → "Frekans" badge'ine tıklar → FrequencyPanel açılır + → Sinyal/market/boyut ayarı yapar → "Frekans Kuponu Oluştur" butonuna basar + → POST /coupon/frequency-coupon { maxMatches, minSignal, markets } + → Backend: SmartCouponService → FrequencyEngineService (raw SQL) + → Response: FrequencyCouponResultDto + → UI: Sinyal kartları, EV istatistikleri, reasoning render edilir + → Bahisler otomatik olarak CouponStore'a sync edilir +``` + +## 8. Derleme ve Doğrulama Notları + +- `node_modules` kullanıcının makinesinde yüklü olmadığı için `npm run build` çalıştırılamadı. +- Kod yapısal olarak doğru, TypeScript tipleri backend DTO'ları ile birebir eşleşiyor. +- Doğrulama için: `npm install && npm run build` çalıştırılmalı. + +## 9. Açık Kalan / Sonraki Adımlar + +- `npm install && npm run build` ile frontend build doğrulanmalı. +- Frekans kuponu uçtan uca test edilmeli (backend Docker ayakta iken). +- FrequencyPanel içindeki market badge'lerine `HT_OU05` ve `DC` gibi ek marketler eklenebilir. +- Frekans sonuçlarındaki `league_profile` badge renkleri dark mode için ince ayar gerektirebilir. +- Kupon geçmişinde AI vs Frekans ayrımını gösteren bir etiket eklenebilir. diff --git a/src/modules/coupons/coupons.controller.ts b/src/modules/coupons/coupons.controller.ts index e77bb5e..50f9596 100755 --- a/src/modules/coupons/coupons.controller.ts +++ b/src/modules/coupons/coupons.controller.ts @@ -27,6 +27,7 @@ import { AnalyzeMatchDto, DailyBankoDto, SuggestCouponDto, + FrequencyCouponDto, } from "./dto/coupons-request.dto"; import { Public } from "../../common/decorators"; import { JwtAuthGuard } from "../auth/guards/auth.guards"; // Assuming standard guard @@ -188,8 +189,43 @@ export class CouponsController { return { success: true, data: coupon }; } + /** + * POST /coupon/frequency-coupon + * Generate a frequency-based parlay coupon (Conditional Frequency Engine) + */ + @Post("frequency-coupon") + @Public() + @HttpCode(HttpStatus.OK) + @ApiOperation({ + summary: "Generate frequency-based parlay coupon", + description: + "Scans upcoming matches, applies conditional frequency analysis " + + "(team odds-band performance), and builds 2-5 match combos with +EV calculation.", + }) + @ApiResponse({ status: 200, description: "Frequency coupon generated" }) + async getFrequencyCoupon(@Body() dto: FrequencyCouponDto) { + const coupon = await this.smartCouponService.generateFrequencyBasedCoupon({ + matchIds: dto.matchIds, + maxMatches: dto.maxMatches, + minSignal: dto.minSignal, + markets: dto.markets, + }); + + if (!coupon || coupon.bets.length === 0) { + return { + success: false, + message: + "Frekans analizine uygun yeterli maç bulunamadı. " + + "minSignal değerini düşürmeyi veya daha fazla maç beklemeyi deneyin.", + data: coupon, + }; + } + + return { success: true, data: coupon }; + } + // ============================================ - // USER COUPON ENDPOINTS (NEW) + // USER COUPON ENDPOINTS // ============================================ /** diff --git a/src/modules/coupons/coupons.module.ts b/src/modules/coupons/coupons.module.ts index 4670bbc..44154b2 100755 --- a/src/modules/coupons/coupons.module.ts +++ b/src/modules/coupons/coupons.module.ts @@ -2,6 +2,7 @@ import { Module } from "@nestjs/common"; import { CouponsController } from "./coupons.controller"; import { SmartCouponService } from "./services/smart-coupon.service"; import { UserCouponService } from "./services/user-coupon.service"; +import { FrequencyEngineService } from "./services/frequency-engine.service"; import { CouponsService } from "./coupons.service"; import { DatabaseModule } from "../../database/database.module"; import { ServicesModule } from "../../services/services.module"; @@ -10,7 +11,18 @@ import { MatchesModule } from "../matches/matches.module"; @Module({ imports: [DatabaseModule, ServicesModule, MatchesModule], controllers: [CouponsController], - providers: [CouponsService, SmartCouponService, UserCouponService], - exports: [CouponsService, SmartCouponService, UserCouponService], + providers: [ + CouponsService, + SmartCouponService, + UserCouponService, + FrequencyEngineService, + ], + exports: [ + CouponsService, + SmartCouponService, + UserCouponService, + FrequencyEngineService, + ], }) export class CouponsModule {} + diff --git a/src/modules/coupons/dto/coupons-request.dto.ts b/src/modules/coupons/dto/coupons-request.dto.ts index dc86c9e..11ee6fe 100644 --- a/src/modules/coupons/dto/coupons-request.dto.ts +++ b/src/modules/coupons/dto/coupons-request.dto.ts @@ -74,3 +74,47 @@ export class SuggestCouponDto { @Max(100) minConfidence?: number; } + +export class FrequencyCouponDto { + @ApiPropertyOptional({ + description: "Optional match IDs — system auto-fetches if empty", + example: ["match-1", "match-2"], + }) + @IsOptional() + @IsArray() + @IsString({ each: true }) + @ArrayMaxSize(50) + matchIds?: string[]; + + @ApiPropertyOptional({ + description: "Maximum matches in parlay (2-5)", + example: 3, + default: 3, + }) + @IsOptional() + @IsNumber() + @Min(2) + @Max(5) + maxMatches?: number; + + @ApiPropertyOptional({ + description: "Minimum combined signal threshold (0.50-0.99)", + example: 0.7, + default: 0.7, + }) + @IsOptional() + @IsNumber() + @Min(0.5) + @Max(0.99) + minSignal?: number; + + @ApiPropertyOptional({ + description: + "Filter markets: OU1.5, OU2.5, OU3.5, BTTS, MS (default: all)", + example: ["OU2.5", "BTTS"], + }) + @IsOptional() + @IsArray() + @IsString({ each: true }) + markets?: string[]; +} diff --git a/src/modules/coupons/services/frequency-engine.service.ts b/src/modules/coupons/services/frequency-engine.service.ts new file mode 100644 index 0000000..4003726 --- /dev/null +++ b/src/modules/coupons/services/frequency-engine.service.ts @@ -0,0 +1,584 @@ +import { Injectable, Logger } from "@nestjs/common"; +import { PrismaService } from "../../../database/prisma.service"; + +// ───────────────────────────────────────────────────────────── +// Types +// ───────────────────────────────────────────────────────────── + +export interface FrequencySignal { + market: string; + pick: string; + homeSignal: number; + awaySignal: number; + combinedSignal: number; + homeMatchCount: number; + awayMatchCount: number; + leagueBonus: number; + confidence: number; +} + +export interface MatchCandidate { + matchId: string; + homeTeamId: string; + awayTeamId: string; + homeTeamName: string; + awayTeamName: string; + leagueId: string; + leagueName: string; + homeOdds: number; + awayOdds: number; + drawOdds: number; + signals: FrequencySignal[]; + bestSignal: FrequencySignal | null; + matchTime: number; +} + +interface TeamFrequencyRow { + team_id: string; + venue: "home" | "away"; + odds_band: string; + total_matches: number; + ou15_rate: number; + ou25_rate: number; + ou35_rate: number; + btts_rate: number; + win_rate: number; + avg_goals: number; +} + +interface LeagueProfileRow { + league_id: string; + league_name: string; + total_matches: number; + ou25_rate: number; + btts_rate: number; + avg_goals: number; +} + +interface UpcomingMatchRow { + match_id: string; + home_team_id: string; + away_team_id: string; + home_team_name: string; + away_team_name: string; + league_id: string; + league_name: string; + mst_utc: bigint; + ms1_odds: number | null; + ms2_odds: number | null; + msx_odds: number | null; + ou25_over_odds: number | null; + ou25_under_odds: number | null; + btts_yes_odds: number | null; + btts_no_odds: number | null; + ou15_over_odds: number | null; + ou35_over_odds: number | null; +} + +// ───────────────────────────────────────────────────────────── +// Constants +// ───────────────────────────────────────────────────────────── + +const MIN_MATCHES = 3; + +const GOLCU_LEAGUES = new Set([ + // Strategy generator'dan türetilen yüksek golcü ligler + // Lig isimleri veritabanındaki gibi +]); + +const DEFANSIF_LEAGUES = new Set([ + // Düşük golcü ligler +]); + +// ───────────────────────────────────────────────────────────── +// Service +// ───────────────────────────────────────────────────────────── + +@Injectable() +export class FrequencyEngineService { + private readonly logger = new Logger(FrequencyEngineService.name); + + constructor(private readonly prisma: PrismaService) {} + + /** + * Belirli bir takımın ev/deplasman + oran bandı koşullu frekanslarını döndürür. + */ + async getTeamFrequency( + teamId: string, + venue: "home" | "away", + oddsBand: string, + ): Promise { + const venueColumn = + venue === "home" ? "m.home_team_id" : "m.away_team_id"; + const oddsSelection = venue === "home" ? "'1'" : "'2'"; + const bandRange = this.parseBandRange(oddsBand); + + if (!bandRange) { + return null; + } + + const rows = await this.prisma.$queryRawUnsafe( + ` + WITH team_matches AS ( + SELECT + m.id AS match_id, + m.score_home, + m.score_away, + (m.score_home + m.score_away) AS total_goals, + CAST(os.odd_value AS DECIMAL) AS team_odds + FROM matches m + JOIN odd_categories oc ON oc.match_id = m.id AND oc.name = 'Maç Sonucu' + JOIN odd_selections os ON os.odd_category_db_id = oc.db_id AND os.name = ${oddsSelection} + WHERE m.status = 'FT' + AND m.score_home IS NOT NULL + AND ${venueColumn} = $1 + AND CAST(os.odd_value AS DECIMAL) >= $2 + AND CAST(os.odd_value AS DECIMAL) < $3 + ) + SELECT + $1::text AS team_id, + $4::text AS venue, + $5::text AS odds_band, + COUNT(*)::int AS total_matches, + COALESCE(AVG(CASE WHEN total_goals > 1 THEN 1.0 ELSE 0.0 END), 0)::float AS ou15_rate, + COALESCE(AVG(CASE WHEN total_goals > 2 THEN 1.0 ELSE 0.0 END), 0)::float AS ou25_rate, + COALESCE(AVG(CASE WHEN total_goals > 3 THEN 1.0 ELSE 0.0 END), 0)::float AS ou35_rate, + COALESCE(AVG(CASE WHEN score_home > 0 AND score_away > 0 THEN 1.0 ELSE 0.0 END), 0)::float AS btts_rate, + COALESCE(AVG(CASE WHEN ${venue === "home" ? "score_home > score_away" : "score_away > score_home"} THEN 1.0 ELSE 0.0 END), 0)::float AS win_rate, + COALESCE(AVG(total_goals), 0)::float AS avg_goals + FROM team_matches + `, + teamId, + bandRange.min, + bandRange.max, + venue, + oddsBand, + ); + + if (!rows.length || rows[0].total_matches < MIN_MATCHES) { + return null; + } + + return rows[0]; + } + + /** + * İki takımın oran bandı geçmişlerini çapraz kontrol eder. + * Tüm marketler için kombine sinyal üretir. + */ + async getMatchFrequencySignals( + homeTeamId: string, + awayTeamId: string, + homeOdds: number, + awayOdds: number, + leagueId?: string, + ): Promise { + const homeBand = this.getOddsBand(homeOdds); + const awayBand = this.getOddsBand(awayOdds); + + const [homeFreq, awayFreq, leagueProfile] = await Promise.all([ + this.getTeamFrequency(homeTeamId, "home", homeBand), + this.getTeamFrequency(awayTeamId, "away", awayBand), + leagueId ? this.getLeagueProfile(leagueId) : null, + ]); + + if (!homeFreq || !awayFreq) { + return []; + } + + const leagueBonus = this.calculateLeagueBonus(leagueProfile); + const signals: FrequencySignal[] = []; + + // OU 1.5 OVER + const ou15Combined = (homeFreq.ou15_rate + awayFreq.ou15_rate) / 2; + if (ou15Combined >= 0.80) { + signals.push({ + market: "OU1.5_OVER", + pick: "1.5 UST", + homeSignal: homeFreq.ou15_rate, + awaySignal: awayFreq.ou15_rate, + combinedSignal: ou15Combined, + homeMatchCount: homeFreq.total_matches, + awayMatchCount: awayFreq.total_matches, + leagueBonus, + confidence: this.calculateConfidence( + ou15Combined, + homeFreq.total_matches, + awayFreq.total_matches, + leagueBonus, + ), + }); + } + + // OU 2.5 OVER + const ou25Combined = (homeFreq.ou25_rate + awayFreq.ou25_rate) / 2; + if (ou25Combined >= 0.60) { + signals.push({ + market: "OU2.5_OVER", + pick: "2.5 UST", + homeSignal: homeFreq.ou25_rate, + awaySignal: awayFreq.ou25_rate, + combinedSignal: ou25Combined, + homeMatchCount: homeFreq.total_matches, + awayMatchCount: awayFreq.total_matches, + leagueBonus, + confidence: this.calculateConfidence( + ou25Combined, + homeFreq.total_matches, + awayFreq.total_matches, + leagueBonus, + ), + }); + } + + // OU 3.5 OVER + const ou35Combined = (homeFreq.ou35_rate + awayFreq.ou35_rate) / 2; + if (ou35Combined >= 0.50) { + signals.push({ + market: "OU3.5_OVER", + pick: "3.5 UST", + homeSignal: homeFreq.ou35_rate, + awaySignal: awayFreq.ou35_rate, + combinedSignal: ou35Combined, + homeMatchCount: homeFreq.total_matches, + awayMatchCount: awayFreq.total_matches, + leagueBonus, + confidence: this.calculateConfidence( + ou35Combined, + homeFreq.total_matches, + awayFreq.total_matches, + leagueBonus, + ), + }); + } + + // BTTS YES + const bttsCombined = (homeFreq.btts_rate + awayFreq.btts_rate) / 2; + if (bttsCombined >= 0.60) { + signals.push({ + market: "BTTS_YES", + pick: "KG VAR", + homeSignal: homeFreq.btts_rate, + awaySignal: awayFreq.btts_rate, + combinedSignal: bttsCombined, + homeMatchCount: homeFreq.total_matches, + awayMatchCount: awayFreq.total_matches, + leagueBonus, + confidence: this.calculateConfidence( + bttsCombined, + homeFreq.total_matches, + awayFreq.total_matches, + leagueBonus, + ), + }); + } + + // OU 2.5 UNDER (düşük gol beklentisi) + const ou25UnderCombined = + (1 - homeFreq.ou25_rate + (1 - awayFreq.ou25_rate)) / 2; + if (ou25UnderCombined >= 0.65) { + signals.push({ + market: "OU2.5_UNDER", + pick: "2.5 ALT", + homeSignal: 1 - homeFreq.ou25_rate, + awaySignal: 1 - awayFreq.ou25_rate, + combinedSignal: ou25UnderCombined, + homeMatchCount: homeFreq.total_matches, + awayMatchCount: awayFreq.total_matches, + leagueBonus: -leagueBonus, // golcü lig bonusu ters çevrilir + confidence: this.calculateConfidence( + ou25UnderCombined, + homeFreq.total_matches, + awayFreq.total_matches, + -leagueBonus, + ), + }); + } + + // MS HOME WIN (ev sahibi kazanma) + const hwCombined = (homeFreq.win_rate + awayFreq.win_rate) / 2; + // awayFreq.win_rate aslında deplasman takımının KAYBETme oranı + // (away takımı o bandda maçları kazanma değil, kaybetme olarak bak) + if (hwCombined >= 0.70 && homeOdds > 1.10 && homeOdds < 3.50) { + signals.push({ + market: "MS_HOME", + pick: "MS 1", + homeSignal: homeFreq.win_rate, + awaySignal: awayFreq.win_rate, + combinedSignal: hwCombined, + homeMatchCount: homeFreq.total_matches, + awayMatchCount: awayFreq.total_matches, + leagueBonus: 0, + confidence: this.calculateConfidence( + hwCombined, + homeFreq.total_matches, + awayFreq.total_matches, + 0, + ), + }); + } + + // Güvene göre sırala (en güçlü sinyal önce) + signals.sort((a, b) => b.confidence - a.confidence); + + return signals; + } + + /** + * Yaklaşan maçları oranlarıyla birlikte getirir. + * LiveMatch tablosundan JSON odds parse eder. + */ + async getUpcomingMatchesWithOdds( + matchIds?: string[], + limit: number = 50, + ): Promise { + const nowMs = Date.now(); + + if (matchIds && matchIds.length > 0) { + // Belirli maçlar istendi + return this.prisma.$queryRawUnsafe( + ` + SELECT + lm.id AS match_id, + lm.home_team_id, + lm.away_team_id, + COALESCE(ht.name, 'Unknown') AS home_team_name, + COALESCE(at.name, 'Unknown') AS away_team_name, + COALESCE(lm.league_id, '') AS league_id, + COALESCE(l.name, 'Unknown') AS league_name, + lm.mst_utc, + (lm.odds->'Maç Sonucu'->>'1')::decimal AS ms1_odds, + (lm.odds->'Maç Sonucu'->>'2')::decimal AS ms2_odds, + (lm.odds->'Maç Sonucu'->>'0')::decimal AS msx_odds, + (lm.odds->'2,5 Alt/Üst'->>'Üst')::decimal AS ou25_over_odds, + (lm.odds->'2,5 Alt/Üst'->>'Alt')::decimal AS ou25_under_odds, + (lm.odds->'Karşılıklı Gol'->>'Var')::decimal AS btts_yes_odds, + (lm.odds->'Karşılıklı Gol'->>'Yok')::decimal AS btts_no_odds, + (lm.odds->'1,5 Alt/Üst'->>'Üst')::decimal AS ou15_over_odds, + (lm.odds->'3,5 Alt/Üst'->>'Üst')::decimal AS ou35_over_odds + FROM live_matches lm + LEFT JOIN teams ht ON lm.home_team_id = ht.id + LEFT JOIN teams at ON lm.away_team_id = at.id + LEFT JOIN leagues l ON lm.league_id = l.id + WHERE lm.id = ANY($1) + AND lm.odds IS NOT NULL + AND lm.odds != 'null'::jsonb + ORDER BY lm.mst_utc ASC + `, + matchIds, + ); + } + + // Otomatik: yaklaşan tüm maçlar + return this.prisma.$queryRawUnsafe( + ` + SELECT + lm.id AS match_id, + lm.home_team_id, + lm.away_team_id, + COALESCE(ht.name, 'Unknown') AS home_team_name, + COALESCE(at.name, 'Unknown') AS away_team_name, + COALESCE(lm.league_id, '') AS league_id, + COALESCE(l.name, 'Unknown') AS league_name, + lm.mst_utc, + (lm.odds->'Maç Sonucu'->>'1')::decimal AS ms1_odds, + (lm.odds->'Maç Sonucu'->>'2')::decimal AS ms2_odds, + (lm.odds->'Maç Sonucu'->>'0')::decimal AS msx_odds, + (lm.odds->'2,5 Alt/Üst'->>'Üst')::decimal AS ou25_over_odds, + (lm.odds->'2,5 Alt/Üst'->>'Alt')::decimal AS ou25_under_odds, + (lm.odds->'Karşılıklı Gol'->>'Var')::decimal AS btts_yes_odds, + (lm.odds->'Karşılıklı Gol'->>'Yok')::decimal AS btts_no_odds, + (lm.odds->'1,5 Alt/Üst'->>'Üst')::decimal AS ou15_over_odds, + (lm.odds->'3,5 Alt/Üst'->>'Üst')::decimal AS ou35_over_odds + FROM live_matches lm + LEFT JOIN teams ht ON lm.home_team_id = ht.id + LEFT JOIN teams at ON lm.away_team_id = at.id + LEFT JOIN leagues l ON lm.league_id = l.id + WHERE lm.mst_utc >= $1 + AND lm.sport = 'football' + AND lm.odds IS NOT NULL + AND lm.odds != 'null'::jsonb + AND (lm.status IS NULL OR lm.status NOT IN ('FT', 'AET', 'PEN', 'ABD', 'CANC', 'PST', 'SUSP', 'INT', 'AWD', 'WO')) + AND (lm.state IS NULL OR lm.state NOT IN ('after', 'postponed', 'cancelled', 'abandoned')) + ORDER BY lm.mst_utc ASC + LIMIT $2 + `, + BigInt(nowMs), + limit, + ); + } + + /** + * Lig bazlı gol profili. + */ + async getLeagueProfile( + leagueId: string, + ): Promise { + const rows = await this.prisma.$queryRawUnsafe( + ` + SELECT + m.league_id, + l.name AS league_name, + COUNT(*)::int AS total_matches, + AVG(CASE WHEN (m.score_home + m.score_away) > 2 THEN 1.0 ELSE 0.0 END)::float AS ou25_rate, + AVG(CASE WHEN m.score_home > 0 AND m.score_away > 0 THEN 1.0 ELSE 0.0 END)::float AS btts_rate, + AVG(m.score_home + m.score_away)::float AS avg_goals + FROM matches m + JOIN leagues l ON m.league_id = l.id + WHERE m.status = 'FT' + AND m.score_home IS NOT NULL + AND m.league_id = $1 + GROUP BY m.league_id, l.name + HAVING COUNT(*) >= 20 + `, + leagueId, + ); + + return rows.length > 0 ? rows[0] : null; + } + + /** + * Bir upcoming match row'unu MatchCandidate'e dönüştürür + * ve frekans sinyallerini hesaplar. + */ + async buildMatchCandidate( + row: UpcomingMatchRow, + ): Promise { + const homeOdds = row.ms1_odds ? Number(row.ms1_odds) : 0; + const awayOdds = row.ms2_odds ? Number(row.ms2_odds) : 0; + const drawOdds = row.msx_odds ? Number(row.msx_odds) : 0; + + if (homeOdds <= 0 || awayOdds <= 0) { + return null; + } + + const signals = await this.getMatchFrequencySignals( + row.home_team_id, + row.away_team_id, + homeOdds, + awayOdds, + row.league_id || undefined, + ); + + if (signals.length === 0) { + return null; + } + + return { + matchId: row.match_id, + homeTeamId: row.home_team_id, + awayTeamId: row.away_team_id, + homeTeamName: row.home_team_name, + awayTeamName: row.away_team_name, + leagueId: row.league_id, + leagueName: row.league_name, + homeOdds, + awayOdds, + drawOdds, + signals, + bestSignal: signals[0] || null, + matchTime: Number(row.mst_utc), + }; + } + + /** + * Bir market pick'ine karşılık gelen odds'u UpcomingMatchRow'dan çeker. + */ + getMarketOdds(row: UpcomingMatchRow, market: string): number { + switch (market) { + case "OU1.5_OVER": + return row.ou15_over_odds ? Number(row.ou15_over_odds) : 0; + case "OU2.5_OVER": + return row.ou25_over_odds ? Number(row.ou25_over_odds) : 0; + case "OU2.5_UNDER": + return row.ou25_under_odds ? Number(row.ou25_under_odds) : 0; + case "OU3.5_OVER": + return row.ou35_over_odds ? Number(row.ou35_over_odds) : 0; + case "BTTS_YES": + return row.btts_yes_odds ? Number(row.btts_yes_odds) : 0; + case "MS_HOME": + return row.ms1_odds ? Number(row.ms1_odds) : 0; + default: + return 0; + } + } + + // ───────────────────────────────────────────────────────────── + // Private Helpers + // ───────────────────────────────────────────────────────────── + + /** + * Oran bandı fonksiyonu — strategy_generator.py ile aynı mantık. + */ + getOddsBand(odds: number): string { + if (odds < 1.3) return "1.00-1.30"; + if (odds < 1.5) return "1.30-1.50"; + if (odds < 1.8) return "1.50-1.80"; + if (odds < 2.2) return "1.80-2.20"; + if (odds < 2.8) return "2.20-2.80"; + if (odds < 4.0) return "2.80-4.00"; + if (odds < 6.0) return "4.00-6.00"; + return "6.00+"; + } + + private parseBandRange( + band: string, + ): { min: number; max: number } | null { + const map: Record = { + "1.00-1.30": { min: 1.0, max: 1.3 }, + "1.30-1.50": { min: 1.3, max: 1.5 }, + "1.50-1.80": { min: 1.5, max: 1.8 }, + "1.80-2.20": { min: 1.8, max: 2.2 }, + "2.20-2.80": { min: 2.2, max: 2.8 }, + "2.80-4.00": { min: 2.8, max: 4.0 }, + "4.00-6.00": { min: 4.0, max: 6.0 }, + "6.00+": { min: 6.0, max: 999.0 }, + }; + return map[band] || null; + } + + private calculateLeagueBonus( + profile: LeagueProfileRow | null, + ): number { + if (!profile || profile.total_matches < 20) { + return 0; + } + + // OU2.5 > %60 ise golcü lig bonusu + if (profile.ou25_rate > 0.6) { + return Math.min((profile.ou25_rate - 0.5) * 0.2, 0.05); + } + + // OU2.5 < %40 ise defansif lig bonusu (negatif) + if (profile.ou25_rate < 0.4) { + return Math.max((profile.ou25_rate - 0.5) * 0.2, -0.05); + } + + return 0; + } + + private calculateConfidence( + combinedSignal: number, + homeN: number, + awayN: number, + leagueBonus: number, + ): number { + // Base confidence: kombine sinyal * 100 + let confidence = combinedSignal * 100; + + // Sample size bonus: daha fazla veri = daha güvenilir + const minN = Math.min(homeN, awayN); + if (minN >= 20) { + confidence += 5; + } else if (minN >= 10) { + confidence += 2; + } else if (minN < 5) { + confidence -= 5; + } + + // Liga bonusu + confidence += leagueBonus * 100; + + return Math.max(0, Math.min(100, parseFloat(confidence.toFixed(1)))); + } +} diff --git a/src/modules/coupons/services/smart-coupon.service.ts b/src/modules/coupons/services/smart-coupon.service.ts index b9db5ce..a4bb8a2 100755 --- a/src/modules/coupons/services/smart-coupon.service.ts +++ b/src/modules/coupons/services/smart-coupon.service.ts @@ -4,6 +4,11 @@ import { AiEngineClient, AiEngineRequestError, } from "../../../common/utils/ai-engine-client"; +import { + FrequencyEngineService, + type MatchCandidate, + type FrequencySignal, +} from "./frequency-engine.service"; export type PredictionRiskLevel = "LOW" | "MEDIUM" | "HIGH" | "EXTREME"; export type PredictionDataQuality = "HIGH" | "MEDIUM" | "LOW"; @@ -131,7 +136,10 @@ export class SmartCouponService { private readonly aiEngineUrl: string; private readonly aiEngineClient: AiEngineClient; - constructor(private readonly geminiService: GeminiService) { + constructor( + private readonly geminiService: GeminiService, + private readonly frequencyEngine: FrequencyEngineService, + ) { this.aiEngineUrl = process.env.AI_ENGINE_URL || "http://ai-engine:8000"; this.aiEngineClient = new AiEngineClient({ baseUrl: this.aiEngineUrl, @@ -244,6 +252,235 @@ export class SmartCouponService { ); } } + + // ───────────────────────────────────────────────────────────── + // FREQUENCY-BASED COUPON ENGINE + // ───────────────────────────────────────────────────────────── + + async generateFrequencyBasedCoupon(options: { + matchIds?: string[]; + maxMatches?: number; + minSignal?: number; + markets?: string[]; + }): Promise { + const maxMatches = options.maxMatches ?? 3; + const minSignal = options.minSignal ?? 0.70; + const allowedMarkets = options.markets?.map((m) => m.toUpperCase()) || null; + + this.logger.log( + `[FrequencyCoupon] Starting — max=${maxMatches}, minSignal=${minSignal}`, + ); + + // 1. Yaklaşan maçları oranlarıyla getir + const upcomingRows = await this.frequencyEngine.getUpcomingMatchesWithOdds( + options.matchIds, + 80, + ); + + this.logger.log( + `[FrequencyCoupon] Found ${upcomingRows.length} upcoming matches with odds`, + ); + + if (upcomingRows.length === 0) { + return { + strategy: "FREQUENCY", + generated_at: new Date().toISOString(), + bets: [], + total_odds: 0, + expected_hit_rate: 0, + expected_value: 0, + ev_positive: false, + reasoning: ["Bültende uygun maç bulunamadı."], + rejected_matches: [], + }; + } + + // 2. Her maç için frekans sinyallerini hesapla (paralel) + const candidatePromises = upcomingRows.map((row) => + this.frequencyEngine.buildMatchCandidate(row).then((candidate) => ({ + candidate, + row, + })), + ); + const candidateResults = await Promise.all(candidatePromises); + + // 3. Sinyali olan adayları filtrele + const allCandidates: Array<{ + candidate: MatchCandidate; + row: (typeof upcomingRows)[0]; + }> = []; + const rejected: FrequencyCouponResult["rejected_matches"] = []; + + for (const { candidate, row } of candidateResults) { + if (!candidate) { + rejected.push({ + match_id: row.match_id, + match_name: `${row.home_team_name} vs ${row.away_team_name}`, + reason: `Yetersiz geçmiş veri (min ${3} maç gerekli)`, + }); + continue; + } + + // Market filtresi uygula + let filteredSignals = candidate.signals; + if (allowedMarkets) { + filteredSignals = filteredSignals.filter((s) => + allowedMarkets.some((m) => s.market.includes(m)), + ); + } + + // Min signal filtresi + filteredSignals = filteredSignals.filter( + (s) => s.combinedSignal >= minSignal, + ); + + if (filteredSignals.length === 0) { + rejected.push({ + match_id: row.match_id, + match_name: `${row.home_team_name} vs ${row.away_team_name}`, + reason: `Kombinasyon sinyali ${(minSignal * 100).toFixed(0)}% eşiğinin altında`, + }); + continue; + } + + // En güçlü sinyali seç + candidate.signals = filteredSignals; + candidate.bestSignal = filteredSignals[0]; + allCandidates.push({ candidate, row }); + } + + this.logger.log( + `[FrequencyCoupon] ${allCandidates.length} candidates passed filters, ${rejected.length} rejected`, + ); + + // 4. En güçlü sinyale göre sırala + allCandidates.sort( + (a, b) => + (b.candidate.bestSignal?.confidence ?? 0) - + (a.candidate.bestSignal?.confidence ?? 0), + ); + + // 5. Çeşitlilik: aynı ligden max 2 maç + const selected: typeof allCandidates = []; + const leagueCount = new Map(); + + for (const entry of allCandidates) { + if (selected.length >= maxMatches) break; + + const lid = entry.candidate.leagueId; + const currentCount = leagueCount.get(lid) || 0; + if (currentCount >= 2) { + rejected.push({ + match_id: entry.candidate.matchId, + match_name: `${entry.candidate.homeTeamName} vs ${entry.candidate.awayTeamName}`, + reason: `Aynı ligden zaten 2 maç seçildi (${entry.candidate.leagueName})`, + }); + continue; + } + + selected.push(entry); + leagueCount.set(lid, currentCount + 1); + } + + // 6. Sonucu oluştur + const bets: FrequencyCouponResult["bets"] = []; + let totalOdds = 1; + let combinedHitRate = 1; + const reasoning: string[] = []; + + for (const { candidate, row } of selected) { + const signal = candidate.bestSignal!; + const betOdds = this.frequencyEngine.getMarketOdds(row, signal.market); + + if (betOdds <= 0) continue; + + const homeBand = this.frequencyEngine.getOddsBand(candidate.homeOdds); + const awayBand = this.frequencyEngine.getOddsBand(candidate.awayOdds); + + // Lig profili belirle + let leagueProfile = "NORMAL"; + if (signal.leagueBonus > 0.02) leagueProfile = "GOLCU"; + else if (signal.leagueBonus < -0.02) leagueProfile = "DEFANSIF"; + + bets.push({ + match_id: candidate.matchId, + match_name: `${candidate.homeTeamName} vs ${candidate.awayTeamName}`, + league: candidate.leagueName, + market: signal.market, + pick: signal.pick, + home_signal: parseFloat(signal.homeSignal.toFixed(3)), + away_signal: parseFloat(signal.awaySignal.toFixed(3)), + combined_signal: parseFloat(signal.combinedSignal.toFixed(3)), + league_profile: leagueProfile, + historical_hit_rate: parseFloat(signal.combinedSignal.toFixed(3)), + odds: betOdds, + home_odds_band: homeBand, + away_odds_band: awayBand, + home_match_count: signal.homeMatchCount, + away_match_count: signal.awayMatchCount, + }); + + totalOdds *= betOdds; + combinedHitRate *= signal.combinedSignal; + + reasoning.push( + `${candidate.homeTeamName} vs ${candidate.awayTeamName}: ` + + `${signal.pick} — Ev(${homeBand}): ${(signal.homeSignal * 100).toFixed(0)}% (${signal.homeMatchCount} maç), ` + + `Dep(${awayBand}): ${(signal.awaySignal * 100).toFixed(0)}% (${signal.awayMatchCount} maç)`, + ); + } + + totalOdds = parseFloat(totalOdds.toFixed(2)); + const expectedValue = parseFloat((combinedHitRate * totalOdds).toFixed(3)); + + return { + strategy: "FREQUENCY", + generated_at: new Date().toISOString(), + bets, + total_odds: totalOdds, + expected_hit_rate: parseFloat(combinedHitRate.toFixed(4)), + expected_value: expectedValue, + ev_positive: expectedValue > 1.0, + reasoning, + rejected_matches: rejected, + }; + } +} + +// ───────────────────────────────────────────────────────────── +// Frequency Coupon Result Interface +// ───────────────────────────────────────────────────────────── + +export interface FrequencyCouponResult { + strategy: "FREQUENCY"; + generated_at: string; + bets: Array<{ + match_id: string; + match_name: string; + league: string; + market: string; + pick: string; + home_signal: number; + away_signal: number; + combined_signal: number; + league_profile: string; + historical_hit_rate: number; + odds: number; + home_odds_band: string; + away_odds_band: string; + home_match_count: number; + away_match_count: number; + }>; + total_odds: number; + expected_hit_rate: number; + expected_value: number; + ev_positive: boolean; + reasoning: string[]; + rejected_matches: Array<{ + match_id: string; + match_name: string; + reason: string; + }>; } const MATCH_COMMENTARY_SYSTEM_PROMPT = `Sen uzman bir futbol bahis analistisin. Sana verilen model çıktısını analiz edip kısa, net ve aksiyon odaklı Türkçe bir yorum yaz.