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;
|
||||
};
|
||||
|
||||
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
|
||||
struct TrackedTrade {
|
||||
int ticket;
|
||||
datetime entryTime;
|
||||
double entryPrice;
|
||||
double entryATR;
|
||||
double entryZ;
|
||||
@@ -127,6 +173,14 @@ private:
|
||||
BarSnapshot history[MAX_HISTORY];
|
||||
int histIdx;
|
||||
int histCount;
|
||||
|
||||
// --- Export buffers ---
|
||||
AgentSnapshot agentHistory[MAX_HISTORY][MAX_AGENTS];
|
||||
TradeRecord completedTrades[];
|
||||
int completedTradeCount;
|
||||
DecisionRecord decisionLog[];
|
||||
int decisionCount;
|
||||
int decisionCapacity;
|
||||
|
||||
void InitCorrelation(int idx) {
|
||||
corrMeanX[idx] = 0;
|
||||
@@ -250,11 +304,20 @@ public:
|
||||
m_trainBuffer = new NNTrainBuffer();
|
||||
}
|
||||
|
||||
histIdx = 0;
|
||||
histCount = 0;
|
||||
}
|
||||
histIdx = 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();
|
||||
if(m_neuralNet) delete m_neuralNet;
|
||||
if(m_trainBuffer) delete m_trainBuffer;
|
||||
@@ -425,10 +488,11 @@ public:
|
||||
return -1;
|
||||
}
|
||||
openTrades[idx].ticket = ticket;
|
||||
openTrades[idx].entryPrice = price;
|
||||
openTrades[idx].entryATR = MathMax(atr, 1e-10);
|
||||
openTrades[idx].entryZ = z;
|
||||
openTrades[idx].isBuy = isBuy;
|
||||
openTrades[idx].entryPrice = price;
|
||||
openTrades[idx].entryATR = MathMax(atr, 1e-10);
|
||||
openTrades[idx].entryZ = z;
|
||||
openTrades[idx].isBuy = isBuy;
|
||||
openTrades[idx].entryTime = TimeCurrent();
|
||||
openTrades[idx].highestPrice = price;
|
||||
openTrades[idx].lowestPrice = price;
|
||||
openTrades[idx].barsHeld = 0;
|
||||
@@ -463,11 +527,40 @@ openTrades[idx].ticket = ticket;
|
||||
return idx;
|
||||
}
|
||||
|
||||
void OnTradeOpen(int ticket, double price, double atr) {
|
||||
AddTrade(ticket, price, atr, combinedZ, combinedZ > 0);
|
||||
}
|
||||
|
||||
void OnTradeClose(int ticket, double closePrice) {
|
||||
void OnTradeOpen(int ticket, double price, double atr) {
|
||||
AddTrade(ticket, price, atr, combinedZ, combinedZ > 0);
|
||||
LogDecision("ENTRY", combinedZ > 0 ? 1 : -1, 0, price, ticket);
|
||||
}
|
||||
|
||||
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
|
||||
int idx = -1;
|
||||
for(int i=0; i<maxOpenTrades; i++) {
|
||||
@@ -572,10 +665,34 @@ UpdateCorrelation(i, openTrades[idx].entryZScores[i], actualReturnZ);
|
||||
}
|
||||
|
||||
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
|
||||
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<ROLLING_TRADES; i++) rollingReturns[i] = 0;
|
||||
|
||||
histIdx = 0;
|
||||
histCount = 0;
|
||||
}
|
||||
|
||||
// --- Self-evaluation ---
|
||||
histIdx = 0;
|
||||
histCount = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// --- Self-evaluation ---
|
||||
void UpdateHealth(double actualReturn) {
|
||||
// Rolling returns buffer
|
||||
rollingReturns[rollingIdx] = actualReturn;
|
||||
@@ -856,8 +982,16 @@ UpdateHealth(actualReturn);
|
||||
void LogBarHistory(datetime time) {
|
||||
history[histIdx].time = time;
|
||||
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;
|
||||
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;
|
||||
if(histCount < MAX_HISTORY) histCount++;
|
||||
}
|
||||
@@ -1299,5 +1433,165 @@ UpdateHealth(actualReturn);
|
||||
FileClose(fh);
|
||||
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
|
||||
|
||||
@@ -169,15 +169,27 @@ void OnDeinit(const int reason) {
|
||||
}
|
||||
}
|
||||
|
||||
// Agent learning summary
|
||||
orchestrator.PrintAgentLearningSummary();
|
||||
orchestrator.SaveAgentLearningCsv();
|
||||
// Agent learning summary
|
||||
orchestrator.PrintAgentLearningSummary();
|
||||
orchestrator.SaveAgentLearningCsv();
|
||||
|
||||
// Analisi completa: tutti i parametri derivati, soglie, periodi, stats
|
||||
orchestrator.SaveAnalysisCSV(sym, Inp_TF);
|
||||
// Per-bar agent z-scores, combinedZ, SHARED variables
|
||||
orchestrator.SaveBarHistoryCSV(sym, Inp_TF);
|
||||
|
||||
// Save state file (include NN weights inline se addestrata)
|
||||
orchestrator.SaveState(sym, Inp_TF);
|
||||
// Per-bar agent weights, biases, correlations, raw signals
|
||||
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)
|
||||
if(nnTrained || orchestrator.IsNeuralReady())
|
||||
@@ -300,11 +312,11 @@ void ManagePositions(const MarketData &data, const FinalSignal &fs) {
|
||||
if(PositionSelectByTicket(tkt)) {
|
||||
bool isBuy = orchestrator.IsBuyTrade(tkt);
|
||||
double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
|
||||
orchestrator.OnTradeClose(tkt, closePrice);
|
||||
trade.PositionClose(tkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
orchestrator.OnTradeClose(tkt, closePrice, "REVERSAL");
|
||||
trade.PositionClose(tkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Aggiorna trailing stop sul terminale (tester supporta PositionModify)
|
||||
for(int i=PositionsTotal()-1; i>=0; i--) {
|
||||
@@ -409,6 +421,10 @@ void LogSignal(const MarketData &data, const FinalSignal &fs) {
|
||||
}
|
||||
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) {
|
||||
Print(log);
|
||||
Print(" Agents: ", fs.contributingAgents);
|
||||
@@ -438,7 +454,7 @@ void OnTrade() {
|
||||
// Trade closed by SL/TP (not by ManagePositions)
|
||||
bool isBuy = orchestrator.IsBuyTrade(tkt);
|
||||
double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
|
||||
orchestrator.OnTradeClose(tkt, closePrice);
|
||||
orchestrator.OnTradeClose(tkt, closePrice, "SLTP");
|
||||
onTradeCloses++;
|
||||
Print("SL/TP chiuso trade #", tkt, " (totale SL/TP: ", onTradeCloses, ")");
|
||||
if(onTradeCloses % saveInterval == 0)
|
||||
|
||||
Reference in New Issue
Block a user