// ======================================================================
// Markov-augmented Harmonic D-Tree Engine (Candlestick 122-directional)
// ======================================================================
// ================= USER CONFIG =================
#define ASSET_SYMBOL "EUR/USD" // symbol to trade
#define ALGO_NAME "Alpha10b" // algo tag (keeps models/files separated)
// Markov gating thresholds
#define MC_ACT 0.30 // min |CDL| ([-1..1]) to mark a pattern active
#define PBULL_LONG_TH 0.60 // Markov gate for long entries
#define PBULL_SHORT_TH 0.40 // Markov gate for short entries
// ================= ENGINE PARAMETERS =================
#define MAX_BRANCHES 3
#define MAX_DEPTH 4
#define NWIN 256
#define NET_EQNS 100
#define DEGREE 4
#define KPROJ 16
#define REWIRE_EVERY 127
#define LOG_EVERY 1
// DTREE-driven rewiring candidates per neighbor slot
#define CAND_NEIGH 8
// ---- DTREE feature sizes (extended with Markov features) ----
#define ADV_EQ_NF 12
#define ADV_PAIR_NF 12
// ================= Candles ? 122-state Markov =================
#define MC_NPAT 61
#define MC_STATES (1 + 2*MC_NPAT) // 0=NONE, 1..122 directional
#define MC_NONE 0
#define MC_LAPLACE 1.0
// ---------- helpers ----------
var clamp01(var x){ if(x<0) return 0; if(x>1) return 1; return x; }
int isInvalid(var x)
{
if(x != x) return 1; // NaN
if(x > 1e100 || x < -1e100) return 1; // ±INF or astronomic values
return 0;
}
var safeSig(var x){
if(x != x) return 0; // NaN -> 0
if(x > 999.) return 999.;
if(x < -999.) return -999.;
return x;
}
// ========== Heuristic 61-candle feature builder ==========
int buildCDL_TA61(var* out, string* names)
{
int i; for(i=0;i<MC_NPAT;i++){ out[i]=0; if(names) names[i]="UNUSED"; }
var O = priceOpen();
var H = priceHigh();
var L = priceLow();
var C = priceClose();
var rng = H - L; if(rng <= 0) rng = 1e-8;
var body = C - O;
var dir = ifelse(body >= 0, 1.0, -1.0);
var bodyFrac = clamp(body/rng, -1, 1); // [-1..1]
var upperFrac = clamp01( (H - max(O,C)) / rng ); // [0..1]
var lowerFrac = clamp01( (min(O,C) - L) / rng ); // [0..1]
var absBody = abs(body)/rng; // [0..1]
// 0: body direction & size
out[0] = bodyFrac; if(names) names[0] = "BODY";
// 1..2: upper/lower dominance (signed)
out[1] = clamp( upperFrac - lowerFrac, -1, 1 ); if(names) names[1] = "UPPER_DOM";
out[2] = clamp( lowerFrac - upperFrac, -1, 1 ); if(names) names[2] = "LOWER_DOM";
// 3: doji-ish (very small body), signed by direction
var dojiT = 0, thresh = 0.10;
if(absBody < thresh) dojiT = 1.0 - absBody/thresh; // 0..1
out[3] = dir * dojiT; if(names) names[3] = "DOJI";
// 4: marubozu-ish (both shadows tiny), signed by direction
var shadowSum = upperFrac + lowerFrac;
var maru = 0; if(shadowSum < 0.10) maru = 1.0 - shadowSum/0.10;
out[4] = dir * clamp01(maru); if(names) names[4] = "MARUBOZU";
// 5: hammer-ish (long lower, tiny upper)
var hamm = 0; if(lowerFrac > 0.60 && upperFrac < 0.10) hamm = (lowerFrac - 0.60)/0.40;
out[5] = dir * clamp01(hamm); if(names) names[5] = "HAMMER";
// 6: shooting-star-ish (long upper, tiny lower), bearish by shape
var star = 0; if(upperFrac > 0.60 && lowerFrac < 0.10) star = (upperFrac - 0.60)/0.40;
out[6] = -clamp01(star); if(names) names[6] = "SHOOTING";
// 7: long body strength (signed)
var longB = 0; if(absBody > 0.70) longB = (absBody - 0.70)/0.30;
out[7] = dir * clamp01(longB); if(names) names[7] = "LONG_BODY";
// 8: small body (spinning top-ish)
out[8] = dir * (1.0 - absBody); if(names) names[8] = "SPIN_TOP";
// 9: momentum-ish scalar from body size (signed)
out[9] = dir * (2.0*absBody - 1.0); if(names) names[9] = "BODY_MOM";
// 10..60 left as zero/UNUSED
return 61;
}
// ===== Markov storage =====
#define MC_IDX(s,t) ((s)*MC_STATES + (t))
static int* MC_Count; // size MC_STATES*MC_STATES
static int* MC_RowSum; // size MC_STATES
static int MC_Prev = -1;
static int MC_Cur = 0;
static var MC_PBullNext = 0.5;
static var MC_Entropy = 0.0;
static string MC_Names[MC_NPAT];
void MC_alloc()
{
int i;
MC_Count = (int*)malloc(MC_STATES*MC_STATES*sizeof(int));
MC_RowSum = (int*)malloc(MC_STATES*sizeof(int));
for(i=0;i<MC_STATES*MC_STATES;i++) MC_Count[i]=0;
for(i=0;i<MC_STATES;i++) MC_RowSum[i]=0;
MC_Prev = -1; MC_Cur = 0; MC_PBullNext = 0.5; MC_Entropy = 0.;
}
void MC_free(){ if(MC_Count){free(MC_Count);MC_Count=0;} if(MC_RowSum){free(MC_RowSum);MC_RowSum=0;} }
int MC_stateFromCDL(var* cdl /*len=61*/, var thr)
{
int i, best=-1; var besta=0;
for(i=0;i<MC_NPAT;i++){ var a=abs(cdl[i]); if(a>besta){ besta=a; best=i; } }
if(best<0) return MC_NONE;
if(besta < thr) return MC_NONE;
int bull = (cdl[best] > 0);
return 1 + 2*best + bull;
}
int MC_indexFromState(int s){ if(s<=0) return -1; return (s-1)/2; }
int MC_isBull(int s){ if(s<=0) return 0; return ((s-1)%2)==1; }
void MC_update(int sPrev,int sCur)
{
if(sPrev<0) return;
MC_Count[MC_IDX(sPrev,sCur)] += 1;
MC_RowSum[sPrev] += 1;
}
var MC_prob(int s,int t)
{
var num = (var)MC_Count[MC_IDX(s,t)] + MC_LAPLACE;
var den = (var)MC_RowSum[s] + MC_LAPLACE*MC_STATES;
if(den<=0) return 1.0/MC_STATES;
return num/den;
}
var MC_nextBullishProb(int s)
{
if(s<0) return 0.5;
int t; var pBull=0, pTot=0;
for(t=1;t<MC_STATES;t++){ var p=MC_prob(s,t); pTot += p; if(MC_isBull(t)) pBull += p; }
if(pTot<=0) return 0.5;
return pBull/pTot;
}
var MC_rowEntropy01(int s)
{
if(s<0) return 1.0;
int t; var H=0, Z=0;
for(t=1;t<MC_STATES;t++){ var p=MC_prob(s,t); Z+=p; }
if(Z<=0) return 1.0;
for(t=1;t<MC_STATES;t++){
var p=MC_prob(s,t)/Z;
if(p>0) H += -p*log(p);
}
var Hmax = log(MC_STATES-1);
if(Hmax<=0) return 0;
return H/Hmax;
}
// ================= HARMONIC D-TREE (engine) =================
typedef struct Node { var v; var r; void* c; int n; int d; } Node;
Node* Root;
Node** G_TreeIdx; int G_TreeN; int G_TreeCap; var G_DTreeExp;
// ------- helpers (built-ins used) -------
int randint(int lo,int hi){ return lo + (int)random(hi - lo + 1); } // [lo..hi]
var randu(var a,var b){ return a + random(b - a); } // [a..b)
var randsign(){ return ifelse(random(1) < 0.5, -1.0, 1.0); }
var mapUnit(var u,var lo,var hi){ u = clamp(u,-1.,1.); var t=0.5*(u+1.0); return lo + t*(hi-lo); }
void pushTreeNode(Node* u){ if(G_TreeN < G_TreeCap) G_TreeIdx[G_TreeN++] = u; }
void indexTreeDFS(Node* u){ if(!u) return; pushTreeNode(u); int i; for(i=0;i<u->n;i++) indexTreeDFS(((Node**)u->c)[i]); }
Node* createNode(int depth)
{
Node* u = (Node*)malloc(sizeof(Node));
u->v = 2*random(1)-1; // [-1..1)
u->r = 0.01 + 0.02*depth + random(1)*0.005; // small positive
u->d = depth;
if(depth > 0){
u->n = randint(1, MAX_BRANCHES);
u->c = malloc(u->n * sizeof(void*));
int i; for(i=0;i<u->n;i++) ((Node**)u->c)[i] = createNode(depth - 1);
} else { u->n = 0; u->c = 0; }
return u;
}
var evaluateNode(Node* u)
{
if(!u) return 0;
var sum=0; int i; for(i=0;i<u->n;i++) sum += evaluateNode(((Node**)u->c)[i]);
var phase = sin(u->r * Bar + sum);
var weight = 1.0 / pow(u->d + 1, G_DTreeExp);
u->v = (1 - weight)*u->v + weight*phase;
return u->v;
}
int countNodes(Node* u){ if(!u) return 0; int c=1,i; for(i=0;i<u->n;i++) c += countNodes(((Node**)u->c)[i]); return c; }
void freeTree(Node* u){ if(!u) return; int i; for(i=0;i<u->n;i++) freeTree(((Node**)u->c)[i]); if(u->c) free(u->c); free(u); }
// =========== NETWORK STATE & COEFFICIENTS ===========
int G_N = NET_EQNS;
int G_D = DEGREE;
int G_K = KPROJ;
var* G_State; var* G_Prev; var* G_Vel;
int* G_Adj; var* G_RP; var* G_Z;
int* G_Mode;
var* G_WSelf; var* G_WN1; var* G_WN2; var* G_WGlob1; var* G_WGlob2; var* G_WMom; var* G_WTree; var* G_WAdv;
var* A1x; var* A1lam; var* A1mean; var* A1E; var* A1P; var* A1i; var* A1c;
var* A2x; var* A2lam; var* A2mean; var* A2E; var* A2P; var* A2i; var* A2c;
var* G1mean; var* G1E; var* G2P; var* G2lam;
var* G_TreeTerm; int* G_TopEq; var* G_TopW; int* G_EqTreeId; var* TAlpha; var* TBeta;
var* G_Pred; var* G_AdvScore;
var* G_PropRaw; var* G_Prop;
string* G_Sym;
// Markov features exposed to DTREE
var G_MCF_PBull, G_MCF_Entropy, G_MCF_State;
// epoch/context & feedback
int G_Epoch = 0;
int G_CtxID = 0;
var G_FB_A = 0.7;
var G_FB_B = 0.3;
// ---------- predictability from D-tree ----------
var nodePredictability(Node* t)
{
if(!t) return 0.5;
var disp=0; int n=t->n, i;
for(i=0;i<n;i++){ Node* c=((Node**)t->c)[i]; disp += abs(c->v - t->v); }
if(n>0) disp /= n;
var depthFac = 1.0/(1+t->d);
var rateBase = 0.01 + 0.02*t->d;
var rateFac = exp(-25.0*abs(t->r - rateBase));
var p = 0.5*(depthFac + rateFac);
p = 0.5*p + 0.5*(1.0/(1.0 + disp));
return clamp(p,0,1);
}
// filenames
void buildEqFileName(int idx, char* outName /*>=64*/) { strcpy(outName, strf("Log\\%s_eq_%03i.csv", ALGO_NAME, idx)); }
// --------- allocation ----------
void allocateNet()
{
int N=G_N, D=G_D, K=G_K;
G_State=(var*)malloc(N*sizeof(var)); G_Prev=(var*)malloc(N*sizeof(var)); G_Vel=(var*)malloc(N*sizeof(var));
G_Adj=(int*)malloc(N*D*sizeof(int));
G_RP=(var*)malloc(K*N*sizeof(var)); G_Z=(var*)malloc(K*sizeof(var));
G_Mode=(int*)malloc(N*sizeof(int));
G_WSelf=(var*)malloc(N*sizeof(var)); G_WN1=(var*)malloc(N*sizeof(var)); G_WN2=(var*)malloc(N*sizeof(var));
G_WGlob1=(var*)malloc(N*sizeof(var)); G_WGlob2=(var*)malloc(N*sizeof(var));
G_WMom=(var*)malloc(N*sizeof(var)); G_WTree=(var*)malloc(N*sizeof(var)); G_WAdv=(var*)malloc(N*sizeof(var));
A1x=(var*)malloc(N*sizeof(var)); A1lam=(var*)malloc(N*sizeof(var)); A1mean=(var*)malloc(N*sizeof(var));
A1E=(var*)malloc(N*sizeof(var)); A1P=(var*)malloc(N*sizeof(var)); A1i=(var*)malloc(N*sizeof(var)); A1c=(var*)malloc(N*sizeof(var));
A2x=(var*)malloc(N*sizeof(var)); A2lam=(var*)malloc(N*sizeof(var)); A2mean=(var*)malloc(N*sizeof(var));
A2E=(var*)malloc(N*sizeof(var)); A2P=(var*)malloc(N*sizeof(var)); A2i=(var*)malloc(N*sizeof(var)); A2c=(var*)malloc(N*sizeof(var));
G1mean=(var*)malloc(N*sizeof(var)); G1E=(var*)malloc(N*sizeof(var));
G2P=(var*)malloc(N*sizeof(var)); G2lam=(var*)malloc(N*sizeof(var));
G_TreeTerm=(var*)malloc(N*sizeof(var)); G_TopEq=(int*)malloc(N*sizeof(int)); G_TopW=(var*)malloc(N*sizeof(var));
TAlpha=(var*)malloc(N*sizeof(var)); TBeta=(var*)malloc(N*sizeof(var));
G_Pred=(var*)malloc(N*sizeof(var)); G_AdvScore=(var*)malloc(N*sizeof(var));
G_PropRaw=(var*)malloc(N*sizeof(var)); G_Prop=(var*)malloc(N*sizeof(var));
G_Sym=(string*)malloc(N*sizeof(string));
G_TreeCap=512; G_TreeIdx=(Node**)malloc(G_TreeCap*sizeof(Node*)); G_TreeN=0;
G_EqTreeId=(int*)malloc(N*sizeof(int));
int i;
for(i=0;i<N;i++){
G_State[i]=2*random(1)-1; G_Prev[i]=G_State[i]; G_Vel[i]=0;
G_Mode[i]=0;
G_WSelf[i]=0.5; G_WN1[i]=0.2; G_WN2[i]=0.2; G_WGlob1[i]=0.1; G_WGlob2[i]=0.1; G_WMom[i]=0.05; G_WTree[i]=0.15; G_WAdv[i]=0.15;
A1x[i]=1; A1lam[i]=0.1; A1mean[i]=0; A1E[i]=0; A1P[i]=0; A1i[i]=0; A1c[i]=0;
A2x[i]=1; A2lam[i]=0.1; A2mean[i]=0; A2E[i]=0; A2P[i]=0; A2i[i]=0; A2c[i]=0;
G1mean[i]=1.0; G1E[i]=0.001; G2P[i]=0.6; G2lam[i]=0.3;
TAlpha[i]=0.8; TBeta[i]=25.0;
G_TreeTerm[i]=0; G_TopEq[i]=-1; G_TopW[i]=0;
G_Pred[i]=0.5; G_AdvScore[i]=0;
G_PropRaw[i]=1; G_Prop[i]=1.0/G_N;
G_Sym[i]=(char*)malloc(1024); strcpy(G_Sym[i],"");
}
}
void freeNet()
{
int i;
if(G_State)free(G_State); if(G_Prev)free(G_Prev); if(G_Vel)free(G_Vel);
if(G_Adj)free(G_Adj); if(G_RP)free(G_RP); if(G_Z)free(G_Z);
if(G_Mode)free(G_Mode); if(G_WSelf)free(G_WSelf); if(G_WN1)free(G_WN1); if(G_WN2)free(G_WN2);
if(G_WGlob1)free(G_WGlob1); if(G_WGlob2)free(G_WGlob2); if(G_WMom)free(G_WMom);
if(G_WTree)free(G_WTree); if(G_WAdv)free(G_WAdv);
if(A1x)free(A1x); if(A1lam)free(A1lam); if(A1mean)free(A1mean); if(A1E)free(A1E); if(A1P)free(A1P); if(A1i)free(A1i); if(A1c)free(A1c);
if(A2x)free(A2x); if(A2lam)free(A2lam); if(A2mean)free(A2mean); if(A2E)free(A2E); if(A2P)free(A2P); if(A2i)free(A2i); if(A2c)free(A2c);
if(G1mean)free(G1mean); if(G1E)free(G1E); if(G2P)free(G2P); if(G2lam)free(G2lam);
if(G_TreeTerm)free(G_TreeTerm); if(G_TopEq)free(G_TopEq); if(G_TopW)free(G_TopW);
if(TAlpha)free(TAlpha); if(TBeta)free(TBeta);
if(G_Pred)free(G_Pred); if(G_AdvScore)free(G_AdvScore);
if(G_PropRaw)free(G_PropRaw); if(G_Prop)free(G_Prop);
if(G_Sym){ for(i=0;i<G_N;i++) if(G_Sym[i]) free(G_Sym[i]); free(G_Sym); }
if(G_TreeIdx)free(G_TreeIdx); if(G_EqTreeId)free(G_EqTreeId);
}
// --------- random projection ----------
void randomizeRP(){ int K=G_K,N=G_N,k,j; for(k=0;k<K;k++) for(j=0;j<N;j++) G_RP[k*N+j]=ifelse(random(1)<0.5,-1.0,1.0); }
void computeProjection(){ int K=G_K,N=G_N,k,j; for(k=0;k<K;k++){ var acc=0; for(j=0;j<N;j++) acc+=G_RP[k*N+j]*(G_State[j]*G_State[j]); G_Z[k]=acc; }}
// --------- build features for DTREE (EXTENDED with Markov) ----------
void buildEqFeatures(int i, var lambda, var mean, var energy, var power, var* S /*ADV_EQ_NF*/)
{
Node* t=G_TreeIdx[G_EqTreeId[i]];
S[0]=safeSig(G_State[i]); S[1]=safeSig(mean); S[2]=safeSig(power); S[3]=safeSig(energy);
S[4]=safeSig(lambda); S[5]=safeSig(G_Pred[i]); S[6]=safeSig(t->d); S[7]=safeSig(t->r);
S[8]=safeSig(G_TreeTerm[i]); S[9]=safeSig(G_Mode[i]);
S[10]=safeSig(G_MCF_PBull); S[11]=safeSig(G_MCF_Entropy);
}
void buildPairFeatures(int i,int j, var lambda, var mean, var energy, var power, var* P /*ADV_PAIR_NF*/)
{
Node* ti=G_TreeIdx[G_EqTreeId[i]];
Node* tj=G_TreeIdx[G_EqTreeId[j]];
P[0]=safeSig(G_State[i]); P[1]=safeSig(G_State[j]);
P[2]=safeSig(ti->d); P[3]=safeSig(tj->d);
P[4]=safeSig(ti->r); P[5]=safeSig(tj->r);
P[6]=safeSig(abs(P[2]-P[3])); P[7]=safeSig(abs(P[4]-P[5]));
P[8]=safeSig(G_Pred[i]*G_Pred[j]);
P[9]=safeSig(lambda); P[10]=safeSig(mean); P[11]=safeSig(power);
}
// --------- DTREE advice wrappers ----------
var adviseEq(int i, var lambda, var mean, var energy, var power)
{
var S[ADV_EQ_NF]; buildEqFeatures(i,lambda,mean,energy,power,S);
var a = adviseLong(DTREE+RETURNS, 0, S, ADV_EQ_NF); // RETURNS => use next trade return as target in Train
return a/100.;
}
var advisePair(int i,int j, var lambda, var mean, var energy, var power)
{
var P[ADV_PAIR_NF]; buildPairFeatures(i,j,lambda,mean,energy,power,P);
var a = adviseLong(DTREE+RETURNS, 0, P, ADV_PAIR_NF);
return a/100.;
}
// --------- DTREE-driven adjacency selection ----------
void rewireAdjacency_DTREE(var lambda, var mean, var energy, var power)
{
int N=G_N, D=G_D, i, d, c, best, cand;
for(i=0;i<N;i++){
for(d=0; d<D; d++){
var bestScore = -2; best = -1;
for(c=0;c<CAND_NEIGH;c++){
cand = randint(0,N-1);
if(cand==i) continue;
int clash=0, k; for(k=0;k<d;k++) if(G_Adj[i*D+k]==cand){clash=1; break;}
if(clash) continue;
var s = advisePair(i,cand,lambda,mean,energy,power);
if(s > bestScore){ bestScore=s; best=cand; }
}
if(best<0){ do{ best = randint(0,N-1);} while(best==i); }
G_Adj[i*D + d] = best;
}
}
}
// --------- DTREE-created coefficients, modes & proportions ----------
void synthesizeEquationFromDTREE(int i, var lambda, var mean, var energy, var power)
{
var a_mode = adviseEq(i,lambda,mean,energy,power);
G_Mode[i] = (int)(abs(a_mode*1000)) & 3;
var a_wself = adviseEq(i,lambda,mean,energy,power);
var a_wn1 = adviseEq(i,lambda,mean,energy,power);
var a_wn2 = adviseEq(i,lambda,mean,energy,power);
var a_g1 = adviseEq(i,lambda,mean,energy,power);
var a_g2 = adviseEq(i,lambda,mean,energy,power);
var a_mom = adviseEq(i,lambda,mean,energy,power);
var a_tree = adviseEq(i,lambda,mean,energy,power);
var a_adv = adviseEq(i,lambda,mean,energy,power);
G_WSelf[i] = mapUnit(a_wself, 0.15, 0.85);
G_WN1[i] = mapUnit(a_wn1, 0.05, 0.35);
G_WN2[i] = mapUnit(a_wn2, 0.05, 0.35);
G_WGlob1[i] = mapUnit(a_g1, 0.05, 0.30);
G_WGlob2[i] = mapUnit(a_g2, 0.05, 0.30);
G_WMom[i] = mapUnit(a_mom, 0.02, 0.15);
G_WTree[i] = mapUnit(a_tree, 0.05, 0.35);
G_WAdv[i] = mapUnit(a_adv, 0.05, 0.35);
var a1=adviseEq(i,lambda,mean,energy,power);
var a2=adviseEq(i,lambda,mean,energy,power);
var a3=adviseEq(i,lambda,mean,energy,power);
var a4=adviseEq(i,lambda,mean,energy,power);
var a5=adviseEq(i,lambda,mean,energy,power);
var a6=adviseEq(i,lambda,mean,energy,power);
var a7=adviseEq(i,lambda,mean,energy,power);
A1x[i] = randsign()*mapUnit(a1, 0.6, 1.2);
A1lam[i] = randsign()*mapUnit(a2, 0.05,0.35);
A1mean[i]= mapUnit(a3,-0.30,0.30);
A1E[i] = mapUnit(a4,-0.0015,0.0015);
A1P[i] = mapUnit(a5,-0.30,0.30);
A1i[i] = mapUnit(a6,-0.02,0.02);
A1c[i] = mapUnit(a7,-0.20,0.20);
var b1=adviseEq(i,lambda,mean,energy,power);
var b2=adviseEq(i,lambda,mean,energy,power);
var b3=adviseEq(i,lambda,mean,energy,power);
var b4=adviseEq(i,lambda,mean,energy,power);
var b5=adviseEq(i,lambda,mean,energy,power);
var b6=adviseEq(i,lambda,mean,energy,power);
var b7=adviseEq(i,lambda,mean,energy,power);
A2x[i] = randsign()*mapUnit(b1, 0.6, 1.2);
A2lam[i] = randsign()*mapUnit(b2, 0.05,0.35);
A2mean[i]= mapUnit(b3,-0.30,0.30);
A2E[i] = mapUnit(b4,-0.0015,0.0015);
A2P[i] = mapUnit(b5,-0.30,0.30);
A2i[i] = mapUnit(b6,-0.02,0.02);
A2c[i] = mapUnit(b7,-0.20,0.20);
var c1=adviseEq(i,lambda,mean,energy,power);
var c2=adviseEq(i,lambda,mean,energy,power);
var d1=adviseEq(i,lambda,mean,energy,power);
var d2=adviseEq(i,lambda,mean,energy,power);
G1mean[i] = mapUnit(c1, 0.4, 1.6);
G1E[i] = mapUnit(c2,-0.004,0.004);
G2P[i] = mapUnit(d1, 0.1, 1.2);
G2lam[i] = mapUnit(d2, 0.05,0.7);
var e1=adviseEq(i,lambda,mean,energy,power);
var e2=adviseEq(i,lambda,mean,energy,power);
TAlpha[i] = mapUnit(e1, 0.3, 1.5);
TBeta[i] = mapUnit(e2, 6.0, 50.0);
var p = adviseEq(i,lambda,mean,energy,power);
G_PropRaw[i] = 0.01 + 0.99 * (0.5*(p+1.0));
}
void normalizeProportions()
{
int N=G_N,i; var s=0; for(i=0;i<N;i++) s += G_PropRaw[i];
if(s<=0) { for(i=0;i<N;i++) G_Prop[i] = 1.0/N; return; }
for(i=0;i<N;i++) G_Prop[i] = G_PropRaw[i]/s;
}
// --------- DTree proportional coupling ----------
var dtreeTerm(int i, int* outTopEq, var* outTopW)
{
int N=G_N,j;
int tid_i=G_EqTreeId[i]; Node* ti=G_TreeIdx[tid_i]; int di=ti->d; var ri=ti->r;
var alpha=TAlpha[i], beta=TBeta[i];
var sumw=0, acc=0, bestW=-1; int bestJ=-1;
for(j=0;j<N;j++){
if(j==i) continue;
int tid_j=G_EqTreeId[j]; Node* tj=G_TreeIdx[tid_j]; int dj=tj->d; var rj=tj->r;
var w = exp(-alpha*abs(di-dj)) * exp(-beta*abs(ri-rj));
var predBoost = 0.5 + 0.5*(G_Pred[i]*G_Pred[j]);
var propBoost = 0.5 + 0.5*( (G_Prop[i] + G_Prop[j]) );
w *= predBoost * propBoost;
var pairAdv = advisePair(i,j,0,0,0,0);
w *= (0.75 + 0.25*(0.5*(pairAdv+1.0)));
sumw += w; acc += w*G_State[j];
if(w>bestW){bestW=w; bestJ=j;}
}
if(outTopEq) *outTopEq = bestJ;
if(outTopW) *outTopW = ifelse(sumw>0, bestW/sumw, 0);
if(sumw>0) return acc/sumw; return 0;
}
// --------- symbolic expression builder ----------
void buildSymbolicExpr(int i, int n1, int n2)
{
string s = G_Sym[i]; strcpy(s,"");
string a1 = strf("(%.3f*x[%i] + %.3f*lam + %.3f*mean + %.5f*E + %.3f*P + %.3f*i + %.3f)",
A1x[i], n1, A1lam[i], A1mean[i], A1E[i], A1P[i], A1i[i], A1c[i]);
string a2 = strf("(%.3f*x[%i] + %.3f*lam + %.3f*mean + %.5f*E + %.3f*P + %.3f*i + %.3f)",
A2x[i], n2, A2lam[i], A2mean[i], A2E[i], A2P[i], A2i[i], A2c[i]);
strcat(s, "x[i]_next = ");
strcat(s, strf("%.3f*x[i] + ", G_WSelf[i]));
if(G_Mode[i]==0){ strcat(s, strf("%.3f*sin%s + ", G_WN1[i], a1)); strcat(s, strf("%.3f*cos%s + ", G_WN2[i], a2)); }
else if(G_Mode[i]==1){ strcat(s, strf("%.3f*tanh%s + ", G_WN1[i], a1)); strcat(s, strf("%.3f*sin%s + ", G_WN2[i], a2)); }
else if(G_Mode[i]==2){ strcat(s, strf("%.3f*cos%s + ", G_WN1[i], a1)); strcat(s, strf("%.3f*tanh%s + ", G_WN2[i], a2)); }
else { strcat(s, strf("%.3f*sin%s + ", G_WN1[i], a1)); strcat(s, strf("%.3f*cos%s + ", G_WN2[i], a2)); }
strcat(s, strf("%.3f*tanh(%.3f*mean + %.5f*E) + ", G_WGlob1[i], G1mean[i], G1E[i]));
strcat(s, strf("%.3f*sin(%.3f*P + %.3f*lam) + ", G_WGlob2[i], G2P[i], G2lam[i]));
strcat(s, strf("%.3f*(x[i]-x_prev[i]) + ", G_WMom[i]));
strcat(s, strf("Prop[i]=%.4f; ", G_Prop[i]));
strcat(s, strf("%.3f*DT(i) + ", G_WTree[i]));
strcat(s, strf("%.3f*DTREE(i)", G_WAdv[i] ));
}
// --------- one-time rewire init ----------
void rewireInit()
{
randomizeRP(); computeProjection();
G_TreeN=0; indexTreeDFS(Root);
int i; for(i=0;i<G_N;i++) G_EqTreeId[i] = i % G_TreeN;
}
// --------- epoch rewire ----------
void rewireEpoch(var lambda, var mean, var energy, var power)
{
int i;
for(i=0;i<G_N;i++){ Node* t=G_TreeIdx[G_EqTreeId[i]]; G_Pred[i]=nodePredictability(t); }
rewireAdjacency_DTREE(lambda,mean,energy,power);
for(i=0;i<G_N;i++) synthesizeEquationFromDTREE(i,lambda,mean,energy,power);
normalizeProportions();
int D=G_D; int h=0; for(i=0;i<G_N*D;i++) h = (h*1315423911) ^ G_Adj[i];
G_CtxID = (h ^ (G_Epoch<<8)) & 0x7FFFFFFF;
for(i=0;i<G_N;i++){ int n1=G_Adj[i*G_D+0], n2=G_Adj[i*G_D+1]; buildSymbolicExpr(i,n1,n2); }
}
// --------- compact driver ----------
var projectNet()
{
int N=G_N,i; var sum=0,sumsq=0,cross=0;
for(i=0;i<N;i++){ sum+=G_State[i]; sumsq+=G_State[i]*G_State[i]; if(i+1<N) cross+=G_State[i]*G_State[i+1]; }
var mean=sum/N, corr=cross/(N-1);
return 0.6*tanh(mean + 0.001*sumsq) + 0.4*sin(corr);
}
// --------- per-bar update ----------
void updateNet(var driver, var* outMean, var* outEnergy, var* outPower, int writeMeta)
{
int N=G_N, D=G_D, i;
var sum=0,sumsq=0; for(i=0;i<N;i++){ sum+=G_State[i]; sumsq+=G_State[i]*G_State[i]; }
var mean=sum/N, energy=sumsq, power=sumsq/N;
for(i=0;i<N;i++){ Node* t=G_TreeIdx[G_EqTreeId[i]]; G_Pred[i]=nodePredictability(t); }
for(i=0;i<N;i++){
int n1=G_Adj[i*D+0], n2=G_Adj[i*D+1];
var xi=G_State[i], xn1=G_State[n1], xn2=G_State[n2], mom=xi-G_Prev[i];
int topEq=-1; var topW=0;
var dt = dtreeTerm(i,&topEq,&topW);
G_TreeTerm[i]=dt; G_TopEq[i]=topEq; G_TopW[i]=topW;
var adv = adviseEq(i, driver, mean, energy, power);
G_AdvScore[i] = adv;
var arg1=A1x[i]*xn1 + A1lam[i]*driver + A1mean[i]*mean + A1E[i]*energy + A1P[i]*power + A1i[i]*i + A1c[i];
var arg2=A2x[i]*xn2 + A2lam[i]*driver + A2mean[i]*mean + A2E[i]*energy + A2P[i]*power + A2i[i]*i + A2c[i];
var nl1,nl2;
if(G_Mode[i]==0){ nl1=sin(arg1); nl2=cos(arg2); }
else if(G_Mode[i]==1){ nl1=tanh(arg1); nl2=sin(arg2); }
else if(G_Mode[i]==2){ nl1=cos(arg1); nl2=tanh(arg2); }
else { nl1=sin(arg1); nl2=cos(arg2); }
var glob1=tanh(G1mean[i]*mean + G1E[i]*energy);
var glob2=sin (G2P[i]*power + G2lam[i]*driver);
var xNew =
G_WSelf[i]*xi +
G_WN1[i]*nl1 +
G_WN2[i]*nl2 +
G_WGlob1[i]*glob1 +
G_WGlob2[i]*glob2 +
G_WMom[i]*mom +
G_WTree[i]*dt +
G_WAdv[i] *adv;
// prevent runaway values
if(xNew != xNew) xNew = 0; // NaN -> 0
else {
if(xNew > 1e6) xNew = 1e6;
if(xNew < -1e6) xNew = -1e6;
}
G_Prev[i]=xi; G_Vel[i]=xNew-xi; G_State[i]=xNew;
if(writeMeta){
char fname[64]; buildEqFileName(i,fname);
int tid=G_EqTreeId[i]; Node* t=G_TreeIdx[tid];
int nn1=G_Adj[i*D+0], nn2=G_Adj[i*D+1];
file_append(fname,
strf("META,%i,%i,%i,%i,%i,%i,%i,%i,%.6f,Pred=%.4f,Adv=%.4f,Prop=%.6f,Mode=%i,WAdv=%.3f,WTree=%.3f,PBull=%.4f,Ent=%.4f,State=%i,\"%s\"\n",
G_Epoch, G_CtxID, NET_EQNS, i, nn1, nn2, tid, t->d, t->r,
G_Pred[i], G_AdvScore[i], G_Prop[i], G_Mode[i], G_WAdv[i], G_WTree[i],
G_MCF_PBull, G_MCF_Entropy, MC_Cur, G_Sym[i]));
}
}
if(outMean) *outMean=mean; if(outEnergy) *outEnergy=energy; if(outPower) *outPower=power;
}
// ----------------- MAIN -----------------
function run()
{
// ===== required for ML training / auto-test =====
NumWFOCycles = 5; // WFO is recommended for ML
set(RULES|TESTNOW|PLOTNOW); // generate rules; auto-test after Train
if(Train){ // RETURNS target = next trade's P/L
Hedge = 2; // allow simultaneous L/S during training
LifeTime= 1; // 1-bar horizon for return labeling
} else {
MaxLong = MaxShort = 1; // clean behavior in Test/Trade
}
// ===== init once =====
static int initialized=0;
static var lambda;
static int fileInit=0;
if(LookBack < NWIN) LookBack = NWIN;
asset(ASSET_SYMBOL);
algo(ALGO_NAME);
if(is(INITRUN) && !initialized){
seed(365); // <<< ensure deterministic Train/Test advise order
var tmp[MC_NPAT]; buildCDL_TA61(tmp, MC_Names);
Root=createNode(MAX_DEPTH);
allocateNet();
MC_alloc();
G_DTreeExp = randu(1.10,1.60);
G_FB_A = randu(0.60,0.85);
G_FB_B = 1.0 - G_FB_A;
randomizeRP(); computeProjection();
rewireInit();
// First epoch synthesis
G_Epoch = 0;
rewireEpoch(0,0,0,0);
// Prepare per-equation CSVs
char fname[64]; int i;
for(i=0;i<NET_EQNS;i++){
buildEqFileName(i,fname);
file_append(fname,
"Bar,lambda,gamma,i,State,n1,n2,mean,energy,power,Vel,Mode,WAdv,WSelf,WN1,WN2,WGlob1,WGlob2,WMom,WTree,Pred,Adv,Prop,TreeTerm,TopEq,TopW,TreeId,Depth,Rate,PBull,Entropy,MCState\n");
}
if(!fileInit){
file_append(strf("Log\\%s_markov.csv",ALGO_NAME),"Bar,State,PBullNext,Entropy,RowSum\n");
fileInit=1;
}
// Initial META
for(i=0;i<G_N;i++){
int n1=G_Adj[i*G_D+0], n2=G_Adj[i*G_D+1]; int tid=G_EqTreeId[i]; Node* t=G_TreeIdx[tid];
char fname2[64]; buildEqFileName(i,fname2);
file_append(fname2,
strf("META,%i,%i,%i,%i,%i,%i,%i,%i,%.6f,Pred=%.4f,Adv=%.4f,Prop=%.6f,Mode=%i,WAdv=%.3f,WTree=%.3f,PBull=%.4f,Ent=%.4f,State=%i,\"%s\"\n",
G_Epoch, G_CtxID, NET_EQNS, i, n1, n2, tid, t->d, t->r,
G_Pred[i], G_AdvScore[i], G_Prop[i], G_Mode[i], G_WAdv[i], G_WTree[i],
G_MCF_PBull, G_MCF_Entropy, MC_Cur, G_Sym[i]));
}
initialized=1;
printf("\nRoot nodes: %i | Net equations: %i (deg=%i, kproj=%i)", countNodes(Root), G_N, G_D, G_K);
}
// ====== Per bar: Candles ? Markov
static var CDL[MC_NPAT];
buildCDL_TA61(CDL,0);
MC_Cur = MC_stateFromCDL(CDL, MC_ACT);
if(Bar > LookBack) MC_update(MC_Prev, MC_Cur);
MC_Prev = MC_Cur;
MC_PBullNext = MC_nextBullishProb(MC_Cur);
MC_Entropy = MC_rowEntropy01(MC_Cur);
// expose global Markov features
G_MCF_PBull = MC_PBullNext;
G_MCF_Entropy = MC_Entropy;
G_MCF_State = (var)MC_Cur;
// ====== Tree driver lambda
lambda = evaluateNode(Root);
// Rewire epoch?
int doRewire = ((Bar % REWIRE_EVERY) == 0);
if(doRewire){
G_Epoch++;
int i; var sum=0; for(i=0;i<G_N;i++) sum += G_State[i];
var mean = sum/G_N;
var energy=0; for(i=0;i<G_N;i++) energy += G_State[i]*G_State[i];
var power = energy/G_N;
rewireEpoch(lambda,mean,energy,power);
}
// Update net this bar (write META only if rewired)
var meanB, energyB, powerB;
updateNet(lambda, &meanB, &energyB, &powerB, doRewire);
// Feedback blend
var gamma = projectNet();
lambda = G_FB_A*lambda + G_FB_B*gamma;
// --- safe plotting (after LookBack only) ---
if(!is(LOOKBACK))
{
var lam = safeSig(lambda);
var gam = safeSig(gamma);
var pw = safeSig(powerB);
var pb = clamp01(MC_PBullNext);
var ent = clamp01(MC_Entropy);
plot("lambda", lam, LINE, 0);
plot("gamma", gam, LINE, 0);
plot("P_win", pw, LINE, 0);
plot("PBullNext", pb, LINE, 0);
plot("MC_Entropy", ent, LINE, 0);
}
// Markov CSV log
if(Bar % LOG_EVERY == 0){
file_append(strf("Log\\%s_markov.csv",ALGO_NAME),
strf("%i,%i,%.6f,%.6f,%i\n", Bar, MC_Cur, MC_PBullNext, MC_Entropy, MC_RowSum[MC_Cur]));
}
// ====== Entries ======
if(Train){
// Ensure samples for RETURNS training (hedged & 1-bar life set above)
if(NumOpenLong == 0) enterLong();
if(NumOpenShort == 0) enterShort();
} else {
// Markov-gated live logic
if( MC_PBullNext > PBULL_LONG_TH && lambda > 0.7 ) enterLong();
if( MC_PBullNext < PBULL_SHORT_TH && lambda < -0.7 ) enterShort();
}
}
// Clean up memory
function cleanup()
{
if(Root) freeTree(Root);
MC_free();
freeNet();
}