Add CSV exports: BarHistory, TradeHistory, AgentInteraction, DecisionLog, plus .gitignore
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
*.ex5
|
||||||
|
*.log
|
||||||
@@ -18,9 +18,55 @@ struct BarSnapshot {
|
|||||||
double combinedZ;
|
double combinedZ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AgentSnapshot {
|
||||||
|
double lastZScore;
|
||||||
|
double weight;
|
||||||
|
double rho;
|
||||||
|
double bias;
|
||||||
|
double biasStd;
|
||||||
|
double rhoLearn;
|
||||||
|
double rawSignal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TradeRecord {
|
||||||
|
int ticket;
|
||||||
|
bool isBuy;
|
||||||
|
datetime entryTime;
|
||||||
|
datetime closeTime;
|
||||||
|
double entryPrice;
|
||||||
|
double closePrice;
|
||||||
|
double entryATR;
|
||||||
|
double entryZ;
|
||||||
|
double slPrice;
|
||||||
|
double highestPrice;
|
||||||
|
double lowestPrice;
|
||||||
|
int barsHeld;
|
||||||
|
double maeATR;
|
||||||
|
double mfeATR;
|
||||||
|
double actualReturn;
|
||||||
|
double entryZScores[MAX_AGENTS];
|
||||||
|
double entryFeatures[NN_FEATURES];
|
||||||
|
string exitReason;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DecisionRecord {
|
||||||
|
datetime time;
|
||||||
|
string action;
|
||||||
|
int direction;
|
||||||
|
double zScore;
|
||||||
|
double combinedZ;
|
||||||
|
double price;
|
||||||
|
int ticket;
|
||||||
|
int agreeingCount;
|
||||||
|
int totalAgents;
|
||||||
|
double confidence;
|
||||||
|
double minZ;
|
||||||
|
};
|
||||||
|
|
||||||
// Posizione aperta tracciata con MAE/MFE
|
// Posizione aperta tracciata con MAE/MFE
|
||||||
struct TrackedTrade {
|
struct TrackedTrade {
|
||||||
int ticket;
|
int ticket;
|
||||||
|
datetime entryTime;
|
||||||
double entryPrice;
|
double entryPrice;
|
||||||
double entryATR;
|
double entryATR;
|
||||||
double entryZ;
|
double entryZ;
|
||||||
@@ -127,6 +173,14 @@ private:
|
|||||||
BarSnapshot history[MAX_HISTORY];
|
BarSnapshot history[MAX_HISTORY];
|
||||||
int histIdx;
|
int histIdx;
|
||||||
int histCount;
|
int histCount;
|
||||||
|
|
||||||
|
// --- Export buffers ---
|
||||||
|
AgentSnapshot agentHistory[MAX_HISTORY][MAX_AGENTS];
|
||||||
|
TradeRecord completedTrades[];
|
||||||
|
int completedTradeCount;
|
||||||
|
DecisionRecord decisionLog[];
|
||||||
|
int decisionCount;
|
||||||
|
int decisionCapacity;
|
||||||
|
|
||||||
void InitCorrelation(int idx) {
|
void InitCorrelation(int idx) {
|
||||||
corrMeanX[idx] = 0;
|
corrMeanX[idx] = 0;
|
||||||
@@ -250,11 +304,20 @@ public:
|
|||||||
m_trainBuffer = new NNTrainBuffer();
|
m_trainBuffer = new NNTrainBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
histIdx = 0;
|
histIdx = 0;
|
||||||
histCount = 0;
|
histCount = 0;
|
||||||
}
|
|
||||||
|
|
||||||
~Orchestrator() {
|
completedTradeCount = 0;
|
||||||
|
ArrayResize(completedTrades, 200);
|
||||||
|
decisionCount = 0;
|
||||||
|
decisionCapacity = 500;
|
||||||
|
ArrayResize(decisionLog, decisionCapacity);
|
||||||
|
for(int ai = 0; ai < MAX_HISTORY; ai++)
|
||||||
|
for(int aj = 0; aj < MAX_AGENTS; aj++)
|
||||||
|
agentHistory[ai][aj].lastZScore = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Orchestrator() {
|
||||||
ReleaseAgents();
|
ReleaseAgents();
|
||||||
if(m_neuralNet) delete m_neuralNet;
|
if(m_neuralNet) delete m_neuralNet;
|
||||||
if(m_trainBuffer) delete m_trainBuffer;
|
if(m_trainBuffer) delete m_trainBuffer;
|
||||||
@@ -425,10 +488,11 @@ public:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
openTrades[idx].ticket = ticket;
|
openTrades[idx].ticket = ticket;
|
||||||
openTrades[idx].entryPrice = price;
|
openTrades[idx].entryPrice = price;
|
||||||
openTrades[idx].entryATR = MathMax(atr, 1e-10);
|
openTrades[idx].entryATR = MathMax(atr, 1e-10);
|
||||||
openTrades[idx].entryZ = z;
|
openTrades[idx].entryZ = z;
|
||||||
openTrades[idx].isBuy = isBuy;
|
openTrades[idx].isBuy = isBuy;
|
||||||
|
openTrades[idx].entryTime = TimeCurrent();
|
||||||
openTrades[idx].highestPrice = price;
|
openTrades[idx].highestPrice = price;
|
||||||
openTrades[idx].lowestPrice = price;
|
openTrades[idx].lowestPrice = price;
|
||||||
openTrades[idx].barsHeld = 0;
|
openTrades[idx].barsHeld = 0;
|
||||||
@@ -463,11 +527,40 @@ openTrades[idx].ticket = ticket;
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTradeOpen(int ticket, double price, double atr) {
|
void OnTradeOpen(int ticket, double price, double atr) {
|
||||||
AddTrade(ticket, price, atr, combinedZ, combinedZ > 0);
|
AddTrade(ticket, price, atr, combinedZ, combinedZ > 0);
|
||||||
}
|
LogDecision("ENTRY", combinedZ > 0 ? 1 : -1, 0, price, ticket);
|
||||||
|
}
|
||||||
void OnTradeClose(int ticket, double closePrice) {
|
|
||||||
|
void LogDecision(string action, int dir, double minZ, double price, int ticket = 0) {
|
||||||
|
if(decisionCount >= decisionCapacity) {
|
||||||
|
decisionCapacity *= 2;
|
||||||
|
ArrayResize(decisionLog, decisionCapacity);
|
||||||
|
}
|
||||||
|
DecisionRecord d;
|
||||||
|
d.time = TimeCurrent();
|
||||||
|
d.action = action;
|
||||||
|
d.direction = dir;
|
||||||
|
d.zScore = MathAbs(combinedZ);
|
||||||
|
d.combinedZ = combinedZ;
|
||||||
|
d.price = price;
|
||||||
|
d.ticket = ticket;
|
||||||
|
d.agreeingCount = 0;
|
||||||
|
d.totalAgents = agentCount;
|
||||||
|
d.confidence = MathAbs(combinedZ);
|
||||||
|
d.minZ = minZ;
|
||||||
|
if(action == "SIGNAL" || action == "ENTRY") {
|
||||||
|
for(int i=0; i<agentCount; i++) {
|
||||||
|
if(agents[i].enabled && MathAbs(agents[i].lastZScore) > 0.1) {
|
||||||
|
if((agents[i].lastZScore > 0) == (dir > 0)) d.agreeingCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decisionLog[decisionCount] = d;
|
||||||
|
decisionCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTradeClose(int ticket, double closePrice, string exitReason = "MANUAL") {
|
||||||
// Trova il trade nell'array
|
// Trova il trade nell'array
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
for(int i=0; i<maxOpenTrades; i++) {
|
for(int i=0; i<maxOpenTrades; i++) {
|
||||||
@@ -572,10 +665,34 @@ UpdateCorrelation(i, openTrades[idx].entryZScores[i], actualReturnZ);
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateHealth(actualReturn);
|
UpdateHealth(actualReturn);
|
||||||
LogHealth();
|
LogHealth();
|
||||||
|
|
||||||
openTrades[idx].active = false;
|
// Save completed trade record
|
||||||
}
|
int ct = completedTradeCount;
|
||||||
|
ArrayResize(completedTrades, ct + 1);
|
||||||
|
completedTrades[ct].ticket = openTrades[idx].ticket;
|
||||||
|
completedTrades[ct].isBuy = openTrades[idx].isBuy;
|
||||||
|
completedTrades[ct].entryPrice = openTrades[idx].entryPrice;
|
||||||
|
completedTrades[ct].closePrice = closePrice;
|
||||||
|
completedTrades[ct].entryATR = openTrades[idx].entryATR;
|
||||||
|
completedTrades[ct].entryZ = openTrades[idx].entryZ;
|
||||||
|
completedTrades[ct].slPrice = openTrades[idx].slPrice;
|
||||||
|
completedTrades[ct].highestPrice = openTrades[idx].highestPrice;
|
||||||
|
completedTrades[ct].lowestPrice = openTrades[idx].lowestPrice;
|
||||||
|
completedTrades[ct].barsHeld = openTrades[idx].barsHeld;
|
||||||
|
completedTrades[ct].maeATR = openTrades[idx].maeATR;
|
||||||
|
completedTrades[ct].mfeATR = openTrades[idx].mfeATR;
|
||||||
|
completedTrades[ct].actualReturn = actualReturn;
|
||||||
|
completedTrades[ct].entryTime = 0;
|
||||||
|
completedTrades[ct].closeTime = TimeCurrent();
|
||||||
|
completedTrades[ct].exitReason = exitReason;
|
||||||
|
for(int ei = 0; ei < agentCount; ei++) completedTrades[ct].entryZScores[ei] = openTrades[idx].entryZScores[ei];
|
||||||
|
for(int ef = 0; ef < NN_FEATURES; ef++) completedTrades[ct].entryFeatures[ef] = openTrades[idx].entryFeatures[ef];
|
||||||
|
|
||||||
|
LogDecision("EXIT", openTrades[idx].isBuy ? 1 : -1, 0, closePrice, ticket);
|
||||||
|
|
||||||
|
openTrades[idx].active = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Trova un trade per ticket
|
// Trova un trade per ticket
|
||||||
int FindTrade(int ticket) const {
|
int FindTrade(int ticket) const {
|
||||||
@@ -776,11 +893,20 @@ UpdateHealth(actualReturn);
|
|||||||
for(int i=0; i<MAX_AGENTS; i++) prevCorr[i] = 0;
|
for(int i=0; i<MAX_AGENTS; i++) prevCorr[i] = 0;
|
||||||
for(int i=0; i<ROLLING_TRADES; i++) rollingReturns[i] = 0;
|
for(int i=0; i<ROLLING_TRADES; i++) rollingReturns[i] = 0;
|
||||||
|
|
||||||
histIdx = 0;
|
histIdx = 0;
|
||||||
histCount = 0;
|
histCount = 0;
|
||||||
}
|
|
||||||
|
completedTradeCount = 0;
|
||||||
// --- Self-evaluation ---
|
ArrayResize(completedTrades, 200);
|
||||||
|
decisionCount = 0;
|
||||||
|
decisionCapacity = 500;
|
||||||
|
ArrayResize(decisionLog, decisionCapacity);
|
||||||
|
for(int ai = 0; ai < MAX_HISTORY; ai++)
|
||||||
|
for(int aj = 0; aj < MAX_AGENTS; aj++)
|
||||||
|
agentHistory[ai][aj].lastZScore = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Self-evaluation ---
|
||||||
void UpdateHealth(double actualReturn) {
|
void UpdateHealth(double actualReturn) {
|
||||||
// Rolling returns buffer
|
// Rolling returns buffer
|
||||||
rollingReturns[rollingIdx] = actualReturn;
|
rollingReturns[rollingIdx] = actualReturn;
|
||||||
@@ -856,8 +982,16 @@ UpdateHealth(actualReturn);
|
|||||||
void LogBarHistory(datetime time) {
|
void LogBarHistory(datetime time) {
|
||||||
history[histIdx].time = time;
|
history[histIdx].time = time;
|
||||||
history[histIdx].combinedZ = combinedZ;
|
history[histIdx].combinedZ = combinedZ;
|
||||||
for(int i=0; i<agentCount; i++)
|
for(int i=0; i<agentCount; i++) {
|
||||||
history[histIdx].z[i] = agents[i].lastZScore;
|
history[histIdx].z[i] = agents[i].lastZScore;
|
||||||
|
agentHistory[histIdx][i].lastZScore = agents[i].lastZScore;
|
||||||
|
agentHistory[histIdx][i].weight = agents[i].weight;
|
||||||
|
agentHistory[histIdx][i].rho = GetCorrelation(i);
|
||||||
|
agentHistory[histIdx][i].bias = agents[i].predictionError.Mean();
|
||||||
|
agentHistory[histIdx][i].biasStd = agents[i].predictionError.Std();
|
||||||
|
agentHistory[histIdx][i].rhoLearn = agents[i].predCorr.Ready() ? agents[i].predCorr.Correlation() : 0;
|
||||||
|
agentHistory[histIdx][i].rawSignal = agents[i].lastRawSignal;
|
||||||
|
}
|
||||||
histIdx = (histIdx + 1) % MAX_HISTORY;
|
histIdx = (histIdx + 1) % MAX_HISTORY;
|
||||||
if(histCount < MAX_HISTORY) histCount++;
|
if(histCount < MAX_HISTORY) histCount++;
|
||||||
}
|
}
|
||||||
@@ -1299,5 +1433,165 @@ UpdateHealth(actualReturn);
|
|||||||
FileClose(fh);
|
FileClose(fh);
|
||||||
Print("Analisi salvata: ", fn);
|
Print("Analisi salvata: ", fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================== SAVE BAR HISTORY CSV =====================
|
||||||
|
void SaveBarHistoryCSV(string symbol, ENUM_TIMEFRAMES tf) const {
|
||||||
|
string fn = "BarHistory_" + symbol + "_" + EnumToString(tf) + ".csv";
|
||||||
|
int fh = FileOpen(fn, FILE_TXT|FILE_WRITE|FILE_COMMON);
|
||||||
|
if(fh == INVALID_HANDLE) { Print("BarHistoryCSV: errore apertura ", fn); return; }
|
||||||
|
|
||||||
|
string header = "bar,time,combinedZ";
|
||||||
|
string agentNames[MAX_AGENTS];
|
||||||
|
for(int i=0; i<agentCount; i++) {
|
||||||
|
agentNames[i] = agents[i].name;
|
||||||
|
header += "," + agentNames[i] + "_z";
|
||||||
|
}
|
||||||
|
header += ",regimeH,adxRaw,regimeConsensus,agreement,trendStrength,patternName";
|
||||||
|
FileWriteString(fh, header + "\r\n");
|
||||||
|
|
||||||
|
int n = MathMin(histCount, MAX_HISTORY);
|
||||||
|
int start = (histCount >= MAX_HISTORY) ? histIdx : 0;
|
||||||
|
for(int i=0; i<n; i++) {
|
||||||
|
int ii = (start + i) % MAX_HISTORY;
|
||||||
|
string line = (string)i + "," + TimeToString(history[ii].time) + "," + StringFormat("%+.6f", history[ii].combinedZ);
|
||||||
|
for(int j=0; j<agentCount; j++)
|
||||||
|
line += "," + StringFormat("%+.6f", history[ii].z[j]);
|
||||||
|
line += "," + StringFormat("%.4f", SHARED_regimeH);
|
||||||
|
line += "," + StringFormat("%.1f", SHARED_adxRaw);
|
||||||
|
line += "," + StringFormat("%+.4f", SHARED_regimeConsensus);
|
||||||
|
line += "," + StringFormat("%.4f", SHARED_regimeAgreement);
|
||||||
|
line += "," + StringFormat("%.4f", SHARED_trendStrength);
|
||||||
|
line += "," + SHARED_patternName;
|
||||||
|
FileWriteString(fh, line + "\r\n");
|
||||||
|
}
|
||||||
|
FileClose(fh);
|
||||||
|
Print("Bar history salvata: ", fn, " (", n, " barre)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== SAVE TRADE HISTORY CSV =====================
|
||||||
|
void SaveTradeHistoryCSV(string symbol, ENUM_TIMEFRAMES tf) const {
|
||||||
|
string fn = "TradeHistory_" + symbol + "_" + EnumToString(tf) + ".csv";
|
||||||
|
int fh = FileOpen(fn, FILE_TXT|FILE_WRITE|FILE_COMMON);
|
||||||
|
if(fh == INVALID_HANDLE) { Print("TradeHistoryCSV: errore apertura ", fn); return; }
|
||||||
|
|
||||||
|
string header = "ticket,isBuy,entryTime,closeTime,barsHeld,entryPrice,closePrice,entryATR,entryZ,slPrice,highestPrice,lowestPrice,maeATR,mfeATR,actualReturn,exitReason";
|
||||||
|
string agentNames[MAX_AGENTS];
|
||||||
|
for(int i=0; i<agentCount; i++) {
|
||||||
|
agentNames[i] = agents[i].name;
|
||||||
|
header += "," + agentNames[i] + "_entryZ";
|
||||||
|
}
|
||||||
|
string featLabels[NN_FEATURES] = {"Hurst","ADX","MA","Momentum","Consensus","Hunter","Agreement","TrendStr"};
|
||||||
|
for(int f=0; f<NN_FEATURES; f++) header += ",feat_" + featLabels[f];
|
||||||
|
FileWriteString(fh, header + "\r\n");
|
||||||
|
|
||||||
|
// Completed trades
|
||||||
|
for(int t=0; t<completedTradeCount; t++) {
|
||||||
|
string line = (string)completedTrades[t].ticket;
|
||||||
|
line += "," + (string)(completedTrades[t].isBuy ? 1 : 0);
|
||||||
|
line += "," + TimeToString(completedTrades[t].entryTime);
|
||||||
|
line += "," + TimeToString(completedTrades[t].closeTime);
|
||||||
|
line += "," + (string)completedTrades[t].barsHeld;
|
||||||
|
line += "," + StringFormat("%.5f", completedTrades[t].entryPrice);
|
||||||
|
line += "," + StringFormat("%.5f", completedTrades[t].closePrice);
|
||||||
|
line += "," + StringFormat("%.4f", completedTrades[t].entryATR);
|
||||||
|
line += "," + StringFormat("%+.4f", completedTrades[t].entryZ);
|
||||||
|
line += "," + StringFormat("%.5f", completedTrades[t].slPrice);
|
||||||
|
line += "," + StringFormat("%.5f", completedTrades[t].highestPrice);
|
||||||
|
line += "," + StringFormat("%.5f", completedTrades[t].lowestPrice);
|
||||||
|
line += "," + StringFormat("%.4f", completedTrades[t].maeATR);
|
||||||
|
line += "," + StringFormat("%.4f", completedTrades[t].mfeATR);
|
||||||
|
line += "," + StringFormat("%+.4f", completedTrades[t].actualReturn);
|
||||||
|
line += "," + completedTrades[t].exitReason;
|
||||||
|
for(int j=0; j<agentCount; j++)
|
||||||
|
line += "," + StringFormat("%+.4f", completedTrades[t].entryZScores[j]);
|
||||||
|
for(int f=0; f<NN_FEATURES; f++)
|
||||||
|
line += "," + StringFormat("%+.4f", completedTrades[t].entryFeatures[f]);
|
||||||
|
FileWriteString(fh, line + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open trades (still active)
|
||||||
|
for(int i=0; i<maxOpenTrades; i++) {
|
||||||
|
if(!openTrades[i].active) continue;
|
||||||
|
string line = (string)openTrades[i].ticket;
|
||||||
|
line += "," + (string)(openTrades[i].isBuy ? 1 : 0);
|
||||||
|
line += ",,"; // no close time yet
|
||||||
|
line += "," + (string)openTrades[i].barsHeld;
|
||||||
|
line += "," + StringFormat("%.5f", openTrades[i].entryPrice);
|
||||||
|
line += ","; // no close price yet
|
||||||
|
line += "," + StringFormat("%.4f", openTrades[i].entryATR);
|
||||||
|
line += "," + StringFormat("%+.4f", openTrades[i].entryZ);
|
||||||
|
line += "," + StringFormat("%.5f", openTrades[i].slPrice);
|
||||||
|
line += "," + StringFormat("%.5f", openTrades[i].highestPrice);
|
||||||
|
line += "," + StringFormat("%.5f", openTrades[i].lowestPrice);
|
||||||
|
line += "," + StringFormat("%.4f", openTrades[i].maeATR);
|
||||||
|
line += "," + StringFormat("%.4f", openTrades[i].mfeATR);
|
||||||
|
line += ",,OPEN"; // no return, exit=OPEN
|
||||||
|
for(int j=0; j<agentCount; j++)
|
||||||
|
line += "," + StringFormat("%+.4f", openTrades[i].entryZScores[j]);
|
||||||
|
for(int f=0; f<NN_FEATURES; f++)
|
||||||
|
line += "," + StringFormat("%+.4f", openTrades[i].entryFeatures[f]);
|
||||||
|
FileWriteString(fh, line + "\r\n");
|
||||||
|
}
|
||||||
|
FileClose(fh);
|
||||||
|
Print("Trade history salvata: ", fn, " (", completedTradeCount, " completati, ", OpenTradeCount(), " aperti)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== SAVE AGENT INTERACTION CSV =====================
|
||||||
|
void SaveAgentInteractionCSV(string symbol, ENUM_TIMEFRAMES tf) const {
|
||||||
|
string fn = "AgentInteraction_" + symbol + "_" + EnumToString(tf) + ".csv";
|
||||||
|
int fh = FileOpen(fn, FILE_TXT|FILE_WRITE|FILE_COMMON);
|
||||||
|
if(fh == INVALID_HANDLE) { Print("AgentInteractionCSV: errore apertura ", fn); return; }
|
||||||
|
|
||||||
|
string header = "bar,time,combinedZ";
|
||||||
|
for(int i=0; i<agentCount; i++) {
|
||||||
|
string n = agents[i].name;
|
||||||
|
header += "," + n + "_z," + n + "_weight," + n + "_rho," + n + "_bias," + n + "_biasStd," + n + "_rhoLearn," + n + "_rawSignal";
|
||||||
|
}
|
||||||
|
FileWriteString(fh, header + "\r\n");
|
||||||
|
|
||||||
|
int n = MathMin(histCount, MAX_HISTORY);
|
||||||
|
int start = (histCount >= MAX_HISTORY) ? histIdx : 0;
|
||||||
|
for(int i=0; i<n; i++) {
|
||||||
|
int ii = (start + i) % MAX_HISTORY;
|
||||||
|
string line = (string)i + "," + TimeToString(history[ii].time) + "," + StringFormat("%+.6f", history[ii].combinedZ);
|
||||||
|
for(int j=0; j<agentCount; j++) {
|
||||||
|
line += "," + StringFormat("%+.4f", agentHistory[ii][j].lastZScore);
|
||||||
|
line += "," + StringFormat("%.4f", agentHistory[ii][j].weight);
|
||||||
|
line += "," + StringFormat("%+.4f", agentHistory[ii][j].rho);
|
||||||
|
line += "," + StringFormat("%+.4f", agentHistory[ii][j].bias);
|
||||||
|
line += "," + StringFormat("%.4f", agentHistory[ii][j].biasStd);
|
||||||
|
line += "," + StringFormat("%+.4f", agentHistory[ii][j].rhoLearn);
|
||||||
|
line += "," + StringFormat("%+.4f", agentHistory[ii][j].rawSignal);
|
||||||
|
}
|
||||||
|
FileWriteString(fh, line + "\r\n");
|
||||||
|
}
|
||||||
|
FileClose(fh);
|
||||||
|
Print("Agent interaction salvata: ", fn, " (", n, " barre)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== SAVE DECISION LOG CSV =====================
|
||||||
|
void SaveDecisionLogCSV(string symbol, ENUM_TIMEFRAMES tf) const {
|
||||||
|
string fn = "DecisionLog_" + symbol + "_" + EnumToString(tf) + ".csv";
|
||||||
|
int fh = FileOpen(fn, FILE_TXT|FILE_WRITE|FILE_COMMON);
|
||||||
|
if(fh == INVALID_HANDLE) { Print("DecisionLogCSV: errore apertura ", fn); return; }
|
||||||
|
|
||||||
|
FileWriteString(fh, "time,action,direction,zScore,combinedZ,price,ticket,agreeingCount,totalAgents,confidence,minZ\r\n");
|
||||||
|
for(int d=0; d<decisionCount; d++) {
|
||||||
|
string line = TimeToString(decisionLog[d].time);
|
||||||
|
line += "," + decisionLog[d].action;
|
||||||
|
line += "," + (string)decisionLog[d].direction;
|
||||||
|
line += "," + StringFormat("%+.4f", decisionLog[d].zScore);
|
||||||
|
line += "," + StringFormat("%+.4f", decisionLog[d].combinedZ);
|
||||||
|
line += "," + StringFormat("%.5f", decisionLog[d].price);
|
||||||
|
line += "," + (string)decisionLog[d].ticket;
|
||||||
|
line += "," + (string)decisionLog[d].agreeingCount;
|
||||||
|
line += "," + (string)decisionLog[d].totalAgents;
|
||||||
|
line += "," + StringFormat("%.4f", decisionLog[d].confidence);
|
||||||
|
line += "," + StringFormat("%.4f", decisionLog[d].minZ);
|
||||||
|
FileWriteString(fh, line + "\r\n");
|
||||||
|
}
|
||||||
|
FileClose(fh);
|
||||||
|
Print("Decision log salvato: ", fn, " (", decisionCount, " decisioni)");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -169,15 +169,27 @@ void OnDeinit(const int reason) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Agent learning summary
|
// Agent learning summary
|
||||||
orchestrator.PrintAgentLearningSummary();
|
orchestrator.PrintAgentLearningSummary();
|
||||||
orchestrator.SaveAgentLearningCsv();
|
orchestrator.SaveAgentLearningCsv();
|
||||||
|
|
||||||
// Analisi completa: tutti i parametri derivati, soglie, periodi, stats
|
// Per-bar agent z-scores, combinedZ, SHARED variables
|
||||||
orchestrator.SaveAnalysisCSV(sym, Inp_TF);
|
orchestrator.SaveBarHistoryCSV(sym, Inp_TF);
|
||||||
|
|
||||||
// Save state file (include NN weights inline se addestrata)
|
// Per-bar agent weights, biases, correlations, raw signals
|
||||||
orchestrator.SaveState(sym, Inp_TF);
|
orchestrator.SaveAgentInteractionCSV(sym, Inp_TF);
|
||||||
|
|
||||||
|
// Per-trade details with PnL, exitReason, full features
|
||||||
|
orchestrator.SaveTradeHistoryCSV(sym, Inp_TF);
|
||||||
|
|
||||||
|
// Entry/exit decision log
|
||||||
|
orchestrator.SaveDecisionLogCSV(sym, Inp_TF);
|
||||||
|
|
||||||
|
// Analisi completa: tutti i parametri derivati, soglie, periodi, stats
|
||||||
|
orchestrator.SaveAnalysisCSV(sym, Inp_TF);
|
||||||
|
|
||||||
|
// Save state file (include NN weights inline se addestrata)
|
||||||
|
orchestrator.SaveState(sym, Inp_TF);
|
||||||
|
|
||||||
// Salva anche NN standalone (utile per debug/backup)
|
// Salva anche NN standalone (utile per debug/backup)
|
||||||
if(nnTrained || orchestrator.IsNeuralReady())
|
if(nnTrained || orchestrator.IsNeuralReady())
|
||||||
@@ -300,11 +312,11 @@ void ManagePositions(const MarketData &data, const FinalSignal &fs) {
|
|||||||
if(PositionSelectByTicket(tkt)) {
|
if(PositionSelectByTicket(tkt)) {
|
||||||
bool isBuy = orchestrator.IsBuyTrade(tkt);
|
bool isBuy = orchestrator.IsBuyTrade(tkt);
|
||||||
double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
|
double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
|
||||||
orchestrator.OnTradeClose(tkt, closePrice);
|
orchestrator.OnTradeClose(tkt, closePrice, "REVERSAL");
|
||||||
trade.PositionClose(tkt);
|
trade.PositionClose(tkt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Aggiorna trailing stop sul terminale (tester supporta PositionModify)
|
// 3. Aggiorna trailing stop sul terminale (tester supporta PositionModify)
|
||||||
for(int i=PositionsTotal()-1; i>=0; i--) {
|
for(int i=PositionsTotal()-1; i>=0; i--) {
|
||||||
@@ -409,6 +421,10 @@ void LogSignal(const MarketData &data, const FinalSignal &fs) {
|
|||||||
}
|
}
|
||||||
printCounter++;
|
printCounter++;
|
||||||
|
|
||||||
|
// Log decision even for non-actionable signals
|
||||||
|
double minZ = (Inp_MinZ > 0) ? Inp_MinZ : orchestrator.AdaptiveMinZ();
|
||||||
|
orchestrator.LogDecision("SIGNAL", fs.direction, minZ, data.Close(0));
|
||||||
|
|
||||||
if(MathAbs(fs.zScore) > Inp_MinZ) {
|
if(MathAbs(fs.zScore) > Inp_MinZ) {
|
||||||
Print(log);
|
Print(log);
|
||||||
Print(" Agents: ", fs.contributingAgents);
|
Print(" Agents: ", fs.contributingAgents);
|
||||||
@@ -438,7 +454,7 @@ void OnTrade() {
|
|||||||
// Trade closed by SL/TP (not by ManagePositions)
|
// Trade closed by SL/TP (not by ManagePositions)
|
||||||
bool isBuy = orchestrator.IsBuyTrade(tkt);
|
bool isBuy = orchestrator.IsBuyTrade(tkt);
|
||||||
double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
|
double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
|
||||||
orchestrator.OnTradeClose(tkt, closePrice);
|
orchestrator.OnTradeClose(tkt, closePrice, "SLTP");
|
||||||
onTradeCloses++;
|
onTradeCloses++;
|
||||||
Print("SL/TP chiuso trade #", tkt, " (totale SL/TP: ", onTradeCloses, ")");
|
Print("SL/TP chiuso trade #", tkt, " (totale SL/TP: ", onTradeCloses, ")");
|
||||||
if(onTradeCloses % saveInterval == 0)
|
if(onTradeCloses % saveInterval == 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user