54 lines
2.6 KiB
Python
54 lines
2.6 KiB
Python
|
|
import kit, numpy as np, sys, datetime as dt
|
||
|
|
sys.stdout.reconfigure(encoding='utf-8',errors='replace')
|
||
|
|
from sklearn.ensemble import HistGradientBoostingClassifier
|
||
|
|
|
||
|
|
def run(sym,tf,sl,tp,H,label,min_year=None):
|
||
|
|
t,o,h,l,c,v,sp=kit.load_rates(sym,tf)
|
||
|
|
if min_year:
|
||
|
|
k=np.array([dt.datetime.fromtimestamp(x,dt.UTC).year for x in t])>=min_year
|
||
|
|
t,o,h,l,c,v,sp=[a[k] for a in (t,o,h,l,c,v,sp)]
|
||
|
|
X,names,a=kit.features(t,o,h,l,c,v)
|
||
|
|
diffs=np.abs(np.diff(np.unique(np.round(c,6)))); tick=np.median(diffs[diffs>0])
|
||
|
|
spread=np.median(sp)*tick
|
||
|
|
y,valid=kit.barrier_vec(h,l,c,a,sl,tp,H,spread)
|
||
|
|
n=len(y); idx=np.arange(n)
|
||
|
|
be=100*sl/(sl+tp)
|
||
|
|
prob=np.full((n,3),np.nan); fold=np.full(n,-1)
|
||
|
|
bounds=np.linspace(int(n*0.35),n,6).astype(int)
|
||
|
|
for f in range(5):
|
||
|
|
te0,te1=bounds[f],bounds[f+1]
|
||
|
|
te=(idx>=te0)&(idx<te1)&valid; tr=(idx<te0-H)&valid
|
||
|
|
if tr.sum()<8000 or te.sum()<1000: continue
|
||
|
|
m=HistGradientBoostingClassifier(max_iter=200,learning_rate=0.06,max_depth=6,
|
||
|
|
l2_regularization=1.0,random_state=0).fit(X[tr],y[tr])
|
||
|
|
prob[te]=m.predict_proba(X[te]); fold[te]=f
|
||
|
|
best=None
|
||
|
|
for thr in (0.40,0.45,0.50,0.55):
|
||
|
|
tr_i=[]; j=0
|
||
|
|
while j<n:
|
||
|
|
if fold[j]<0 or not np.isfinite(prob[j,0]): j+=1; continue
|
||
|
|
p=prob[j]; pr=int(np.argmax(p))
|
||
|
|
if pr==2 or float(np.max(p))<thr: j+=1; continue
|
||
|
|
tr_i.append((pr==y[j],fold[j])); j+=H
|
||
|
|
if len(tr_i)<60: continue
|
||
|
|
w=np.array([x[0] for x in tr_i]); fo=np.array([x[1] for x in tr_i])
|
||
|
|
wr=100*w.mean(); nT=len(w)
|
||
|
|
se=100*np.sqrt((be/100)*(1-be/100)/nT); sig=(wr-be)/se
|
||
|
|
pf=[100*w[fo==f].mean() for f in range(5) if (fo==f).sum()>=15]
|
||
|
|
pos=sum(1 for x in pf if x>be)
|
||
|
|
if best is None or sig>best[0]:
|
||
|
|
best=(sig,thr,nT,wr,be,pf,pos,len(pf))
|
||
|
|
if best is None: print(f" {label:<26} too few trades"); return
|
||
|
|
sig,thr,nT,wr,be,pf,pos,nf=best
|
||
|
|
exp=(wr/100)*tp-(1-wr/100)*sl
|
||
|
|
print(f" {label:<26} thr{thr:.2f} {nT:5d} trades win {wr:5.2f}% vs {be:5.2f}% "
|
||
|
|
f"edge {wr-be:+5.2f}pp ({sig:+.2f}s) exp {exp:+.3f} ATR folds+{pos}/{nf}")
|
||
|
|
|
||
|
|
print("=== PURGED WALK-FORWARD, SEQUENTIAL NON-OVERLAPPING TRADES ===")
|
||
|
|
print("(best-of-4 confidence thresholds shown; 'folds+' = test folds above break-even)\n")
|
||
|
|
for sym,tf,mn in (("EURUSD","16385",1999),("USDJPY","16385",1999),
|
||
|
|
("XAUUSD","16385",None),("SP500","16385",None)):
|
||
|
|
print(f"{sym} H1:")
|
||
|
|
for sl,tp,H in ((2,2,32),(2,3,48),(2,6,128)):
|
||
|
|
run(sym,tf,sl,tp,H,f"{sl}:{tp} h{H}",mn)
|
||
|
|
print()
|