LearningSnapshot buildSnapshot() {
LearningSnapshot s;
s.meanScore = 0;
s.meanCompactness = 0;
s.meanVol = 0;
for(int i=0;i<N_ASSETS;i++) {
s.meanScore += (double)scores[i];
s.meanCompactness += (double)compactness[i];
s.meanVol += (double)featSoA.get(2, i, 0);
}
s.meanScore /= (double)N_ASSETS;
s.meanCompactness /= (double)N_ASSETS;
s.meanVol /= (double)N_ASSETS;
double sumAbs = 0;
double sumSq = 0;
int nCorr = 0;
for(int i=0;i<N_ASSETS;i++) {
for(int j=i+1;j<N_ASSETS;j++) {
double c = fabs((double)corrMatrix[i*N_ASSETS + j]);
sumAbs += c;
sumSq += c * c;
nCorr++;
}
}
if(nCorr > 0) {
s.meanAbsCorr = sumAbs / (double)nCorr;
double m2 = sumSq / (double)nCorr - s.meanAbsCorr * s.meanAbsCorr;
if(m2 < 0) m2 = 0;
s.stdAbsCorr = sqrt(m2);
} else {
s.meanAbsCorr = 0;
s.stdAbsCorr = 0;
}
s.momentumMean = 0;
for(int i=0;i<N_ASSETS;i++) s.momentumMean += (double)featSoA.get(1, i, 0);
s.momentumMean /= (double)N_ASSETS;
s.regime = 0;
s.regimeConfidence = 0;
return s;
}
void onBar() {
barCount++;
for(int i=0;i<N_ASSETS;i++) computeFeatures(i);
if(barCount % UPDATE_EVERY == 0) {
updateCount++;
computeCorrelationMatrix();
computeDistanceMatrix();
#if USE_COMMUNITY
hclust.update(distMatrix.data);
#endif
#if USE_COMMUNITY
comm.update(corrMatrix.data, distMatrix.data);
#endif
floydWarshall();
computeScores();
LearningSnapshot snap = buildSnapshot();
controller.onUpdate(snap, scores.data, N_ASSETS, updateCount);
#if USE_DENSITY
double dz[DENSITY_DIM];
densityState.build(snap, updateCount, openCL.ready, controller.scoreScale, controller.dynamicTopK, dz);
densityModel.observe(dz, updateCount, &densityLabel, &densityConf, &densityNoise);
densityRegimeCtrl.apply(densityNoise, densityLabel, densityConf, STRATEGY_PROFILE, &controller.dynamicTopK, &controller.scoreScale, &controller.riskScale);
for(int i=0;i<N_ASSETS;i++) {
double s = (double)scores[i] * densityRegimeCtrl.appliedRiskScale;
if(s > 1.0) s = 1.0;
if(s < 0.0) s = 0.0;
scores[i] = (fvar)s;
}
#endif
#if USE_AE
double aeState[AE_INPUT_DIM];
double ms=0, mc=0, mv=0;
for(int i=0;i<N_ASSETS;i++){ ms += (double)scores[i]; mc += (double)compactness[i]; mv += (double)featSoA.get(2, i, 0); }
ms /= (double)N_ASSETS; mc /= (double)N_ASSETS; mv /= (double)N_ASSETS;
aeState[0] = ms;
aeState[1] = mc;
aeState[2] = mv;
aeState[3] = controller.scoreScale;
aeState[4] = (double)controller.dynamicTopK;
aeState[5] = (double)barCount / (double)(LookBack + 1);
aeState[6] = (double)updateCount / 1000.0;
aeState[7] = (double)openCL.ready;
double reconErr = ae.infer(aeState);
novelty.update(reconErr);
novelty.apply(&controller.dynamicTopK, &controller.scoreScale);
for(int i=0;i<N_ASSETS;i++){{
double s = (double)scores[i] * novelty.riskScale;
if(s > 1.0) s = 1.0;
if(s < 0.0) s = 0.0;
scores[i] = (fvar)s;
}}
#endif
printTopK();
}
}
void printTopK() {
int indices[N_ASSETS];
for(int i=0;i<N_ASSETS;i++) indices[i] = i;
int topN = controller.dynamicTopK;
#if USE_COMMUNITY
if(comm.qSmooth < (fvar)COMM_Q_LOW && topN > 2) topN--;
if(comm.qSmooth > (fvar)COMM_Q_HIGH && topN < TOP_K) topN++;
#endif
for(int i=0;i<topN;i++){
for(int j=i+1;j<N_ASSETS;j++){
if(scores[indices[j]] > scores[indices[i]]) {
int tmp = indices[i];
indices[i] = indices[j];
indices[j] = tmp;
}
}
}
if(updateCount % 10 == 0) {
printf("===CompactDominant_v14 Top-K(update#%d,OpenCL=%d)===\n",
updateCount, openCL.ready);
#if USE_COMMUNITY
printf(" communities=%d Q=%.4f\n", comm.nCommunities, (double)comm.qSmooth);
#endif
#if USE_DENSITY
printf(" density(label=%d,noise=%d,conf=%.3f,pause=%d)\n", densityLabel, densityNoise, densityConf, densityRegimeCtrl.paused);
#endif
int selected[N_ASSETS];
int selCount = 0;
#if USE_COMMUNITY
int coarseUsed[HCLUST_COARSE_K];
int fineTake[HCLUST_FINE_K];
int fineCap = (topN + HCLUST_FINE_K - 1) / HCLUST_FINE_K;
for(int c=0;c<HCLUST_COARSE_K;c++) coarseUsed[c] = 0;
for(int c=0;c<HCLUST_FINE_K;c++) fineTake[c] = 0;
for(int i=0;i<topN;i++){
int idx = indices[i];
int cid = comm.clusterCoarse[idx];
if(cid < 0 || cid >= HCLUST_COARSE_K) cid = 0;
if(coarseUsed[cid]) continue;
coarseUsed[cid] = 1;
selected[selCount++] = idx;
int fid = comm.clusterFine[idx];
if(fid < 0 || fid >= HCLUST_FINE_K) fid = 0;
fineTake[fid]++;
}
for(int i=0;i<topN && selCount<topN;i++){
int idx = indices[i];
int dup = 0;
for(int k=0;k<selCount;k++) if(selected[k]==idx){ dup=1; break; }
if(dup) continue;
int fid = comm.clusterFine[idx];
if(fid < 0 || fid >= HCLUST_FINE_K) fid = 0;
if(fineTake[fid] >= fineCap) continue;
selected[selCount++] = idx;
fineTake[fid]++;
}
#else
for(int i=0;i<topN;i++) selected[selCount++] = indices[i];
#endif
for(int i=0;i<selCount;i++){
int idx = selected[i];
printf(" %d.%s: score=%.4f, C=%.4f\n", i+1, ASSET_NAMES[idx], (double)scores[idx], (double)compactness[idx]);
}
}
}
};
// ---------------------------- Zorro DLL entry ----------------------------
static CompactDominantStrategy* S = NULL;
DLLFUNC void run()
{
if(is(INITRUN)) {
BarPeriod = 60;
LookBack = max(LookBack, FEAT_WINDOW + 50);
asset((char*)ASSET_NAMES[0]);
if(!S) {
S = new CompactDominantStrategy();
S->init();
}
}
if(is(EXITRUN)) {
if(S) {
S->shutdown();
delete S;
S = NULL;
}
return;
}
if(!S || Bar < LookBack)
return;
S->onBar();
}