
    +3j7              	       2   d Z ddlZddlZddlZddlZddlZddl	Z	e	j                  j                  ej                  j                  ej                  j                  ej                  j                  e      d                   ddlmZ d Zedk(  r e        yy)a  
Validate Strategy Performance

This script runs a single backtest of a specific strategy configuration on a given dataset.
It is useful for verifying the performance of a strategy with specific parameters (often found via optimization)
and visualizing the trade list.

Usage:
    python strategies/validate_strategy.py --data <path_to_csv> --strategy_file <strategy_filename> [--show-trades]

Arguments:
    --data: Path to the OHLCV CSV data file.
    --strategy_file: Name of the strategy Python file in the strategies/ folder (e.g., strategy_rsi_gaussian.py).
    --show-trades: If present, prints the list of executed trades to the console.
    Nz..)SCORE_STARTc            	         t        j                  d      } | j                  ddd       | j                  dt        dd	
       | j                  dt        dd
       | j                  dt        d       | j                  dt        d       | j                  dt         j                  dd       | j                  dt        t
        dt
         d
       | j                  dg ddd       | j                  dt        d d!
       | j                         }|j                  }t        j                  j                  |      st        d"|        y t        j                  j                  t        j                  j                  t              |j                         }t        j                  j                  |      st        d#|        y t"        j$                  j'                  d$|      }t"        j$                  j)                  |      }|t*        j,                  d$<   |j.                  j1                  |       t        d%| d&       t3        j4                  |      }|j6                  j                  j9                         j                  j;                         |_        t3        j<                  |d'   d(      j>                  jA                  d       |d'<   t3        jB                  d)      }t3        jB                  d*      }|jD                  |d'   |k\  |d'   |k  z     jG                         jI                  d+      }i }	|jJ                  rt        j                  j                  |jJ                        rd,d l&}
t        d-|jJ                   d&       |jJ                  jO                  d.      rKt3        j4                  |jJ                        }|jP                  d,   jS                         }	t        d/|	        nX|jJ                  jO                  d0      r=tU        |jJ                        5 }|
jW                  |      }	d d d        t        d/|	        t        d1        |jX                  |fi |	}|jZ                  dk7  rd2}||j6                  vrt        d3| d4       n|j\                  }|jZ                  d5k(  r"||   |k  }|d6   |z  }d7|jD                  |d6f<   n!||   |k\  }|d6   |z  }d7|jD                  |d6f<   |j_                         }t        d8|jZ                   d9| d:| d;       d }d }|j`                  rQtc        |d<      r-	 |je                  |jG                         |jf                  =      }ntk        |j                    d>      }||d6   |d?   z     jG                         }d@|dA<   dB|jD                  |d6   dAf<   dC|jD                  |d?   dAf<   |jl                  rgt        dD       g dE}g dF}|D ]"  }||j6                  v s|jo                  |       $ t        ||   jq                  dG      js                  d7H             dI}dJ}|}|}dK}g } d7}!dK}"d,}#d,}$g }%g }&g }'dK}(dK})|ju                         D ]#  \  }*}+|+d6   r"d}!|+dL   }"|#dMz  }#dK}(dK})|%jo                  |       .|!r|+dN   |"z
  |"z  },|dM|,z   z  }-||-z
  |z  }.|.|kD  r|.}|+dL   |"z
  |"z  }/|/|(k  r|/}(|/|)kD  r|/})|+d?   r}d7}!|+dL   }0|&jo                  |(       |'jo                  |)       |"dM|z   z  }1|0dM|z
  z  }2|2|1z
  |1z  }3| jo                  |3       |3d,kD  r|$dMz  }$|dM|3z   z  }||kD  r|}|%jo                  |       |+dL   |"z
  |"z  }4|dM|4z   z  }5|%jo                  |5       |%jo                  |       & ||z
  |z  dOz  }6|#d,kD  r|$|#z  dOz  ndK}7|dP   jw                         dOz  }8t3        jx                  |%      }9|9j{                         j}                         }:dK};dK}<t        |:      d,kD  r|:jw                         }=|:j                         }>t        j                  t        jv                  t        j                  d,|:      dQz              }?|>d,k7  r|=|>z  t        j                  dR      z  };|?d,k7  r|=|?z  t        j                  dR      z  }<dS}@t        |      dTz  }A|6dJz  }B|Ad,kD  r&dMBz   dUkD  r|dVkD  rdMBz   dWAz  z  dWz
  dJz  }C|C|dJz  z  }@|&rt        jv                  |&      dOz  ndK}D|'rt        jv                  |'      dOz  ndK}E|&rt        |&      dOz  ndK}F|'rt        |'      dOz  ndK}Gt        dX       t        dY       t        dZ|        t        d[|j                          d\|j                                 |jZ                  dk7  r&t        d]|jZ                   d^|j\                   d       t        d_|6d`da       t        db|dOz  d`da       t        dc|#        t        dd|7d`de|$ df|# d       t        dg|8dhda       t        diDd`djFd`dk       t        dlEd`dmGd`dk       t        dn|;d`       t        do|<d`       t        dp@d`       t        dq       |j`                  rst        dX       t        dr       t        ds|jf                   d\|j                                 t        dt       |t        d_|j                  dudK      d`da       t        dbt        |j                  dvdK            d`da       t        dct        |j                  dwd,                    t        dg|j                  dxdK      dhda       t        dn|j                  dydK      d`       t        do|j                  dzdK      d`       t        dp|j                  d{dK      d`       t        d||j                  d}dK      d`       nt        d~|        t        dq       |j                  r4|j                  |j                         t        d|j                          y y # 1 sw Y   xY w# th        $ r}|}Y d }~d }~ww xY w)NzValidate Strategy Performance)descriptionz--show-trades
store_truezShow the list of trades)actionhelpz--datazresults/TV_Export.csvzPath to the data CSV file)typedefaultr   z--strategy_filezstrategy_activation_scores.pyz@Name of the strategy Python file (must be in strategies/ folder)z--params_filez?Path to a CSV or JSON file with parameters to override defaults)r	   r   z--exportz:Path to export the signals CSV (e.g. strategies/DEBUG.csv)z--canonical-metricsTzXAlso print strategy.calculate_metrics output, matching optimizer scoring (default: true))r   r
   r   z--score-startz:Start date for canonical metrics scoring window (default: )z--regime-suppress)bullbearnoner   zSuppress entries outside the given regime. 'bull' = only enter when zscore >= threshold; 'bear' = only enter when zscore < threshold; 'none' = no suppression (default))choicesr
   r   z--regime-thresholdg      .@zMVRV zscore percentile threshold for regime classification (default: 15.0). zscore >= threshold = bull; zscore < threshold = bearzError: File not found at z"Error: Strategy file not found at strategy_modulezLoading data from z...time)utcz
2015-01-01z
2025-12-31)dropr   zLoading parameters from z.csvzLoaded parameters: z.jsonzGenerating signals...zscorez+[WARNING] --regime-suppress requested but 'z0' column not found in data; suppression skipped.r   execute_entryFz[regime-suppress=z] threshold=z  suppressed z entry signalscalculate_metrics)score_startz$ does not expose calculate_metrics()execute_exit signal_typez
ENTRY LONGz	EXIT LONGz
--- First 50 Trades ---)r   r   close)hbandfilt	stoch_rsiactivation_score2   )indexg{Gzt?g      Y@g        r      lowd   position   im  g      $g     v@g&.>gMbP?g      ?z
==============================zTrade-walk diagnosticszData File: zDate Range: z to zRegime Filter: z (zscore threshold=zTotal P&L: z.2f%zMax Equity Drawdown: zTotal Trades: zProfitable Trades: z% (/z% Time In Market: z.1fz	Avg MAE: z%  (worst: z%)z	Avg MFE: z%  (best:  zSharpe Ratio: zSortino Ratio: zCalmar Ratio: z==============================zCanonical optimizer metricszScoring Window: z<Source: strategy.calculate_metrics(signals, score_start=...)zTotal P&L %zMax Drawdown %zTotal Tradesz% In MarketzSharpe RatiozSortino RatiozCalmar RatiozP&L/DD Ratio: zP&L/DD RatiozUnavailable: zSignals exported to )LargparseArgumentParseradd_argumentstrBooleanOptionalActionr   float
parse_argsdataospathexistsprintjoindirname__file__strategy_file	importlibutilspec_from_file_locationmodule_from_specsysmodulesloaderexec_modulepdread_csvcolumnslowerstripto_datetimedttz_localize	Timestamploccopyreset_indexparams_filejsonendswithilocto_dictopenloadgenerate_signalsregime_suppressregime_thresholdsumcanonical_metricshasattrr   r   	ExceptionRuntimeErrorshow_tradesappendhead	to_stringiterrowsmeanSeries
pct_changedropnalenstdnpsqrtminimumminmaxdategetabsintexportto_csv)Hparserargscsv_pathstrategy_pathspecstrategy_signalsdf
start_dateend_datestrategy_paramsrN   	df_paramsfsignals
zscore_colthr	bear_mask
suppressed	bull_maskn_suppressedrX   canonical_errorexcdisplay_eventscols_to_showpossible_colscolCOMMISSION_RATEinitial_capitalequitypeak_equitymax_drawdown_pct
trades_pnlin_positionentry_pricetotal_tradesprofitable_tradesdaily_equity_curvetrade_mae_listtrade_mfe_listcurrent_maecurrent_mfer!   rowfloating_pnl_pctfloating_equitydrawdown	close_ret
exit_priceeffective_entryeffective_exitpnl_pctfloating_pnl_pct_closefloating_equity_closetotal_pnl_pctprofitable_pctpct_in_marketequity_seriesreturnssharpe_ratiosortino_ratiomean_return
std_returndownside_deviationcalmar_ration_yearstotal_returnannualized_return_pctavg_maeavg_mfe	worst_maebest_mfesH                                                                           strategies/validate_strategy.pymainr      s   $$1PQF
C\]
s4KRmn
)=\  df  g
c8yz

3op
-h6T6T^bw  y
c;YZeYffgh  j
+5MW]n  o ,5$U  V D yyH77>>(#)(45 GGLL!:D<N<NOM77>>-(2=/BC>>112C]SD ~~66t<%5CKK!"KK,-	xj
,-	X	B %%'++113BJ6
588DDTJBvJ l+J||L)H	Fz)bjH.DE	F	K	K	M	Y	Y_c	Y	dB OBGGNN4+;+;<()9)9(:#>?$$V,D$4$45I'nnQ/779O''89:&&w/d&&'1"&))A, (''89:	
!"///FoFG
 v%
W__,?
|K{|}''C##v-#J/#5	$_5	A
:?I67 $J/36	$_5	A
:?I67%>>+L%d&:&:%;<uMZfYgguvwO#%89&$4$F$Fw||~cgcscs$F$t! +%%&&JKO
 W_58OOPUUWN$&N=!IUN~o6EFHSN~n5}DE)*7J Cn,,,##C( ! 	n\*//3==E=JK OOF!KJKKLNNKK &&(
sKg,KALKK%%f-  !$E
[ 8KG$,<(<=O#o5DH**#+  W3{BI;&';&' >"# \
 %%k2%%k2 #._1D"E!+q?/B!C)O;N!!'*Q;%*% 1w;'K'"(K"))&1 +.g,*D)S&(.!6L2L(M%"))*?@ %%f-y )| o-@3FMAMPQAQ',6<WZNJ',,.4M II01M&&(//1GLM
7|alln[[]
WWRWWRZZ7-CQ-F%GH?'*4DL"(+==MML"gG 5(L{L(D05E5M"#l"2g!F!LPU U,0@50HI/=bggn%+3G/=bggn%+3G-;N#c)I-;N#c)H	-	
"#	Kz
"#	L*+4/@
ABv% 4 455HI^I^H__`ab	Kc*!
,-	!"2S"8!=Q
?@	N<.
)*	s337H6I<.XY
Z[	}S1
34	Igc]+i_B
?@	Igc]+hs^2
>?	N<,
-.	OM#.
/0	N<,
-.	&Mm+, !1!1 2$x}}6GHILM(K 1 5 5mS I#NaPQ)#.?.C.CDTVY.Z*[\_)``abcN3'8'<'<^Q'O#P"QRS&'8'<'<]C'PQT&UUVWXN#4#8#8#Mc"RSTO$5$9$9/3$OPS#TUVN#4#8#8#Mc"RSTN#4#8#8#Mc"RSTM/!234f{{t{{#$T[[M23 c ('F  &"%&s$   !q +q q	q&q!!q&__main__)__doc__pandasrA   r1   numpyrg   r)   importlib.utilr9   r=   r2   r]   abspathr5   r6   r7   configr   r   __name__     r   <module>r      sw     	    
 RWW__X-F MN O P4d zF r   