
    %jV                       d Z ddlm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ddl	m
Z
 ddlmZ dZddd	d
ddddddddddddddddddddddddd dd!d"d#d$d%dd&Zg d'g d(g d)g d*g d+g d,d&Ze
 G d- d.                      Zdad4Zdbd:Zdcd<ZefdddDZdedFZdfdIZdgdMZdhdPZdidTZdjdkdYZdld^Zdmd_Zed`k    r e e                      dS )nzMonte Carlo strategy simulator for the personal US equity agent.

The simulator uses synthetic market regimes, not live prices. It is meant to
stress-test decision rules before they are used as portfolio policy.
    )annotationsN)	dataclass)Pathi#);On?皙?)gI+?y&1?)r   Q?)皙?Q?)
ףp=
Q?)basketqualityleadersoxlsoxs)g~jth?r	   )gy&1|?Mb?)r   y&1?)g~jt?333333?)g{Gzgp=
ף?)gMb`r   )        r   )gMb`?g9v?)g{Gztr   )g~jtxr   )gQ롿Q?)g;OngI+?)gy&1r   )gRQ(\µ?)r   r   )r	   {Gz?)r   g~jt?)r   g
ףp=
?)zG?r   )g(\µr   )g333333)\(?)g/$r   )gQr   )g=
ףp=ʿQ?)g(\?p=
ף?)risk_on	selectivechopselloffreboundcrash))r         ?)r         ?)r    Q?)r!   r   r"   r   )r#   g{Gz?))r   
ףp=
?)r   gzG?)r    )\(?)r!   皙?r'   r#   {Gz?))r   r&   )r   皙?)r    RQ?)r!   r(   r"   {Gz?)r#   r   ))r   r	   )r   r0   )r    g(\?)r!   g
ףp=
?)r"   r%   r#   g)\(?))r   333333?)r   Q?)r    r-   )r!   r&   r/   r+   ))r   r,   )r   r   )r    r   )r!   (\?)r"   ffffff?r1   c                  t    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded	<   d
ed<   d
ed<   ded<   ded<   dS )StrategyResultstrnamelist[float]final_equitymax_drawdownmax_drawdown_krwz
list[bool]hit_weekly_questhit_monthly_questz	list[int]weekly_quest_countmonthly_quest_count
hit_doubleended_below_startN)__name__
__module____qualname____annotations__     )outputs/strategy_monte_carlo_simulator.pyr7   r7   O   s         III!!!!    !!!!!!!!""""!!!!!!rI   r7   rngrandom.Randomcurrentr8   returnc                    |                                  }d}t          |         D ]\  }}||z  }||k    r|c S t          |         d         d         S Nr   r   )randomTRANSITIONS)rK   rM   roll
cumulativeregimeprobabilitys         rJ   pick_regimerX   ]   se    ::<<DJ*73  k!
:MMM w#A&&rI   regimesdictrV   assetfloatc                p    ||         |         \  }}|                      ||          }t          |d          S )Ng)gaussmax)rK   rY   rV   r[   meanstdevvalues          rJ   normal_returnrc   g   s7    &/%(KD%IIdE""EuerI   dict[str, bool]c                h   |dv o|                                  dk     }|dv o|                                  dk     }|dv o|                                  dk     }|dv o|                                  dk     }|d	k    o|                                  d
k     }|p||p|||dv o|                                  dk     dS )N>   r#   r!   gGz?>   r    r   333333?>   r"   r   r   ffffff?>   r    r!   r(   r"   q=
ףp?ףp=
?)
crash_riskr   r"   confirmed_breakdownrR   )rK   rV   rj   false_crashrisk_on_signalfalse_risk_onrebound_signals          rJ   signal_qualityrq   m   s    //GCJJLL44GJ11IcjjllT6IKBBZszz||VZGZN11IcjjllT6IMy(@SZZ\\D-@N /K!2]!%)==U#**,,QUBU	  rI   strategysignaldrawdownpending_cash_daysintequitydict[str, float]c                L   | dk    r	dddddddS | dk    r)|d	k     r	dddddd
dS |d         r	dddddddS dddddddS | dk    r3|d         r	dddddddS |d         s|d         r	dddddddS dddddddS | dk    rk|dk    rdddd|dk    rdnd|dk    rdnddS |d         rdddd|dk    rdnd|dk    rdnddS |d         r	dddddddS |d         r	ddd d!dd"dS d#d$dddd!dS | d%k    rX|dk    s|d         rdd#dd|dk    rdnd|dk    rd&nd'dS |d         r	dd#dd(dddS |d         r|d)k    r	ddd*ddddS dd+dddddS | d,k    rt          d|t          z  d-z
            }d-}|d-k    rd.}n|d/k    rd0}n|dk    rd1}|d2k     r	dddddd
dS |d	k     r)d3d4dd|d         r|dk    rdnd|d         r|dk    rd5nd6dS |dk    s|d         r'|dk    rt          dd|z            nd}dd#dd|d'|z
  dS |d         rt          d7d8|z            }	d9dd|	dd5|	z
  dS |d         rt          d/d*|z            }	dd#d|	dd!|	z
  dS dd*dddd:dS | d;k    ry|dk    s|d<         r|d=k     rdddd|dk    rd#nd|dk    rd&nddS |d         rdd+dd|dk    rdnd|dk    rd>nd?dS |d         r	dddd#dddS |d         r	ddd@ddddS d$dAddBdd(dS | dCk    rA|d<         s|d)k     rdddd|dk    rdnd|dk    rd/nd5dS |d         r	dddddddS dddddddS | dDk    ry|dk    s|d<         r|dEk     rdddd|dk    rdnd|dk    rdndFdS |d         rdddd|dk    rdnd|dk    rd/nd?dS |d         r	dd*ddddGdS |d         r	dd+dddddS d#dAdddddS t          dH|            )Iz>Return weights over basket, quality, leader, soxl, soxs, cash.passive_holdg?r-   r*   r   r
   )r   r   r   r   r   cashpanic_sell_rebuy皙g?r   皙?rf   g?r2   aggressive_leveragerk   r%   g?r"   turbo_soxl_soxs_switchr#   r   r5   gp=
ף?r)   gQ?g)\(?r0   gQ?r&   gq=
ףp?gQ?r   r(   g{Gz?selective_leverage_burstgGz?g=
ףp=?gGz?g{Gzr3   g{Gz?compounding_tactical_ladder      ?g333333?r$   g?gzG?g
ףp=
ǿr   gp=
ף?g333333?rg   ri   r.   r   gQ?guarded_aggressive_barbellrj   g{GzgQ?g(\?gHzG?r4   r	   defensive_trendadaptive_barbellgQrh   r   zunknown strategy: )r_   START_CAPITAL_KRWmin
ValueError)
rr   rV   rs   rt   ru   rw   profit_bufferturbosoxs_weightsoxl_weights
             rJ   weights_for_strategyr   {   s[	    >!!44W[eijjj%%%e"ttT[_imnnn) 	o"ttT[_imnnn44W[eijjj((('( 	o"ttT[_imnnn) 	oy 1 	o"ttT[_imnnn44W[eijjj+++W"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w'( 	w"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w) 	o"ttT[_imnnn) 	o"ttT[_imnnn44W[eijjj---W'< ="ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w) 	o"ttT[_imnnn) 	oE!1!1"ttT[_imnnn44W[eijjj000C*;!;c!ABBD  EEd""EEd""Ee"ttT[_imnnne"ttTcij  dA  \f  FW  [\  F\  F\[_[_  bf  x~  T  xU  pz  Zk  op  Zp  Zp  pt  pt  vz  {  {  {W'< =5F!5K5K#dD5L111QUK"ttT[fpt  xC  qC  D  D  D) 	DdD5L11K"tt[bfpt  xC  qC  D  D  D) 	DdD5L11K"tt[bfpt  xC  qC  D  D  D44W[eijjj///W!5(U:J:J"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w'( 	w"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w) 	o"ttT[_imnnn) 	o"ttT[_imnnn44W[eijjj$$$, 	w8e#3#3"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w) 	o"ttT[_imnnn44W[eijjj%%%W!5(U:J:J"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w'( 	w"ttTctxycycy[_[_  @D  Vg  kl  Vl  Vl  NR  NR  rv  w  w  w) 	o"ttT[_imnnn) 	o"ttT[_imnnn44W[eijjj
4(44
5
55rI   transitionsc                    |                                  }d}||         D ]\  }}||z  }||k    r|c S ||         d         d         S rP   rl   )rK   r   rM   rT   rU   rV   rW   s          rJ   pick_regime_from_transitionsr      se    ::<<DJ*73  k!
:MMM w#A&&rI   days<tuple[float, float, float, bool, bool, int, int, bool, bool]c           
        t           }|}d}d}|}	|}
d}d}d}d}d}|                    g d          }d}t          |          D ]}t          |||          }t	          ||          }||z  dz
  }|d         r*| dv r&t          ||                    g d                    }nt          d|d	z
            }t          | |||||          }d}|                                D ](\  }}|d
k    rd}nt          ||||          }|||z  z  })| dk    rt          |d          }n| dk    rt          |d          }n| dk    rt          |d          }nl| dk    rt          |d          }nU| dk    rt          |d          }n>| dk    rt          |d          }n'| dk    rt          |d          }nt          |d          }|d|z   z  }t          ||          }t          |||z  dz
            }t          |||z
            }||
dz   k    rd}||	dz   k    rd}|t           dz  k    rd}|dz  d k    r||
dz   k    r|d	z  }|}
|d!z  d"k    r||	dz   k    r|d	z  }|}	|||||||||t           k     f	S )#Nr   Fr   )r   r   r    r!   r   rj   >   r   r   r   )r         r   r{   g-C6
?r   r   r   gp=
ףr   g)\(r   gףp=
ÿr   g)\(̿r   gp=
ףr   g(\¿r}   逄 T逖 r               )
r   choiceranger   rq   r_   r   itemsrc   r   )rr   rK   r   rY   r   rw   highmax_dd
max_dd_krwmonthly_start
week_start
hit_weeklyhit_monthlyweekly_countmonthly_countrB   rV   ru   dayrs   rt   weightsdaily_returnr[   weightasset_returns                             rJ   simulate_oner      sD   FDFJMJJKLMJZZCCCDDFT{{ 9# 9#-c;GGV,,D=3&, 	>H0u$u$u #$5szz)))7L7L M M #A'81'< = =&xK\^dee$]]__ 	2 	2ME6&,S'65IIF\11LL)))|V44LL555|V44LL***|V44LL...|V44LL111|V44LL333|V44LL666|V44LL|U33L#$$4  VVd]S011Vd]33
Z)+++J]Z///K&***J7a<<i///!J8r>>333""M6:z;m]gio  sD  jD  D  DrI   valuesr:   pc                ,   | st          d          S t          |           }t          |          dz
  |z  }t          j        |          }t          j        |          }||k    r|t          |                   S ||         ||z
  z  ||         ||z
  z  z   S )Nnanr   )r\   sortedlenmathfloorceilrv   )r   r   orderedklowr   s         rJ   
percentiler   :  s     U||VnnG	W	QA
*Q--C9Q<<D
d{{s1vv3<4!8$wt}C'@@@rI   resultdict[str, float | str]c                   | j         }d |D             }d |D             }| j        }| j        }t          j        |          }t          j        |          }t          |d          }t          |d          }	t          j        |          }
t          j        |          }t          |d          }t          |d          }t          j        |          }t          |d          }t          j        |          }t          |d          }t          | j                  t          | j                  z  }t          | j
                  t          | j
                  z  }t          | j                  t          | j                  z  }t          | j                  t          | j                  z  }t          j        | j                  }t          j        | j                  }||
dz  z   |dz  z   |dz  z   |dz  z   |dz  z   |d	z  z   |d
z  z   |dz  z   |dz  z
  }d}d}|dk     rd}d}|dk    rd}d}|dk     rd}d}|s|n|dz
  }i d| j        d|
d|d|d|d|dz  d|dz  d|dz  d|	dz  d t          j        |          d!t          |d          d"t          |d          d#|dz  d$|dz  d%|d&|d'|dz  |dz  |||dz  |dz  |||rd(nd)|d*	S )+Nc                "    g | ]}|t           z
  S rH   r   .0rb   s     rJ   
<listcomp>zsummarize.<locals>.<listcomp>H  s    ???u))???rI   c                (    g | ]}|t           z  d z
  S )r   r   r   s     rJ   r   zsummarize.<locals>.<listcomp>I  s#    EEEU))C/EEErI   r
   gffffff?r-   g      ?r   r   igffffff?r~   i F i<6Tp5_drawdown_exceeds_30m_krw$below_start_probability_exceeds_5pctr   p5_net_profit_negativei ʚ;rr   mean_profit_krwmedian_profit_krwp5_profit_krwp95_profit_krwmean_return_pctd   median_return_pctp5_return_pctp95_return_pctmedian_final_krwp5_final_krwp95_final_krwmedian_max_drawdown_pctp5_max_drawdown_pctmedian_max_drawdown_krwp5_max_drawdown_krwprob_weekly_quest_hit_pctyesno)	prob_monthly_quest_hit_pctavg_weekly_quest_countavg_monthly_quest_countprob_x2_hit_pctprob_below_start_pctchallenge_net_profit_score_krwqualified_score_krwdisqualifieddisqualification_reason)r;   r<   r=   
statisticsr`   medianr   sumrB   r   rC   r>   r?   r@   rA   r9   )r   finalsprofitsreturnsddsdd_krwmean_returnmedian_return	p5_return
p95_returnmean_profitmedian_profit	p5_profit
p95_profit	median_ddp5_ddmedian_dd_krw	p5_dd_krwrB   below_startweeklymonthlyavg_weekly_countavg_monthly_countscorer   r   qualified_scores                               rJ   	summarizer   F  s    F?????GEEfEEEG

C$F/'**K%g..M7D))IGT**J/'**K%g..M7D))IGT**J!#&&IsD!!E%f--M64((IV&''#f.?*@*@@Jf.//#f6N2O2OOK())C0G,H,HHF&*++c&2J.K.KKG!v'@AA"(BCC 	

	
d
	 t
	 Y
&		'
 j
(	) z
!	" d
	 $
	 

"		# 
 L ;"?T"H1}}":#/JeeU]5JOFK; 	] 		
 	* 	;, 	]S0 	S 	*s* 	J-f55 	
6400 	FD11 	"9s? 	us{ 	"=  	y!" 	$Vc\#$ '.m"2#4%+ +c 1*/.!-74#:5   rI   path
str | Nonetuple[dict, dict, str]c                    | st           t          dfS t          j        t	          |                                                     }|d         |d         | fS )Nsynthetic_defaultrY   r   )DEFAULT_REGIMESDEFAULT_TRANSITIONSjsonloadsr   	read_text)r  payloads     rJ   load_regime_configr    sR     I 35HHHjd--//00G9w}5t;;rI   
iterationsseedregime_config@tuple[list[dict[str, float | str]], dict[str, float | str], str]c                X   g d}t          j        |          }t          |          \  }}}g }	|D ]K}
t          |
g g g g g g g g g 
  
        }t	          |           D ]
}t          |
||||          \	  }}}}}}}}}|j                            |           |j                            |           |j	                            |           |j
                            |           |j                            |           |j                            |           |j                            |           |j                            |           |j                            |           |	                    |           Md |	D             }|                    d d           ||d         |fS )N)	rz   r|   r   r   r   r   r   r   r   c                ,    g | ]}t          |          S rH   )r   )r   r   s     rJ   r   z#run_simulations.<locals>.<listcomp>  s     999v6""999rI   c                ,    t          | d                   S )Nr   )r\   )rows    rJ   <lambda>z!run_simulations.<locals>.<lambda>  s    5-B)C#D#D rI   T)keyreverser   )rR   Randomr  r7   r   r   r;   appendr<   r=   r>   r?   r@   rA   rB   rC   sort)r  r   r  r  
strategiesrK   rY   r   sourceresultsrr   r   _finalddr   r   r   r   r   doublebelow	summariess                          rJ   run_simulationsr$    s   
 
 
J -

C#5m#D#D G[&$&G  "b"b"b"b"MMz"" 
	3 
	3A]ijrtwy}  @G  IT  ^U  ^UZE2vvwmVUZ&&u---&&r***#**6222#**6222$++G444%,,\:::&--m<<<$$V,,,$++E2222v99999INNDDdNSSSilF**rI   r   rowslist[dict[str, float | str]]Nonec                2   t          |d                                                   }|                     dd          5 }t          j        ||          }|                                 |                    |           d d d            d S # 1 swxY w Y   d S )Nr   wr   )newline)
fieldnames)listkeysopencsv
DictWriterwriteheader	writerows)r  r%  fieldshandlewriters        rJ   	write_csvr6    s    $q',,..!!F	3	#	# v6:::                 s   A BBBc                    t          j                    } |                     dt          d           |                     dt          d           |                     dt          d           |                     dd 	           |                     d
d           |                                 }|j        dk     rt          d          |j        dk     rt          d          t          |j        |j        |j	        |j
                  \  }}}t          t                                                    j        }t          |dz  |           |j        |j        |j	        t           |||d}|j        r%t%          t#          j        |dd                     ns|D ]X}t%          |d          d|d         dd|d         dd|d         dd|d         dd |d!         d"k     d#|d$         d           Yt%          d%|d                     d&S )'Nz--iterationsi  )typedefaultz--days   z--seedi&5z--regime-config)r9  z--json
store_true)actionr   z!--iterations must be at least 100zN--days must be at least 252 for the adopted account-growth simulation standardz strategy_monte_carlo_results.csv)r  r   r  start_capital_krwregime_sourcebest_strategyr#  Fr   )ensure_asciiindentrr   z: median_profit=r   z,.0fz p5_profit=r   z p5_mdd=r   z x2=r   z.1fz% qualified=r   r   z score=r   zBEST=r   )argparseArgumentParseradd_argumentrv   
parse_argsr  
SystemExitr   r$  r  r  r   __file__resolveparentr6  r   r  printdumps)parserargsr#  bestr>  out_dirr  r  s           rJ   mainrP    sk   $&&F
S$???
sC888
sH===
)4888
666D<===y3ijjj%4T_diQUQZ\`\n%o%o"It]8nn$$&&-Gg::IFFF o		.& G y *djuQ???@@@@ 	 	Cz? ; ;C8K4LT ; ; 19; ;34<; ; +,4; ; !0D8	; ;
 23:; ;    	(d:&(()))1rI   __main__)rK   rL   rM   r8   rN   r8   )
rK   rL   rY   rZ   rV   r8   r[   r8   rN   r\   )rK   rL   rV   r8   rN   rd   )rr   r8   rV   r8   rs   rd   rt   r\   ru   rv   rw   r\   rN   rx   )rK   rL   r   rZ   rM   r8   rN   r8   )rr   r8   rK   rL   r   rv   rY   rZ   r   rZ   rN   r   )r   r:   r   r\   rN   r\   )r   r7   rN   r   )r  r  rN   r  )N)
r  rv   r   rv   r  rv   r  r  rN   r  )r  r   r%  r&  rN   r'  )rN   rv   )__doc__
__future__r   rB  r/  r  r   rR   r   dataclassesr   pathlibr   r   r  r  r7   rX   rc   rq   r   r   r   r   r   r  r$  r6  rP  rD   rF  rH   rI   rJ   <module>rV     s    # " " " " "  



        ! ! ! ! ! !         
 !!   !!   "!   ""!  !!   ""! I+ +^ ~~ A  A  A{{{~~~~~~|||   
" 
" 
" 
" 
" 
" 
" 
"' ' ' '      ( &e6 e6 e6 e6 e6P' ' ' 'JD JD JD JDZ	A 	A 	A 	AS S S Sl< < < < +  +  +  +  +F   + + + +\ z
*TTVV

 rI   