Files
iddaai-be/mds/MISSED_OPPORTUNITIES_SCRIPT.md
fahricansecer 2f0b85a0c7
Deploy Iddaai Backend / build-and-deploy (push) Failing after 18s
first (part 2: other directories)
2026-04-16 15:11:25 +03:00

11 KiB
Raw Permalink Blame History

Missed Opportunity Analysis Script

Dosya: ai-engine/scripts/missed_opportunities.py Tarih: 2026-03-18 Amaç: PASS grade'li ama gerçekte tutan pick'leri tespit ederek grading threshold'larını optimize etmek


1. Ne Yapıyor?

Bu script, AI Engine'in "oynamayın" (PASS) dediği ama aslında tutan pick'leri bulur. Böylece:

  • Hangi PASS gate'inin en çok "kaçırılmış fırsat" ürettiğini gösterir
  • Threshold'ların gevşetilmesi gereken yerleri tespit eder
  • Edge bucket analizi ile hangi aralıklardaki PASS'lerin tuttuğunu gösterir
  • Potansiyel kaybedilen kârı hesaplar

2. Kullanım

cd ai-engine

# Son 5 gün (varsayılan)
python scripts/missed_opportunities.py

# Son 10 gün
python scripts/missed_opportunities.py --days 10

# Belirli tarih aralığı
python scripts/missed_opportunities.py --date 2026-03-01 --end-date 2026-03-15

# Günlük max maç limitini değiştir (varsayılan: 15)
python scripts/missed_opportunities.py --days 7 --max-per-day 25

⚠️ Script salt okunurdur — DB'ye hiçbir şey yazmaz, yalnızca rapor üretir.


3. Çalışma Akışı

1. top_leagues.json → sadece ana ligler
2. DB'den FT (Full Time) maçları çeker
3. Her maçı SingleMatchOrchestrator ile analiz eder
4. bet_summary'deki PASS pick'leri filtreler
5. actual_outcome() ile gerçek sonuçla karşılaştırır
6. Tutanları "missed opportunity" olarak kaydeder
7. 6 farklı rapor tablosu üretir

4. Dosya Yapısı ve Önemli Fonksiyonlar

actual_outcome(sh, sa, market, pick) → bool

Gerçek skor ile pick'in doğruluğunu kontrol eder.

Market Açıklama Kontrol Mantığı
MS Maç Sonucu (1X2) sh > sa → "1", sh < sa → "2", sh == sa → "X"
DC Çifte Şans (1X, X2, 12) İki sonucun birini kapsar
OU15 Üst/Alt 1.5 total > 1.5
OU25 Üst/Alt 2.5 total > 2.5
OU35 Üst/Alt 3.5 total > 3.5
BTTS Karşılıklı Gol sh > 0 AND sa > 0
OE Tek/Çift total % 2 == 1

Atlanan market'ler: HT, HT_OU05, HTFT (ilk yarı market'leri, skor ayrıştırması yok)

run_analysis(start_date, end_date, max_per_day)

Ana analiz fonksiyonu. Her maç için:

  1. SingleMatchOrchestrator.analyze_match(match_id) çağrısı
  2. bet_summary dizisindeki her item'ı kontrol
  3. playable=False veya bet_grade="PASS" olanları filtreler
  4. actual_outcome() ile tutan PASS pick'leri toplar

Her missed opportunity entry'si şu alanları içerir:

{
    "date":       "2026-03-15",
    "match":      "Fenerbahçe vs Galatasaray",
    "score":      "2-1",
    "market":     "MS",
    "pick":       "1",
    "odds":       1.85,
    "ev_edge":    0.045,
    "confidence": 62.5,
    "grade":      "PASS",
    "stake":      0.0,
    "playable":   False,
    "reasons":    ["insufficient_play_score", "lineup_not_confirmed"]
}

5. Rapor Bölümleri (6 Tablo)

5.1. MATCH-BY-MATCH DETAIL

Her maç için tutan PASS pick'leri ayrıntılı gösterir. Her satırın altında PASS sebebi belirtilir:

  2026-03-15 | Fenerbahçe vs Galatasaray (2-1)
    ✅ HIT (PASS): MS     → 1            odds=1.85  edge=+0.045  conf=62.5%  grade=PASS
       └─ PASS reason: insufficient_play_score

5.2. MARKET SUMMARY

Market bazlı aggregate istatistikler:

MARKET     HIT  AVG_EDGE  AVG_ODDS  AVG_CONF
MS          12    +0.038     1.92    55.3%
OU25         8    +0.041     1.78    58.1%
BTTS         5    +0.029     2.05    51.2%

Kullanım: Hangi market'te en çok fırsat kaçırılıyor? OU25'te edge ortalaması yüksekse → OU25 threshold'u gevşetilebilir.

5.3. EDGE BUCKET ANALYSIS

Edge değerine göre PASS pick'lerin dağılımı:

EDGE_RANGE         HIT  AVG_ODDS  AVG_CONF  NOTE
edge < 0%            3     2.10    45.2%
0% to +2%           12     1.75    52.8%
+2% to +5%          18     1.90    56.1%  ← potansiyel grade upgrade adayı
+5% to +10%          7     2.15    60.3%  ← potansiyel grade upgrade adayı
+10%+                2     1.65    68.4%  ← neden PASS? kontrol et!

Akıllı notlar:

  • +2% to +5% ve +5% to +10% aralığı → pozitif edge var, playable yapılabilir
  • +10%+ → ciddi edge olmasına rağmen PASS → muhtemelen konfidans veya kadro gate'i

5.4. PASS REASON BREAKDOWN (Yeni Eklenen)

En kritik tablo. Hangi PASS gate'inin en çok missed opportunity ürettiğini gösterir:

REASON                                     HIT  AVG_EDGE  AVG_ODDS  AVG_CONF  NOTE
insufficient_play_score                     42    +0.045     1.85    58.2%  ← threshold gevşetilebilir
lineup_not_confirmed                        28    +0.032     2.10    52.1%  ← post-match kadro bilgisi mevcut
below_calibrated_conf_threshold             15    +0.061     1.72    48.5%  ← edge yüksek, conf threshold düşürülebilir
lineup_insufficient_for_market               8    +0.028     1.95    55.0%  ← post-match kadro bilgisi mevcut

PASS reasons field'ı nereden geliyor?

SingleMatchOrchestratorapply_grading()bet_summary[].reasons listesine PASS sebepleri yazılır.

Bilinen reason key'leri:

Reason Key Açıklama Aksiyon Önerisi
insufficient_play_score Toplam play skoru threshold'un altı Threshold'u düşür
below_calibrated_conf_threshold Kalibrasyon konfidansı düşük Conf threshold'u market bazlı ayarla
lineup_not_confirmed Kadro onaylanmamış Post-match veriler için ihmal edilebilir
lineup_insufficient_for_market Bu market için kadro yetersiz Post-match veriler için ihmal edilebilir
insufficient_edge EV edge threshold altı Edge threshold'u incele
odds_out_of_range Odds kabul edilen aralığın dışı Odds range'i genişlet

Akıllı notlar mantığı:

  • insufficient_play_score + avg_edge > 3% → "threshold gevşetilebilir"
  • lineup_* reason'lar → "post-match kadro bilgisi mevcut" (tarihsel analizde kadro zaten belli)
  • below_calibrated_conf_threshold + avg_edge > 5% → "edge yüksek, conf threshold düşürülebilir"

5.5. TOP 15 MISSED (Highest Edge)

En yüksek edge'e sahip 15 tutan PASS pick. Her birinin altında PASS sebebi:

  1. Fenerbahçe vs Galatasaray         2-1   MS     1            odds=1.85  edge=+0.120  conf=62.5%
     └─ insufficient_play_score, lineup_not_confirmed
  2. Barcelona vs Real Madrid           3-2   OU25   Üst 2.5      odds=1.72  edge=+0.095  conf=58.1%
     └─ below_calibrated_conf_threshold

Kullanım: Bu listedeki pattern'leri incele. Hep aynı reason mı tekrarlıyor? → O gate'i gevşetmek en büyük getiriyi sağlar.

5.6. POTENTIAL PROFIT LOST

Flat 1-unit stake ile ne kadar kâr kaçırıldığının özeti:

  Tutan PASS pick sayısı:  87
  Kaçırılan toplam kâr:    +72.35 units
  Ortalama odds:           1.83
  Ortalama edge:           +0.041

6. Veri Akışı Diyagramı

┌───────────────┐       ┌──────────────────────┐
│ DB (matches)  │──────▶│ SingleMatchOrchestrator│
│ FT + top_league│       │   .analyze_match()    │
└───────────────┘       └───────┬──────────────┘
                                │
                        ┌───────▼──────────────┐
                        │   bet_summary[]      │
                        │   ├─ market          │
                        │   ├─ pick            │
                        │   ├─ playable        │
                        │   ├─ bet_grade       │
                        │   ├─ ev_edge         │
                        │   ├─ odds            │
                        │   ├─ calibrated_conf │
                        │   └─ reasons[]       │◀── PASS sebebi
                        └───────┬──────────────┘
                                │
                  grade=="PASS" || !playable
                                │
                        ┌───────▼──────────────┐
                        │ actual_outcome()     │
                        │ score vs pick check  │
                        └───────┬──────────────┘
                                │
                          correct == true
                                │
                        ┌───────▼──────────────┐
                        │ missed[]             │
                        │ 6 rapor tablosu      │
                        └──────────────────────┘

7. Threshold Tuning Rehberi

Bu raporu çalıştırdıktan sonra şu adımları izle:

  1. PASS REASON BREAKDOWN tablosuna bak → En çok hangi reason üretiyor?
  2. O reason'ın avg_edge'ine bak → Pozitif ve anlamlıysa threshold gevşetilebilir
  3. TOP 15 listesini incele → Tekrar eden pattern var mı?
  4. Edge Bucket'ta +5%+ bölümüne bak → Burada PASS olan pick'ler ciddi fırsat kaçırması
  5. Market Summary'de en çok kaçıran market'e bak → O market'in threshold'unu öncelikli ayarla

Threshold Değiştirme Noktaları

Parametre Dosya Açıklama
play_score_threshold config/grading.py Minimum play skoru
calibrated_conf_threshold config/grading.py Minimum kalibrasyon konfidansı
min_edge config/grading.py Minimum EV edge
odds_range config/grading.py Kabul edilen odds aralığı
lineup_required_pct config/grading.py Minimum kadro onay yüzdesi

8. Yapılan Değişiklikler (Change Log)

2026-03-18 — PASS Reason Breakdown Eklentisi

4 değişiklik noktası:

# Satır Değişiklik Açıklama
1 153 pass_reasons = item.get("reasons", []) bet_summary'den reasons field'ı okunuyor
2 181 "reasons": pass_reasons Entry dict'ine PASS sebepleri ekleniyor
3 226-232 Match detail'de reason gösterimi Her HIT satırının altında └─ PASS reason:
4 281-310 Yeni PASS REASON BREAKDOWN tablosu Reason bazlı count, avg_edge, avg_odds, avg_conf + akıllı notlar
5 319-326 TOP 15'te reason Her pick'in altında └─ reason_str

Eklenen importlar: Yok (mevcut defaultdict, Dict, List kullanıldı)

Yeni fonksiyon: Yok — tüm değişiklikler run_analysis() raporlama bölümünde