// ----------------------------------------------------------------------
// J) Heavy per-bar update slice (uses rolling G_UpdatePos cursor)
// ----------------------------------------------------------------------
var f_affine(var x, var lam, var mean, var E, var P, var i, var c){
return x + lam*mean + E + P + i + c; // small helper used inside nonlins
}
var nonlin1(int i, int n1, var lam, var mean, var E, var P){
var x = G_State[n1];
var arg = (var)A1x[i]*x + (var)A1lam[i]*lam + (var)A1mean[i]*mean + (var)A1E[i]*E + (var)A1P[i]*P + (var)A1i[i]*i + (var)A1c[i];
return arg;
}
var nonlin2(int i, int n2, var lam, var mean, var E, var P){
var x = G_State[n2];
var arg = (var)A2x[i]*x + (var)A2lam[i]*lam + (var)A2mean[i]*mean + (var)A2E[i]*E + (var)A2P[i]*P + (var)A2i[i]*i + (var)A2c[i];
return arg;
}
// returns 1 if a full heavy-update pass finishes, else 0
int heavyUpdateChunk(var lambda, var mean, var energy, var power, int batch){
int N = G_N;
if(N <= 0) return 0;
if(batch < UPDATE_MIN_BATCH) batch = UPDATE_MIN_BATCH;
if(G_UpdatePos >= N) G_UpdatePos = 0;
int i0 = G_UpdatePos;
int i1 = i0 + batch; if(i1 > N) i1 = N;
// projection may be reused by multiple chunks within the same bar
computeProjection();
int i;
for(i=i0;i<i1;i++){
// --- neighbors (safe) ---
int n1 = adjSafe(i,0);
int n2 = ifelse(G_D>=2, adjSafe(i,1), n1);
// --- DTREE ensemble term (also returns top meta) ---
int topEq = -1; var topW = 0;
var treeT = dtreeTerm(i, &topEq, &topW);
G_TreeTerm[i] = (fvar)treeT;
G_TopEq[i] = (i16)topEq;
G_TopW[i] = (fvar)topW;
// --- advisor (data-driven) ---
var adv = adviseEq(i, lambda, mean, energy, power);
// --- nonlinear pair terms controlled by Mode ---
var a1 = nonlin1(i,n1,lambda,mean,energy,power);
var a2 = nonlin2(i,n2,lambda,mean,energy,power);
var t1, t2;
if(G_Mode[i]==1){ t1 = tanh(a1); t2 = sin(a2);
} else if(G_Mode[i]==2){ t1 = cos(a1); t2 = tanh(a2);
} else { t1 = sin(a1); t2 = cos(a2); }
// --- global couplings & momentum ---
var glob1 = tanh( (var)G1mean[i]*mean + (var)G1E[i]*energy );
var glob2 = sin ( (var)G2P[i]*power + (var)G2lam[i]*lambda );
var mom = (G_State[i] - G_Prev[i]);
// --- next state synthesis ---
var xnext =
(var)G_WSelf[i]*G_State[i]
+ (var)G_WN1[i]*t1
+ (var)G_WN2[i]*t2
+ (var)G_WGlob1[i]*glob1
+ (var)G_WGlob2[i]*glob2
+ (var)G_WMom[i]*mom
+ (var)G_WTree[i]*treeT
+ (var)G_WAdv[i]*adv;
// --- stability clamp & book-keeping ---
xnext = clamp(xnext, -10, 10);
G_Prev[i] = G_State[i];
G_State[i]= xnext;
G_StateSq[i] = xnext*xnext;
// --- keep last advisor output for hit-rate scoring next bar ---
G_AdvPrev[i] = (fvar)adv;
// --- lightweight per-eq meta logging (sampled) ---
if(!G_LogsOff && (Bar % LOG_EVERY)==0 && (i < LOG_EQ_SAMPLE)){
int tid = safeTreeIndexFromEq(G_EqTreeId[i]);
Node* tnode = treeAt(tid);
int nodeDepth = 0;
if(tnode) nodeDepth = tnode->d;
var rate = (var)TBeta[i]; // any per-eq scalar to inspect quickly
var pred = predByTid(tid);
// last parameter must be a string (avoid ternary; lite-C friendly)
string expr = 0;
if(LOG_EXPR_TEXT){
if(G_Sym) expr = G_Sym[i];
else expr = 0;
}
appendEqMetaLine(Bar, G_Epoch, G_CtxID,
i, n1, n2, tid, nodeDepth, rate, pred, adv, G_Prop[i], (int)G_Mode[i],
(var)G_WAdv[i], (var)G_WTree[i], G_MCF_PBull, G_MCF_Entropy, (int)G_MCF_State,
expr);
}
}
// advance rolling cursor
G_UpdatePos = i1;
// full pass completed?
if(G_UpdatePos >= N){
G_UpdatePos = 0;
G_UpdatePasses += 1;
return 1;
}
return 0;
}
// ----------------------------------------------------------------------
// K) Cycle tracker: pick leader eq on ring and update phase/speed
// ----------------------------------------------------------------------
void updateEquationCycle() {
if(!G_EqTheta){ G_CycPh = wrapPi(G_CycPh); return; }
// Leader = argmax Prop[i]
int i, bestI = 0; var bestP = -1;
for(i=0;i<G_N;i++){
var p = (var)G_Prop[i];
if(p > bestP){ bestP = p; bestI = i; }
}
var th = ifelse(G_EqTheta != 0, G_EqTheta[bestI], 0);
// angular speed (wrapped diff)
var d = angDiff(G_LeadTh, th);
// EW smoothing for speed
G_CycSpd = 0.9*G_CycSpd + 0.1*d;
// integrate phase, keep wrapped
G_CycPh = wrapPi( G_CycPh + G_CycSpd );
G_LeadEq = bestI;
G_LeadTh = th;
}
// ----------------------------------------------------------------------
// L) Markov orchestration per bar (5m every bar; 1H & Relation on close)
// ----------------------------------------------------------------------
int is_H1_close(){ return (Bar % TF_H1) == 0; }
void updateAllMarkov(){
// Don’t touch Markov until all chains are allocated
if(!MC_Count || !MC_RowSum || !ML_Count || !ML_RowSum || !MR_Count || !MR_RowSum)
return;
// low TF always
updateMarkov_5M();
// on 1H close, refresh HTF & relation
if(is_H1_close()){
updateMarkov_1H();
updateMarkov_REL();
}
// expose HTF features to DTREE (the legacy MC_* are HTF via MH_*)
G_MCF_PBull = MH_PBullNext;
G_MCF_Entropy = MH_Entropy;
G_MCF_State = MH_Cur;
}
// ----------------------------------------------------------------------
// M) Rewire scheduler (chunked): decide batch and normalize periodically
// ----------------------------------------------------------------------
void maybeRewireNow(var lambda, var mean, var energy, var power){
int mb = mem_mb_est();
// Near budget? shrink batch or skip
if(mb >= UPDATE_MEM_HARD) return;
// choose batch by bar type
int batch = ifelse(is_H1_close(), REWIRE_BATCH_EQ_H1, REWIRE_BATCH_EQ_5M);
// soften by memory
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);
// Normalize proportions after completing a full pass (and every REWIRE_NORM_EVERY passes)
if(finished && (G_RewirePasses % REWIRE_NORM_EVERY) == 0){
normalizeProportions();
// write a header once and roll context id every META_EVERY full passes
writeEqHeaderOnce();
if((G_RewirePasses % META_EVERY) == 0){
// refresh context hash using adjacency (same as in rewireEpoch)
int D = G_D, i, total = G_N * D;
unsigned int h = 2166136261u;
for(i=0;i<total;i++){
unsigned int x = (unsigned int)G_Adj[i];
h ^= x + 0x9e3779b9u + (h<<6) + (h>>2);
}
G_CtxID = (int)((h ^ ((unsigned int)G_Epoch<<8)) & 0x7fffffff);
}
}
}
// ----------------------------------------------------------------------
// N) Heavy update scheduler (chunked) for each bar
// ----------------------------------------------------------------------
void runHeavyUpdates(var lambda, var mean, var energy, var power){
int mb = mem_mb_est();
// Near hard ceiling? skip heavy work this bar
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);
}
// ----------------------------------------------------------------------
// O) Hit-rate scorer (EW average of 1-bar directional correctness)
// ----------------------------------------------------------------------
void updateHitRates(){
if(is(INITRUN)) return;
if(Bar <= LookBack) return;
int i;
var r = G_Ret1; // realized 1-bar return provided by outer loop
var sgnR = sign(r);
for(i=0;i<G_N;i++){
var a = (var)G_AdvPrev[i]; // last bar's advisor score (-1..+1)
var sgnA = ifelse(a > HIT_EPS, 1, ifelse(a < -HIT_EPS, -1, 0));
var hit = ifelse(sgnR == 0, 0.5, ifelse(sgnA == sgnR, 1.0, 0.0));
G_HitEW[i] = (fvar)((1.0 - HIT_ALPHA)*(var)G_HitEW[i] + HIT_ALPHA*hit);
G_HitN[i] += 1;
}
}
// ----------------------------------------------------------------------
// P) Lambda/Gamma blend & accuracy sentinel
// ----------------------------------------------------------------------
var blendLambdaGamma(var lambda_raw, var gamma_raw){
// adapt blend weight a bit with entropy: more uncertainty -> lean on gamma
var w = clamp(G_FB_W + 0.15*(0.5 - G_MCF_Entropy), 0.4, 0.9);
var x = w*lambda_raw + (1.0 - w)*gamma_raw;
acc_update(lambda_raw, gamma_raw);
return x;
}
// ----------------------------------------------------------------------
// Q) Per-bar orchestrator (no orders here; main run() will call this)
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// Q) Per-bar orchestrator (no orders here; main run() will call this)
// Hardened for warmup & init guards (safe if called before LookBack)
// ----------------------------------------------------------------------
void alpha12_step(var ret1_now /*1-bar realized return for scoring*/)
{
// If somehow called before init completes, do nothing
if(!ALPHA12_READY) return;
// 1) Markov update & expose HTF features (always safe)
updateAllMarkov();
// --- Warmup guard ---------------------------------------------------
// Some environments (or external callers) may invoke this before LookBack.
// In warmup we only maintain projections and exit; no rewires/heavy updates.
if(Bar < LookBack){
// keep projection cache alive if arrays exist
computeProjection();
G_Ret1 = ret1_now; // harmless bookkeeping for scorer
// optionally adapt MC threshold very slowly even in warmup
{
var h = 0.5;
int i; var acc = 0;
for(i=0;i<G_N;i++) acc += (var)G_HitEW[i];
if(G_N > 0) h = acc/(var)G_N;
var target = MC_ACT
+ 0.15*(0.55 - h)
+ 0.10*(G_MCF_Entropy - 0.5);
target = clamp(target, 0.20, 0.50);
G_MC_ACT = 0.95*G_MC_ACT + 0.05*target;
}
return; // <-- nothing heavy before LookBack
}
// --------------------------------------------------------------------
// 2) Compute lambda from current projection snapshot
var lambda = 0.0;
{
computeProjection();
int K = keffClamped(); // clamped effective projection dimension
int k;
var e = 0;
var pwr = 0;
for(k = 0; k < K; k++){
var z = (var)G_Z[k];
e += z;
pwr += z*z;
}
var mean = 0;
var energy = pwr; // total energy = sum of squares
var power = 0;
if(K > 0){
mean = e / (var)K;
power = pwr / (var)K;
}
// local "lambda" = trend proxy mixing price-like aggregates
lambda = 0.7*tanh(mean) + 0.3*tanh(0.05*power);
// 3) Maybe rewire a slice this bar (uses same features)
maybeRewireNow(lambda, mean, energy, power);
// 4) Heavy updates for a slice
runHeavyUpdates(lambda, mean, energy, power);
}
// 5) Gamma from coarse network projection (stable, uses whole state)
var gamma = projectNet();
// 6) Blend & store accuracy sentinel
var x = blendLambdaGamma(lambda, gamma);
// 7) Update ring / equation-cycle tracker
updateEquationCycle();
// 8) Score previous advisors against realized 1-bar return
G_Ret1 = ret1_now;
updateHitRates();
// 9) Depth manager & elastic growth controller (memory-aware)
depth_manager_runtime();
edc_runtime();
// 10) Adapt MC acceptance threshold by hit-rate/entropy
{
var h = 0.0;
int i;
for(i = 0; i < G_N; i++) h += (var)G_HitEW[i];
if(G_N > 0) h /= (var)G_N; else h = 0.5;
var target = MC_ACT
+ 0.15*(0.55 - h)
+ 0.10*(G_MCF_Entropy - 0.5);
target = clamp(target, 0.20, 0.50);
G_MC_ACT = 0.9*G_MC_ACT + 0.1*target;
}
// silence unused warning if trading block is removed
x = x;
}
// ==================== Part 4/4 — Runtime, Trading, Init/Cleanup ====================
// ---- globals used by Part 4
var G_LastSig = 0; // blended lambda/gamma used for trading view
int G_LastBarTraded = -1;
// ---- small guards for optional plotting
void plotSafe(string name, var v){
if(ENABLE_PLOTS && !G_ChartsOff) plot(name, v, NEW|LINE, 0);
}
// ---- lite-C compatible calloc replacement ----
void* xcalloc(int count, int size) // removed 'static' (lite-C)
{
int bytes = count*size;
void* p = malloc(bytes);
if(p) memset(p,0,bytes);
else quit("Alpha12: OOM in xcalloc");
return p;
}
// ======================= Markov alloc/free =======================
void allocMarkov()
{
int NN = MC_STATES*MC_STATES;
int bytesMat = NN*sizeof(int);
int bytesRow = MC_STATES*sizeof(int);
// --- HTF (1H) chain (legacy MC_*) ---
MC_Count = (int*)malloc(bytesMat);
MC_RowSum= (int*)malloc(bytesRow);
if(!MC_Count || !MC_RowSum) quit("Alpha12: OOM in allocMarkov(MC)");
memset(MC_Count, 0, bytesMat);
memset(MC_RowSum, 0, bytesRow);
// --- LTF (5M) chain ---
ML_Count = (int*)malloc(bytesMat);
ML_RowSum= (int*)malloc(bytesRow);
if(!ML_Count || !ML_RowSum) quit("Alpha12: OOM in allocMarkov(ML)");
memset(ML_Count, 0, bytesMat);
memset(ML_RowSum, 0, bytesRow);
// --- Relation chain (links 5M & 1H) ---
MR_Count = (int*)malloc(bytesMat);
MR_RowSum= (int*)malloc(MR_STATES*sizeof(int)); // MR_STATES == MC_STATES
if(!MR_Count || !MR_RowSum) quit("Alpha12: OOM in allocMarkov(MR)");
memset(MR_Count, 0, bytesMat);
memset(MR_RowSum, 0, MR_STATES*sizeof(int));
// --- initial states & defaults ---
MC_Prev = MH_Prev = -1; MC_Cur = MH_Cur = 0;
ML_Prev = -1; ML_Cur = 0;
MR_Prev = -1; MR_Cur = 0;
MC_PBullNext = 0.5; MC_Entropy = 1.0;
ML_PBullNext = 0.5; ML_Entropy = 1.0;
MR_PBullNext = 0.5; MR_Entropy = 1.0;
}
void freeMarkov(){
if(MC_Count) free(MC_Count);
if(MC_RowSum)free(MC_RowSum);
if(ML_Count) free(ML_Count);
if(ML_RowSum)free(ML_RowSum);
if(MR_Count) free(MR_Count);
if(MR_RowSum)free(MR_RowSum);
MC_Count=MC_RowSum=ML_Count=ML_RowSum=MR_Count=MR_RowSum=0;
}
// ======================= Alpha12 init / cleanup =======================
void Alpha12_init()
{
if(ALPHA12_READY) return;
// 1) Session context first
asset(ASSET_SYMBOL);
BarPeriod = BAR_PERIOD;
set(PLOTNOW); // plotting gated by ENABLE_PLOTS at call sites
// 2) Warmup window
LookBack = max(300, NWIN);
// 3) Clamp effective projection size and reset projection cache
if(G_Keff < 1) G_Keff = 1;
if(G_Keff > G_K) G_Keff = G_K;
G_ProjBar = -1;
G_ProjK = -1;
// 4) Core allocations
allocateNet();
allocMarkov();
// 5) Depth LUT + initial tree + indexing
if(!G_DepthW) G_DepthW = (var*)malloc(DEPTH_LUT_SIZE*sizeof(var));
if(!Root) Root = createNode(MAX_DEPTH);
G_RT_TreeMaxDepth = MAX_DEPTH;
refreshDepthW();
reindexTreeAndMap(); // sizes pred cache & ring angles
// 6) Bootstrap: RP, projection, one full rewire pass (also sets proportions & CtxID)
rewireInit();
computeProjection();
rewireEpoch(0,0,0,0);
// 7) Logging header once
writeEqHeaderOnce();
// 8) Reset rolling cursors / exposed Markov defaults
G_RewirePos = 0; G_RewirePasses = 0;
G_UpdatePos = 0; G_UpdatePasses = 0;
G_MCF_PBull = 0.5; G_MCF_Entropy = 1.0; G_MCF_State = 0;
// 9) Done
ALPHA12_READY = 1;
printf("\n[Alpha12] init done: N=%i D=%i K=%i (Keff=%i) Depth=%i est=%i MB",
G_N, G_D, G_K, G_Keff, G_RT_TreeMaxDepth, mem_mb_est());
}
void Alpha12_cleanup(){
freeMarkov();
if(Root){ freeTree(Root); Root=0; }
freeNodePool();
if(G_DepthW){ free(G_DepthW); G_DepthW=0; }
freeNet();
ALPHA12_READY = 0;
}
// ======================= Helpers for realized 1-bar return =======================
var realizedRet1(){
// Basic 1-bar return proxy from close series
vars C = series(priceClose());
if(Bar <= LookBack) return 0;
return C[0] - C[1];
}
// ======================= Trading gate =======================
// Combines blended network signal with Markov PBull gate.
// Returns signed signal in [-1..1].
var tradeSignal(){
// --- EARLY GUARDS ---
if(!ALPHA12_READY) return 0; // init not completed
if(!G_RP || !G_Z || !G_StateSq) return 0; // projection buffers not allocated
// Recompute a lightweight lambda/gamma snapshot for display/decisions.
// (Alpha12_step already ran heavy ops; this is cheap.)
computeProjection();
int Keff = keffClamped(); // clamped effective projection size
if(Keff <= 0) return 0; // nothing to project yet; be safe
int k;
var e = 0;
var pwr = 0;
for(k = 0; k < Keff; k++){
var z = (var)G_Z[k];
e += z;
pwr += z*z;
}
// --- NO TERNARY: explicit guards for lite-C ---
var mean = 0;
var 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);
G_LastSig = x;
// Markov (HTF) directional gating (no ternaries)
var gLong = 0;
var gShort = 0;
if(G_MCF_PBull >= PBULL_LONG_TH) gLong = 1.0;
if(G_MCF_PBull <= PBULL_SHORT_TH) gShort = 1.0;
// Symmetric gate around x (no ternary)
var s = 0;
if(x > 0) s = x * gLong;
else s = x * gShort;
// Modulate by relation chain confidence (lower entropy -> stronger)
var conf = 1.0 - 0.5*(MR_Entropy); // 0.5..1.0 typically
s *= conf;
return clamp(s, -1, 1);
}
// ======================= Position sizing & risk =======================
var posSizeFromSignal(var s){
// Simple linear sizing, capped
var base = 1;
var scale = 2.0 * abs(s); // 0..2
return base * (0.5 + 0.5*scale); // 0.5..1.5 lots (example)
}
void placeOrders(var s){
// Basic long/short logic with soft handoff
if(s > 0){
if(!NumOpenLong) enterLong(posSizeFromSignal(s));
if(NumOpenShort) exitShort();
} else if(s < 0){
if(!NumOpenShort) enterShort(posSizeFromSignal(s));
if(NumOpenLong) exitLong();
}
// if s==0 do nothing (hold)
}
// ======================= Main per-bar runtime =======================
void Alpha12_bar(){
// 1) Provide last realized return to the engine scorer
var r1 = realizedRet1();
// 2) Run the engine step (updates Markov, rewires slices, heavy updates, etc.)
alpha12_step(r1);
// 3) Build trading signal & place orders (once per bar)
var s = tradeSignal();
placeOrders(s);
// 4) Plots (guarded)
plotSafe("PBull(1H)", 100*(G_MCF_PBull-0.5));
plotSafe("PBull(5M)", 100*(ML_PBullNext-0.5));
plotSafe("PBull(Rel)", 100*(MR_PBullNext-0.5));
plotSafe("Entropy(1H)", 100*(G_MCF_Entropy));
plotSafe("Sig", 100*G_LastSig);
}
// ---- Zorro hooks (after macros!) ----
function init(){ Alpha12_init(); }
function run()
{
// keep it lean; do NOT change BarPeriod/asset here anymore
if(Bar < LookBack){
updateAllMarkov();
return;
}
Alpha12_bar();
}
function cleanup(){ Alpha12_cleanup(); }