diff --git a/.github/workflows/gemini-review.yml b/.github/workflows/gemini-review.yml index 58196b1..f729c5f 100644 --- a/.github/workflows/gemini-review.yml +++ b/.github/workflows/gemini-review.yml @@ -70,6 +70,9 @@ jobs: github_pr_number: '${{ github.event.pull_request.number }}' settings: |- { + "security": { + "trustAllWorkspaces": true + }, "model": { "maxSessionTurns": 25 }, diff --git a/advanced_predictors.py b/advanced_predictors.py index e31c127..22ae397 100644 --- a/advanced_predictors.py +++ b/advanced_predictors.py @@ -19,10 +19,12 @@ def __init__( self, impact_bps_per_imbalance: Decimal, min_confidence: Decimal, + trade_flow_volatility_scaling: Decimal, volatility_window: int = 10, # 计算波动率使用的窗口大小 ) -> None: self.impact_bps_per_imbalance = impact_bps_per_imbalance self.min_confidence = min_confidence + self.trade_flow_volatility_scaling = trade_flow_volatility_scaling # 使用 deque 可以高效地在固定大小的窗口上进行操作 self.mid_price_history = deque(maxlen=volatility_window) @@ -33,20 +35,22 @@ def predict(self, features: AdvancedMarketFeatures) -> Prediction: # 1. 计算波动率因子 self.mid_price_history.append(features.quote.mid) volatility = Decimal(statistics.stdev(self.mid_price_history)) if len(self.mid_price_history) > 1 else Decimal("0") + # 将波动率归一化,使其成为一个相对指标,避免受价格本身大小的影响 + normalized_volatility = volatility / features.quote.mid if features.quote.mid > 0 else Decimal("0") # 2. 计算基础价格偏移 (来自原始ImbalancePredictor) base_edge_bps = self._microprice_edge_bps(features) + features.imbalance * self.impact_bps_per_imbalance - # 3. 计算交易流调整量 (我们的新alpha!) - # 规则:如果交易流为正(买方更激进),我们稍微调高预测价,反之亦然。 - # 调整的幅度可以根据置信度等进行缩放。 - trade_flow_adjustment_bps = features.trade_flow * Decimal("10") # 示例:每0.1的flow,价格偏移1 bps + # 3. 计算交易流调整量 (新的Alpha) + # 规则:交易流的影响力与波动率成反比。波动越大,交易流的权重越低。 + volatility_dampening_factor = (Decimal("1") + normalized_volatility * Decimal("100")) # 波动率越高,这个因子越大 + trade_flow_adjustment_bps = (features.trade_flow * self.trade_flow_volatility_scaling) / volatility_dampening_factor # 4. 组合所有因子 total_edge_bps = base_edge_bps + trade_flow_adjustment_bps - # 5. 风险调整:如果波动率过高,降低预测的偏移量,甚至不进行预测 - if volatility > (features.quote.mid * Decimal("0.01")): + # 5. 风险调整:如果波动率过高,降低预测的偏移量 + if normalized_volatility > Decimal("0.01"): # 价格在窗口期内波动超过1% total_edge_bps *= Decimal("0.5") reason_suffix = ";vol_dampen" else: diff --git a/config.py b/config.py index 124fd33..8ded0d7 100644 --- a/config.py +++ b/config.py @@ -113,6 +113,8 @@ class BotConfig: cancel_unfilled_after_ms: int = _int("CANCEL_UNFILLED_AFTER_MS", "0") prediction_latency_ms: int = _int("PREDICTION_LATENCY_MS", "180") prediction_edge_bps: Decimal = _decimal("PREDICTION_EDGE_BPS", "8") + # 交易流对价格预测的影响力,会根据波动率进行缩放。值越大,交易流的影响越大。 + trade_flow_volatility_scaling: Decimal = _decimal("TRADE_FLOW_VOLATILITY_SCALING", "20") min_prediction_confidence: Decimal = _decimal("MIN_PREDICTION_CONFIDENCE", "0.10") orderbook_imbalance_levels: int = _int("ORDERBOOK_IMBALANCE_LEVELS", "3") dry_run: bool = _bool("DRY_RUN", "true") diff --git a/market_maker.py b/market_maker.py index 384b2e7..e36f5ca 100644 --- a/market_maker.py +++ b/market_maker.py @@ -99,6 +99,7 @@ def bootstrap(self) -> None: self.predictor = AdvancedPredictor( impact_bps_per_imbalance=self.config.prediction_edge_bps, min_confidence=self.config.min_prediction_confidence, + trade_flow_volatility_scaling=self.config.trade_flow_volatility_scaling, ) if self.data_recorder is None and self.condition_id: self.data_recorder = DataRecorder(self.condition_id) diff --git a/polymarket_adapter.py b/polymarket_adapter.py index b4ef5c3..407a449 100644 --- a/polymarket_adapter.py +++ b/polymarket_adapter.py @@ -357,10 +357,19 @@ def today_rewards_estimate(self, condition_id: str) -> Decimal: except Exception as exc: LOGGER.debug("Reward estimate unavailable: %s", exc) return Decimal("0") + if isinstance(result, dict): value = result.get("total") or result.get("earnings") or result.get("amount") or "0" - return Decimal(str(value)) - return Decimal(str(result or "0")) + try: + return Decimal(str(value)) + except ArithmeticError: + LOGGER.warning("Invalid decimal value for reward from dict: %s", value) + return Decimal("0") + try: + return Decimal(str(result or "0")) + except ArithmeticError: + LOGGER.warning("Invalid decimal value for reward: %s", result) + return Decimal("0") @staticmethod def _close_only_time(market: dict[str, Any]) -> tuple[str, str]: