int heavyUpdateChunk(var lambda, var mean, var energy, var power, int batch){
if(net.N <= 0) return 0;
if(batch < UPDATE_MIN_BATCH) batch = UPDATE_MIN_BATCH;
if(UpdatePos >= net.N) UpdatePos = 0;
int i0 = UpdatePos;
int i1 = i0 + batch; if(i1 > net.N) i1 = net.N;
net.computeProjection();
int i;
for(i=i0;i<i1;i++){
int n1 = net.adjSafe(i,0);
int n2 = ifelse(net.D>=2, net.adjSafe(i,1), n1);
int topEq=-1; var topW=0;
var treeT = dtreeTerm(i, &topEq, &topW);
net.TreeTerm[i] = (fvar)treeT;
net.TopEq[i] = (i16)topEq;
net.TopW[i] = (fvar)topW;
var adv = adviseEq(i, lambda, mean, energy, power);
var a1 = nonlin1(i,n1,lambda,mean,energy,power);
var a2 = nonlin2(i,n2,lambda,mean,energy,power);
var t1,t2;
if(net.Mode[i]==1){ t1=tanh(a1); t2=sin(a2); }
else if(net.Mode[i]==2){ t1=cos(a1); t2=tanh(a2); }
else { t1=sin(a1); t2=cos(a2); }
var glob1 = tanh((var)net.G1mean[i]*mean + (var)net.G1E[i]*energy);
var glob2 = sin ((var)net.G2P[i]*power + (var)net.G2lam[i]*lambda);
var mom = (net.State[i] - net.Prev[i]);
var xnext =
(var)net.WSelf[i]*net.State[i]
+ (var)net.WN1[i]*t1
+ (var)net.WN2[i]*t2
+ (var)net.WGlob1[i]*glob1
+ (var)net.WGlob2[i]*glob2
+ (var)net.WMom[i]*mom
+ (var)net.WTree[i]*treeT
+ (var)net.WAdv[i]*adv;
xnext = clamp(xnext, -10., 10.);
net.Prev[i] = net.State[i];
net.State[i] = xnext;
net.StateSq[i] = xnext*xnext;
net.AdvPrev[i] = (fvar)adv;
// meta logging (sampled)
if(!rt.LogsOff && (Bar % LOG_EVERY)==0 && (i < LOG_EQ_SAMPLE)){
int tid = dt.safeTreeIndexFromEq((int)net.EqTreeId[i], dt.TreeN);
Node* tnode = dt.treeAt(tid);
int nodeDepth = (tnode ? tnode->d : 0);
var rate = (var)net.TBeta[i];
var pred = dt.predByTid(tid);
string expr = 0;
if(LOG_EXPR_TEXT && net.Sym) expr = net.Sym[i];
log.appendEqMetaLine(Bar, Epoch, CtxID,
i, n1, n2, tid, nodeDepth, rate, pred, adv, net.Prop[i], (int)net.Mode[i],
(var)net.WAdv[i], (var)net.WTree[i], MH.PBullNext, MH.Entropy, (int)MH.Cur,
expr);
}
}
UpdatePos = i1;
if(UpdatePos >= net.N){
UpdatePos = 0;
UpdatePasses++;
return 1;
}
return 0;
}
// ------------------- hit-rate scorer (unchanged) ----------------------
void updateHitRates(){
if(is(INITRUN)) return;
if(Bar <= LookBack) return;
var r = net.Ret1;
var sgnR = sign(r);
int i;
for(i=0;i<net.N;i++){
var a = (var)net.AdvPrev[i];
var sgnA = ifelse(a > 0.0001, 1, ifelse(a < -0.0001, -1, 0));
var hit = ifelse(sgnR == 0, 0.5, ifelse(sgnA == sgnR, 1.0, 0.0));
net.HitEW[i] = (fvar)((1.0 - 0.02)*(var)net.HitEW[i] + 0.02*hit);
net.HitN[i] += 1;
}
}
// ------------------- blend lambda/gamma & accuracy --------------------
var blendLambdaGamma(var lambda_raw, var gamma_raw){
var w = clamp(FB_W + 0.15*(0.5 - MH.Entropy), 0.4, 0.9);
var x = w*lambda_raw + (1.0 - w)*gamma_raw;
rt.acc_update(lambda_raw, gamma_raw);
return x;
}
// ------------------- rewire scheduler (unchanged logic) ----------------
void maybeRewireNow(var lambda, var mean, var energy, var power){
int mb = mem_mb_est();
if(mb >= UPDATE_MEM_HARD) return;
int batch = ifelse(is_H1_close(), REWIRE_BATCH_EQ_H1, REWIRE_BATCH_EQ_5M);
if(mb >= REWIRE_MEM_SOFT) batch = (batch>>1);
if(batch < REWIRE_MIN_BATCH) batch = REWIRE_MIN_BATCH;
int finished = rewireEpochChunk(lambda,mean,energy,power,batch);
if(finished && (RewirePasses % REWIRE_NORM_EVERY) == 0){
net.normalizeProportions();
log.writeEqHeaderOnce();
if((RewirePasses % META_EVERY) == 0){
int D = net.D, i, total = net.N*D;
unsigned int h = 2166136261u;
for(i=0;i<total;i++){
unsigned int x = (unsigned int)net.Adj[i];
h ^= x + 0x9e3779b9u + (h<<6) + (h>>2);
}
CtxID = (int)((h ^ ((unsigned int)Epoch<<8)) & 0x7fffffff);
}
}
}
// ------------------- heavy update scheduler (unchanged) ---------------
void runHeavyUpdates(var lambda, var mean, var energy, var power){
int mb = mem_mb_est();
if(mb >= UPDATE_MEM_HARD) return;
int batch = ifelse(is_H1_close(), UPDATE_BATCH_EQ_H1, UPDATE_BATCH_EQ_5M);
if(mb >= UPDATE_MEM_SOFT) batch = (batch>>1);
if(batch < UPDATE_MIN_BATCH) batch = UPDATE_MIN_BATCH;
heavyUpdateChunk(lambda,mean,energy,power,batch);
}
// ------------------- main engine step (unchanged) ---------------------
void alpha12_step(var ret1_now){
if(!ready) return;
updateAllMarkov();
if(Bar < LookBack){
net.computeProjection();
net.Ret1 = ret1_now;
// adapt MC threshold slowly
var h=0; int i;
for(i=0;i<net.N;i++) h += (var)net.HitEW[i];
if(net.N > 0) h /= (var)net.N; else h=0.5;
var target = MC_ACT + 0.15*(0.55 - h) + 0.10*(MH.Entropy - 0.5);
target = clamp(target, 0.20, 0.50);
MC_ACT_dyn = 0.95*MC_ACT_dyn + 0.05*target;
return;
}
// lambda from projection
net.computeProjection();
int Keff = net.keffClamped();
int k;
var e=0, pwr=0;
for(k=0;k<Keff;k++){ var z=(var)net.Z[k]; e+=z; pwr+=z*z; }
var mean=0, power=0;
if(Keff > 0){ mean = e/(var)Keff; power = pwr/(var)Keff; }
var energy = pwr;
var lambda = 0.7*tanh(mean) + 0.3*tanh(0.05*power);
maybeRewireNow(lambda,mean,energy,power);
runHeavyUpdates(lambda,mean,energy,power);
var gamma = projectNet();
var x = blendLambdaGamma(lambda,gamma);
(void)x;
// cycle tracker
dt.updateEquationCycle(net.Prop, net.N);
// score previous advisors
net.Ret1 = ret1_now;
updateHitRates();
// depth manager (pruning) – note: reindex after prune if depth reduced
int beforeDepth = rt.RT_TreeMaxDepth;
rt.depth_manager_runtime(dt);
if(rt.RT_TreeMaxDepth != beforeDepth){
reindexTreeAndMap();
}
// adapt MC acceptance threshold
{
var h=0; int i;
for(i=0;i<net.N;i++) h += (var)net.HitEW[i];
if(net.N > 0) h /= (var)net.N; else h=0.5;
var target = MC_ACT + 0.15*(0.55 - h) + 0.10*(MH.Entropy - 0.5);
target = clamp(target, 0.20, 0.50);
MC_ACT_dyn = 0.9*MC_ACT_dyn + 0.1*target;
}
}
// ------------------- realized 1-bar return (unchanged) ----------------
var realizedRet1(){
vars C = series(priceClose(0));
if(Bar <= LookBack) return 0;
return C[0] - C[1];
}
// ------------------- trading signal (unchanged) -----------------------
var tradeSignal(){
if(!ready) return 0;
if(!net.RP || !net.Z || !net.StateSq) return 0;
net.computeProjection();
int Keff = net.keffClamped();
if(Keff <= 0) return 0;
int k;
var e=0, pwr=0;
for(k=0;k<Keff;k++){ var z=(var)net.Z[k]; e+=z; pwr+=z*z; }
var mean=0, power=0;
if(Keff > 0){ mean = e/(var)Keff; power = pwr/(var)Keff; }
var lambda = 0.7*tanh(mean) + 0.3*tanh(0.05*power);
var gamma = projectNet();
var x = blendLambdaGamma(lambda,gamma);
LastSig = x;
var gLong=0, gShort=0;
if(MH.PBullNext >= PBULL_LONG_TH) gLong = 1.0;
if(MH.PBullNext <= PBULL_SHORT_TH) gShort= 1.0;
var s=0;
if(x > 0) s = x*gLong;
else s = x*gShort;
var conf = 1.0 - 0.5*(MR.Entropy);
s *= conf;
return clamp(s,-1.,1.);
}
// ------------------- position sizing & orders (unchanged) -------------
var posSizeFromSignal(var s){
var base = 1;
var scale = 2.0*abs(s);
return base * (0.5 + 0.5*scale);
}
void placeOrders(var s){
if(s > 0){
if(NumOpenShort) exitShort();
if(!NumOpenLong){
Lots = posSizeFromSignal(s);
enterLong();
}
} else if(s < 0){
if(NumOpenLong) exitLong();
if(!NumOpenShort){
Lots = posSizeFromSignal(s);
enterShort();
}
}
}
// ------------------- plotting guard -------------------
void plotSafe(string name, var v){
if(ENABLE_PLOTS && !rt.ChartsOff) plot(name, v, NEW|LINE, 0);
}
// ------------------- per-bar wrapper -------------------
void onBar(){
var r1 = realizedRet1();
alpha12_step(r1);
var s = tradeSignal();
placeOrders(s);
plotSafe("PBull(1H)", 100*(MH.PBullNext-0.5));
plotSafe("PBull(5M)", 100*(ML.PBullNext-0.5));
plotSafe("PBull(Rel)", 100*(MR.PBullNext-0.5));
plotSafe("Entropy(1H)", 100*(MH.Entropy));
plotSafe("Sig", 100*LastSig);
}
};
// ======================================================================
// ========================= Zorro DLL entry (bridge) ====================
DLLFUNC void run()
{
if(is(INITRUN)) {
if(!gAlpha12) gAlpha12 = new Alpha12Strategy();
gAlpha12->init();
}
if(!gAlpha12 || !gAlpha12->ready)
return;
// warmup behavior: keep Markov updated and projection alive
if(is(LOOKBACK) || Bar < LookBack) {
gAlpha12->updateAllMarkov();
gAlpha12->net.computeProjection();
return;
}
gAlpha12->onBar();
if(is(EXITRUN)) {
gAlpha12->cleanup();
delete gAlpha12;
gAlpha12 = nullptr;
}
}