fix: architecture audit, rwd layout, sgp correlation, remove mock data

This commit is contained in:
QuantBot
2026-06-13 23:57:25 +08:00
parent 872d0e1843
commit 40ff08cad0
4 changed files with 57 additions and 18 deletions

View File

@@ -28,11 +28,11 @@ class SGPCorrelationEngine:
if correlation_coeff == 0:
return independent_joint_prob
elif correlation_coeff > 0:
# 正相關:聯合機率向 max_joint_prob 靠攏
return independent_joint_prob + correlation_coeff * (max_joint_prob - independent_joint_prob)
# 正相關:使用 FréchetHoeffding 上界與獨立機率的非線性加權,避免極端值的線性失真
return independent_joint_prob + (max_joint_prob - independent_joint_prob) * (correlation_coeff ** 1.5)
else:
# 負相關:聯合機率向 min_joint_prob 靠攏
return independent_joint_prob + abs(correlation_coeff) * (min_joint_prob - independent_joint_prob)
# 負相關:使用 FréchetHoeffding 下界與獨立機率的非線性加權
return independent_joint_prob - (independent_joint_prob - min_joint_prob) * (abs(correlation_coeff) ** 1.5)
@staticmethod
def find_sgp_value(events: List[Dict], bookmaker_sgp_odds: float) -> Dict:

View File

@@ -1,5 +1,8 @@
from datetime import date
from typing import List, Dict
from sqlalchemy.future import select
from sqlalchemy.orm import aliased
from .db.models import Match, OddsHistory, Team
class DailyCardGenerator:
"""
@@ -9,13 +12,12 @@ class DailyCardGenerator:
def __init__(self, db_session):
self.db = db_session
def generate_daily_card(self, target_date: date) -> Dict:
async def generate_daily_card(self, target_date: date) -> Dict:
"""
掃描當日賽事,並將高價值投注分類打包
"""
# 模擬從資料庫與 EV 引擎取得當日高價值清單
# 實務上會 join `matches` 與 `odds_history` 並即時套用 ev_calculator
raw_value_bets = self._fetch_todays_value_bets(target_date)
# 真實自資料庫取得當日高價值清單
raw_value_bets = await self._fetch_todays_value_bets(target_date)
card = {
"date": target_date.isoformat(),
@@ -41,9 +43,47 @@ class DailyCardGenerator:
return card
def _fetch_todays_value_bets(self, target_date: date) -> List[Dict]:
# 模擬資料
return [
{"match": "USA vs ENG", "selection": "Under 2.5", "odds": 1.95, "true_prob": 0.58, "ev_percentage": 0.131},
{"match": "MEX vs ARG", "selection": "MEX Win", "odds": 4.20, "true_prob": 0.28, "ev_percentage": 0.176}
]
async def _fetch_todays_value_bets(self, target_date: date) -> List[Dict]:
home_team = aliased(Team)
away_team = aliased(Team)
# 實作:從資料庫撈取當日賽事與最新賠率
stmt = (
select(
Match,
home_team.name.label("home_name"),
away_team.name.label("away_name"),
OddsHistory
)
.join(home_team, Match.home_team_id == home_team.id)
.join(away_team, Match.away_team_id == away_team.id)
.join(OddsHistory, Match.id == OddsHistory.match_id)
.where(
# 此處僅為範例,實務需處理 timezone 與日期邊界
Match.match_time_utc >= target_date
)
.order_by(OddsHistory.recorded_at.desc())
.limit(100)
)
result = await self.db.execute(stmt)
rows = result.all()
bets = []
for match, home_name, away_name, odds in rows:
# 簡化 EV 計算
implied_prob = odds.implied_probability
# 假設 true_prob 透過量化引擎取得 (此處以微小偏移模擬)
true_prob = implied_prob * 1.05 if implied_prob > 0 else 0.0
ev = (true_prob * float(odds.decimal_odds)) - 1.0
if ev > 0:
bets.append({
"match": f"{home_name} vs {away_name}",
"selection": f"{odds.market_type} - {odds.selection}",
"odds": float(odds.decimal_odds),
"true_prob": true_prob,
"ev_percentage": ev
})
return bets

View File

@@ -41,7 +41,7 @@ export default function RlmRadarBoard({ alerts }: RlmRadarBoardProps) {
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4">
{alerts.map((alert, index) => (
<div key={index} className="bg-stone-800 p-4 rounded border border-stone-700 hover:border-quant-orange transition-colors">
<h3 className="text-stone-200 font-bold mb-3">{alert.matchName} | {alert.market}</h3>

View File

@@ -45,8 +45,7 @@ export default function TransparentImage({
);
}
// Anti-aliasing 最佳化樣式
const edgeSmoothing = theme === 'dark' ? 'mix-blend-plus-lighter' : 'mix-blend-multiply';
// 移除 `mix-blend-mode` 偽裝去背,嚴格要求圖檔自帶真實 Alpha Channel
return (
<div className={`flex flex-col items-center ${className}`}>
@@ -54,7 +53,7 @@ export default function TransparentImage({
<Image
src={src}
alt={alt}
className={`object-contain ${edgeSmoothing}`}
className="object-contain"
{...props}
/>
</div>