
    iZ)                         d Z ddlZddlZddlZddlZddlmZmZ ddlmZm	Z	m
Z
mZ ddlmZmZmZ ddlmZ ddlmZmZ ddlmZmZmZmZmZmZmZ dd	ed
edee	   fdZdde de de fdZ! G d d      Z"y)u  
PolyEdge — Backtest Engine

Simulates Polymarket 5-min BTC binary options using historical M5 data.

Each M5 candle simulates one binary market:
- Strike = open price of the candle
- Market YES price = simulated from order book model
- Resolution: did BTC close above the strike?
    N)datetime	timedelta)ListDictAnyOptional)calc_fair_valuerealized_volmomentum_drift)SignalEngine)RiskManagercalc_taker_fee)INITIAL_BANKROLLSLIPPAGE_PCTCOMMISSION_MODELVOL_LOOKBACK_BARSMOMENTUM_LOOKBACKMOMENTUM_WEIGHTUSE_LIMIT_ORDERSfilepathmax_rowsreturnc           	         g g }}t        | d      5 }t        j                  |      }t        |       d}|D ]_  }|r||k\  r nV	 |d   }t	        j
                  |dd d      }	t        |d         }
|j                  |
       |j                  |	       |dz  }a ddd       g }d}dx}x}x}}t        ||      D ]l  \  }	}|	j                  |	j                  dz  dz  dd      }||k7  r$||j                  |||||d	       |}|x}x}x}}St        ||      }t        ||      }|}n |r|j                  |||||d	       |S #  Y xY w# 1 sw Y   xY w)
z/Load tick data and resample to M5 OHLC candles.rr   N   z%Y%m%d %H:%M:%S      )minutesecondmicrosecond)timeopenhighlowclose)r"   csvreadernextr   strptimefloatappendzipreplacer   maxmin)r   r   pricestimesfr'   countrowtstbidcandlescurrent_startohlcp	bar_starts                      5/var/www/html/crpytotradingbot/polymarket/backtest.pyload_m5_candlesrA      s   EF	h	 AV 	CEX-V%%b"g/@ACFmc"Q
		$ GMAAE6" 1IIahh!mq%8PQIR	%()qQ   &MAAAq	AAq	AA !qQ
 	
 N; s$   1E
AEE
EE

E
fair_valuenoisec                 .    t        dt        d|             S )u  
    Simulate what Polymarket's YES price would be.
    
    In reality, the market price is set by other traders.
    We model it as: market_price = fair_value + noise
    where noise represents market inefficiency.
    
    For backtesting, we use a simple model:
    - Some bars: market is efficient (price ≈ fair value)
    - Some bars: market overshoots (trend followers push too far)
    - Some bars: market undershoots (slow to react)
    
    Uses deterministic noise based on candle data to avoid randomness.
    g{Gz?Gz?)r.   r/   )rB   rC   s     r@   simulate_market_pricerF   O   s    " tSz*++    c                   t    e Zd ZdZefdefdZddedefdZ	dde
e   defdZdd	ed
eeef   fdZddefdZy)BacktestEnginezF
    Runs a backtest of the PolyEdge strategy on historical data.
    bankrollc                 ^    t               | _        t        |      | _        g | _        g | _        y N)r   signal_enginer   risk_managerr8   results)selfrJ   s     r@   __init__zBacktestEngine.__init__h   s'    )^'1#%#%rG   r   r   c                 n    t        ||      | _        t        dt        | j                         d|        y)z Load candle data from tick file.zLoaded z M5 candles from N)rA   r8   printlen)rP   r   r   s      r@   	load_datazBacktestEngine.load_datan   s0    &x:DLL)**;H:FGrG   	filepathsc           	      (   g }|D ]V  }t        ||      }|j                  |       t        dt        |       dt        j
                  j                  |              X t        |d       | _        t        dt        | j                         d       y)z)Load candles from multiple monthly files.z	  Loaded z candles from c                     | d   S )Nr!    )xs    r@   <lambda>z.BacktestEngine.load_multiple.<locals>.<lambda>z   s
    6 rG   )keyzTotal: z candlesN)	rA   extendrS   rT   ospathbasenamesortedr8   )rP   rV   r   all_candlesfpr=   s         r@   load_multiplezBacktestEngine.load_multiples   s     	LBH-Aq!Ic!fX^BGG4D4DR4H3IJK	L k/BCDLL)*(34rG   market_noiser   c           	      |   t        t        t              dz   }d}d}t        | j                        D ]  \  }}|dz  }|d   j                         }||k7  r|}| j                  j                          | j                  j                  |d          | j                  j                          ||k  r~|d   }| j                  |dz
     d   }	| j                  j                         }
| j                  j                         }t        |	||
d|t        	      }ddl}t!        |j#                  |d    j%                               j'                         dd
 d      }|dz  dz  dz
  dz  |z  }t        dt)        d||z               }| j                  j+                  |	||d      }|p| j                  j-                  |      }|dk  r|d   |kD  }|d   dk(  r|t.        z   }t)        |d      }||z  }|}n d|z
  t.        z   }t)        |d      }||z  }| }|r	|d|z
  z  }n| }t0        rt2        dk(  rd}nt5        ||      }i d|dt7        |d         d|d   d|d|d|d|d|d|d||z
  d|d   d|d   d |d    d!|d!   d"|	d#|d$|d   }| j                  j9                  |       | j:                  j=                  |        | j                  j?                         }||d%<   ||d&<   ||d'<   | j                  r<t7        | j                  |   d         |d(<   t7        | j                  d)   d         |d*<   |S )+u&  
        Run the backtest.
        
        For each M5 candle after warmup:
        1. The "binary market" has strike = candle open price
        2. We model what the YES price would be on Polymarket
        3. Our signal engine determines if there's a mispricing
        4. If signal fires, we size and place the trade
        5. Candle closes → binary resolves → P&L recorded
        
        Args:
            market_noise: How much the market misprice (0 = efficient, 0.05 = noisy)
        
        Returns:
            Results dict
        
   Nr   r   r!   r%   r"   g      @)current_pricestrikevoltime_to_expiry_mindriftmomentum_weight      i  g      ?   g?gffffff?)rh   ri   market_yes_pricetime_remaining_min	directionbuy_yesrE   makerbarbet_size	buy_priceshareswonpnlfeenet_pnledgerB   market_pricerj   	btc_priceri   	btc_close
total_barswarmup_barsre   
start_dateend_date) r.   r   r   	enumerater8   daterN   new_dayrM   updatetickget_vol	get_driftr	   r   hashlibintmd5encode	hexdigestr/   generate_signal
size_trader   r   r   r   strrecord_traderO   r+   	get_stats)rP   re   warmupcurrent_day	bar_counticandle
candle_dayri   rh   rj   rl   fvr   seed	noise_valrq   signalrw   btc_above_strikerx   ry   rz   r{   r|   trade_resultstatss                              r@   runzBacktestEngine.run}   s$   " &(9:R?	"4<<0 q	.IAvNI  ,,.J[((!!))+ %%fWo6""$ 6z
 F^F
 !LL1-g6M$$,,.C&&002E +#& /B w{{fVn%5#=#=#?@JJLRaPRTUD+-3q8<GI"4T2	>)BC ''77+!1#&	 8 F ~ ((33F;H1}  &g7k"i/,|;		40	!I-&!11\A		40	!I-** I.i  $4$?$Y9qF6N+ VK0 H	
 Y & s s s 39 v f\2 ~ 6 ve} ]  &!" VG_#L( **<8LL-cq	.h !!++-'l%m ,n<<"%dll6&:6&B"CE, #DLL$4V$< =E*rG   
output_dirc                    t        j                  |d       t        j                         j	                  d      }| j
                  j                         }t        | d| dd      5 }t        j                  ||d       d	d	d	       | j                  rt        | d
| dd      5 }| j                  d   j                         }|j                  dj                  |      dz          | j                  D ].  |j                  dj                  fd|D              dz          0 	 d	d	d	       t        | d| dd      5 }|j                  d       t        | j
                  j                        D ]  \  }}|j                  | d|dd        	 d	d	d	       t!        d| d| d       y	# 1 sw Y   .xY w# 1 sw Y   xY w# 1 sw Y   5xY w)zSave detailed results to files.T)exist_okz%Y%m%d_%H%M%Sz/polyedge_stats_z.jsonwrp   )indentNz/polyedge_trades_z.csvr   ,
c              3   :   K   | ]  }t        |           y wrL   )r   ).0kr   s     r@   	<genexpr>z.BacktestEngine.save_results.<locals>.<genexpr>#  s     $=1S1Y$=s   z/polyedge_equity_ztrade_num,equity
z.2fzResults saved to z/polyedge_*_z.*)r^   makedirsr   nowstrftimerN   r   r"   jsondumprO   keyswritejoinr   equity_curverS   )	rP   r   	timestampr   r2   r   r   eqr   s	           @r@   save_resultszBacktestEngine.save_results  s   
J.LLN++O<	 !!++-ZL 05A3G 	*1IIeQq)	* <<$5i[EsK Fq||A++--. FAGGCHH$=$==DEFF ZL 1)DA3G 	+1GG()"4#4#4#A#AB +21#Qr#hb)*+	+
 	!*\)BGH#	* 	*
F F	+ 	+s&   (F-'A>F: AG-F7:GGNr   )g        )rO   )__name__
__module____qualname____doc__r   r*   rQ   r   r   rU   r   rd   r   r   r   r   rY   rG   r@   rI   rI   c   sr     *: & &H# H H
5tCy 5C 5S SS#X SjIs IrG   rI   r   )gQ?)#r   r&   mathr   r^   r   r   typingr   r   r   r   rB   r	   r
   r   signalsr   riskr   r   configr   r   r   r   r   r   r   r   r   rA   r*   rF   rI   rY   rG   r@   <module>r      s   	    	 ( , , D D   ,  /c /S /d /d,e ,E ,U ,(HI HIrG   