update 03-29 01:36
This commit is contained in:
@@ -65,6 +65,8 @@ class RiskConfig:
|
||||
class FeesConfig:
|
||||
taker_fee_5m: float = 0.0156
|
||||
taker_fee_15m: float = 0.03
|
||||
fee_rate: float = 0.045
|
||||
fee_exponent: int = 1
|
||||
|
||||
def fee_for_timeframe(self, timeframe: str) -> float:
|
||||
"""Return the taker fee for a given timeframe string (e.g. '5M')."""
|
||||
@@ -76,6 +78,13 @@ class FeesConfig:
|
||||
raise ValueError(f"Unknown timeframe '{timeframe}'; expected one of {list(mapping)}")
|
||||
return mapping[timeframe]
|
||||
|
||||
def dynamic_fee(self, price: float, shares: int = 1) -> float:
|
||||
"""Compute Polymarket's dynamic taker fee for a given price and share count.
|
||||
|
||||
Formula: shares * price * fee_rate * (price * (1 - price)) ** fee_exponent
|
||||
"""
|
||||
return shares * price * self.fee_rate * (price * (1.0 - price)) ** self.fee_exponent
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BinanceConfig:
|
||||
|
||||
@@ -109,7 +109,8 @@ class TemporalArbStrategy:
|
||||
)
|
||||
|
||||
# 6. Edge calculation (after fees)
|
||||
taker_fee = self.fees.fee_for_timeframe(timeframe)
|
||||
# Use dynamic fee formula: fee per share / price = effective fee rate
|
||||
taker_fee = self.fees.dynamic_fee(poly_price, 1) / poly_price
|
||||
edge = estimated_prob - poly_price - taker_fee
|
||||
|
||||
if edge < self.arb.min_edge:
|
||||
@@ -118,7 +119,7 @@ class TemporalArbStrategy:
|
||||
# 7. Position sizing
|
||||
asset = Asset(symbol)
|
||||
size = self.calculate_kelly_size(
|
||||
edge=edge,
|
||||
estimated_prob=estimated_prob,
|
||||
price=poly_price,
|
||||
balance=self.balance,
|
||||
max_size=self.risk.max_position_per_market_usd,
|
||||
@@ -181,25 +182,25 @@ class TemporalArbStrategy:
|
||||
"""
|
||||
abs_change = abs(price_change_pct)
|
||||
|
||||
# Factor 1: Base probability from price magnitude
|
||||
# 0.15% → ~70%, 0.3% → ~82%, 0.5% → ~90%, 1.0%+ → ~95%
|
||||
base_prob = 0.55 + abs_change * 1.0 # 1.0 scaling factor
|
||||
base_prob = min(base_prob, 0.95)
|
||||
# Factor 1: Sigmoid base probability from price magnitude
|
||||
# k=18.0 steepness, inflection at 0.10% change
|
||||
# 0.03% → ~0.53, 0.10% → ~0.65, 0.20% → ~0.80, 0.50% → ~0.93
|
||||
k = 18.0
|
||||
threshold = 0.10
|
||||
sigmoid_val = 1.0 / (1.0 + math.exp(-k * (abs_change - threshold)))
|
||||
base_prob = 0.52 + sigmoid_val * 0.43 # maps [0,1] → [0.52, 0.95]
|
||||
|
||||
# Factor 2: Time decay — more time elapsed = more confirmation
|
||||
# If 80% of window has passed and price is still in this direction,
|
||||
# the probability of reversal is lower
|
||||
elapsed_fraction = max(0, 1.0 - (time_remaining / total_window_sec))
|
||||
# Sigmoid-like boost: ramps up in the last 40% of the window
|
||||
elapsed_fraction = 1.0 - (time_remaining / total_window_sec) if total_window_sec > 0 else 0.5
|
||||
# Ramps up in the last 40% of the window
|
||||
time_factor = 1.0 + 0.08 * max(0, elapsed_fraction - 0.6) / 0.4
|
||||
time_factor = min(time_factor, 1.08)
|
||||
|
||||
# Factor 3: Volatility / momentum strength
|
||||
# Very large moves (>0.5%) get extra confidence
|
||||
if abs_change > 0.5:
|
||||
vol_boost = min(0.05, (abs_change - 0.5) * 0.1)
|
||||
else:
|
||||
vol_boost = 0.0
|
||||
vol_boost = min(0.05, (abs_change - 0.5) * 0.1) if abs_change > 0.5 else 0.0
|
||||
|
||||
final_prob = base_prob * time_factor + vol_boost
|
||||
return min(0.95, max(0.50, final_prob))
|
||||
@@ -210,7 +211,7 @@ class TemporalArbStrategy:
|
||||
|
||||
def calculate_kelly_size(
|
||||
self,
|
||||
edge: float,
|
||||
estimated_prob: float,
|
||||
price: float,
|
||||
balance: float,
|
||||
max_size: float,
|
||||
@@ -224,7 +225,7 @@ class TemporalArbStrategy:
|
||||
return 0
|
||||
|
||||
b = (1.0 / price) - 1.0 # Payout odds
|
||||
p = edge + price # estimated_prob (edge = prob - price - fee)
|
||||
p = estimated_prob
|
||||
q = 1.0 - p
|
||||
|
||||
if b <= 0:
|
||||
|
||||
Reference in New Issue
Block a user