Update
This commit is contained in:
@@ -0,0 +1,539 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SimpleRSIReversalAUDUSD.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
// Include trade class
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input int RSIPeriod = 28; // RSI period
|
||||
input double OverboughtLevel = 68; // Overbought level
|
||||
input double OversoldLevel = 30; // Oversold level
|
||||
input int TakeProfitPips = 175; // Take profit in pips
|
||||
input int StopLossPips = 5; // Stop loss in pips
|
||||
input double MaxLotSize = 0.2; // Maximum lot size
|
||||
input int MaxSpread = 1000; // Maximum allowed spread in pips
|
||||
input int MaxDuration = 340; // Maximum trade duration in hours
|
||||
input bool UseStopLoss = false; // Use stop loss
|
||||
input bool UseTakeProfit = false; // Use take profit
|
||||
input bool UseRSIExit = true; // Use RSI for exit
|
||||
input double RSIExitLevel = 48; // RSI level to exit (50 = neutral)
|
||||
input bool CloseOutsideSession = true; // Close trades outside Asian session
|
||||
input color PanelBackground = clrBlack; // Panel background color
|
||||
input color PanelText = clrWhite; // Panel text color
|
||||
input int PanelX = 10; // Panel X position
|
||||
input int PanelY = 20; // Panel Y position
|
||||
|
||||
// Global variables
|
||||
CTrade trade;
|
||||
int rsiHandle;
|
||||
bool isPositionOpen = false;
|
||||
double positionOpenPrice = 0;
|
||||
datetime positionOpenTime = 0;
|
||||
ENUM_POSITION_TYPE lastPositionType = POSITION_TYPE_BUY;
|
||||
bool sessionCloseAttempted = false; // Track if we've attempted to close positions for current session
|
||||
|
||||
// RSI crossover variables
|
||||
double rsiCurrent = 0;
|
||||
double rsiPrevious = 0;
|
||||
double rsiPrevious2 = 0;
|
||||
bool rsiCrossedOverbought = false;
|
||||
bool rsiCrossedOversold = false;
|
||||
bool rsiCrossedExitLevel = false;
|
||||
|
||||
// Panel objects
|
||||
string panelName = "RSIPanel";
|
||||
int panelWidth = 200;
|
||||
int panelHeight = 200;
|
||||
int labelHeight = 20;
|
||||
int labelSpacing = 5;
|
||||
|
||||
// Session times (UTC)
|
||||
const int AsianSessionStart = 0; // 00:00 UTC
|
||||
const int AsianSessionEnd = 8; // 08:00 UTC
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create panel |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreatePanel()
|
||||
{
|
||||
// Create panel background
|
||||
ObjectCreate(0, panelName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XDISTANCE, PanelX);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YDISTANCE, PanelY);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XSIZE, panelWidth);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YSIZE, panelHeight);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, PanelBackground);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTED, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_HIDDEN, true);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_ZORDER, 0);
|
||||
|
||||
// Create title label
|
||||
ObjectCreate(0, panelName + "Title", OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_YDISTANCE, PanelY + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + "Title", OBJPROP_TEXT, "RSI Reversal");
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_FONTSIZE, 10);
|
||||
|
||||
// Create score labels
|
||||
CreateScoreLabel("RSI", "RSI: ", 0);
|
||||
CreateScoreLabel("Position", "Position: ", 1);
|
||||
CreateScoreLabel("Spread", "Spread: ", 2);
|
||||
CreateScoreLabel("Session", "Session: ", 3);
|
||||
CreateScoreLabel("SL", "Stop Loss: ", 4);
|
||||
CreateScoreLabel("TP", "Take Profit: ", 5);
|
||||
CreateScoreLabel("Cross", "Cross: ", 6);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create score label |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreateScoreLabel(string name, string text, int index)
|
||||
{
|
||||
ObjectCreate(0, panelName + name, OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_YDISTANCE, PanelY + 30 + index * (labelHeight + labelSpacing));
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + name, OBJPROP_TEXT, text);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_FONTSIZE, 8);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update panel values |
|
||||
//+------------------------------------------------------------------+
|
||||
void UpdatePanel(double rsi, string position, int spread, string session, double sl, double tp, string crossInfo)
|
||||
{
|
||||
ObjectSetString(0, panelName + "RSI", OBJPROP_TEXT, "RSI: " + DoubleToString(rsi, 2));
|
||||
ObjectSetString(0, panelName + "Position", OBJPROP_TEXT, "Position: " + position);
|
||||
ObjectSetString(0, panelName + "Spread", OBJPROP_TEXT, "Spread: " + IntegerToString(spread) + " pips");
|
||||
ObjectSetString(0, panelName + "Session", OBJPROP_TEXT, "Session: " + session);
|
||||
ObjectSetString(0, panelName + "SL", OBJPROP_TEXT, "Stop Loss: " + IntegerToString(StopLossPips) + " pips");
|
||||
ObjectSetString(0, panelName + "TP", OBJPROP_TEXT, "Take Profit: " + IntegerToString(TakeProfitPips) + " pips");
|
||||
ObjectSetString(0, panelName + "Cross", OBJPROP_TEXT, "Cross: " + crossInfo);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if current time is in Asian session |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsAsianSession()
|
||||
{
|
||||
datetime currentTime = TimeCurrent();
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
|
||||
return (timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get current session name |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetCurrentSession()
|
||||
{
|
||||
datetime currentTime = TimeCurrent();
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
|
||||
if(timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd)
|
||||
return "Asian";
|
||||
else if(timeStruct.hour >= 8 && timeStruct.hour < 16)
|
||||
return "London";
|
||||
else if(timeStruct.hour >= 13 && timeStruct.hour < 21)
|
||||
return "New York";
|
||||
else
|
||||
return "Other";
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if trading is allowed |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsTradingAllowed()
|
||||
{
|
||||
// Check if market is open
|
||||
if(!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough money
|
||||
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check RSI crossover conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckRSICrossover()
|
||||
{
|
||||
// Reset crossover flags
|
||||
rsiCrossedOverbought = false;
|
||||
rsiCrossedOversold = false;
|
||||
rsiCrossedExitLevel = false;
|
||||
|
||||
// Check for overbought crossover (RSI crosses above overbought level)
|
||||
if(rsiPrevious < OverboughtLevel && rsiCurrent >= OverboughtLevel)
|
||||
{
|
||||
rsiCrossedOverbought = true;
|
||||
}
|
||||
|
||||
// Check for oversold crossover (RSI crosses below oversold level)
|
||||
if(rsiPrevious > OversoldLevel && rsiCurrent <= OversoldLevel)
|
||||
{
|
||||
rsiCrossedOversold = true;
|
||||
}
|
||||
|
||||
// Check for exit level crossover
|
||||
if(rsiPrevious < RSIExitLevel && rsiCurrent >= RSIExitLevel)
|
||||
{
|
||||
rsiCrossedExitLevel = true;
|
||||
}
|
||||
else if(rsiPrevious > RSIExitLevel && rsiCurrent <= RSIExitLevel)
|
||||
{
|
||||
rsiCrossedExitLevel = true;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsiHandle = iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE);
|
||||
|
||||
if(rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Wait a bit for the indicator to be ready
|
||||
Sleep(100);
|
||||
|
||||
// Initialize RSI values with retry logic
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
|
||||
int retryCount = 0;
|
||||
bool rsiInitialized = false;
|
||||
|
||||
while(retryCount < 10 && !rsiInitialized)
|
||||
{
|
||||
int copied = CopyBuffer(rsiHandle, 0, 0, 3, rsi);
|
||||
if(copied >= 3)
|
||||
{
|
||||
rsiCurrent = rsi[0];
|
||||
rsiPrevious = rsi[1];
|
||||
rsiPrevious2 = rsi[2];
|
||||
rsiInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
retryCount++;
|
||||
Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
if(!rsiInitialized)
|
||||
{
|
||||
// Don't fail initialization, just set default values
|
||||
rsiCurrent = 50.0;
|
||||
rsiPrevious = 50.0;
|
||||
rsiPrevious2 = 50.0;
|
||||
}
|
||||
|
||||
// Create panel
|
||||
CreatePanel();
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Release indicator handles
|
||||
IndicatorRelease(rsiHandle);
|
||||
|
||||
// Remove panel objects
|
||||
ObjectsDeleteAll(0, panelName);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close all trades for the current symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CloseAllTrades(string reason = "")
|
||||
{
|
||||
bool allClosed = true;
|
||||
int totalPositions = PositionsTotal();
|
||||
|
||||
if(totalPositions == 0)
|
||||
return true;
|
||||
|
||||
// Check if there are any positions with our magic number
|
||||
bool hasOurPositions = false;
|
||||
for(int i = 0; i < totalPositions; i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 123456)
|
||||
{
|
||||
hasOurPositions = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = totalPositions - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
// Try to close position with retry logic
|
||||
int retryCount = 0;
|
||||
bool positionClosed = false;
|
||||
|
||||
while(retryCount < 3 && !positionClosed)
|
||||
{
|
||||
if(trade.PositionClose(_Symbol))
|
||||
{
|
||||
isPositionOpen = false;
|
||||
positionClosed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = GetLastError();
|
||||
|
||||
// If error is 4756 (Trade disabled), wait longer before retry
|
||||
if(error == 4756)
|
||||
{
|
||||
Sleep(5000); // Wait 5 seconds before retry
|
||||
retryCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For other errors, break the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!positionClosed)
|
||||
{
|
||||
allClosed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allClosed;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if trading is allowed
|
||||
if(!IsTradingAllowed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we're in Asian session
|
||||
if(!IsAsianSession())
|
||||
{
|
||||
// Close all positions if outside Asian session and CloseOutsideSession is true
|
||||
if(CloseOutsideSession && !sessionCloseAttempted)
|
||||
{
|
||||
CloseAllTrades("Outside Asian session");
|
||||
sessionCloseAttempted = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the session close attempt flag when we enter Asian session
|
||||
sessionCloseAttempted = false;
|
||||
}
|
||||
|
||||
// Get current spread
|
||||
double spread = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
int spreadInPips = (int)(spread / _Point);
|
||||
|
||||
// Check if spread is too high
|
||||
if(spreadInPips > MaxSpread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get RSI values from bar data
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
|
||||
int copied = CopyBuffer(rsiHandle, 0, 0, 3, rsi);
|
||||
if(copied < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update RSI values
|
||||
rsiPrevious2 = rsiPrevious;
|
||||
rsiPrevious = rsiCurrent;
|
||||
rsiCurrent = rsi[0];
|
||||
|
||||
// Validate RSI values
|
||||
if(rsiCurrent == 0 || rsiPrevious == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for RSI crossovers
|
||||
CheckRSICrossover();
|
||||
|
||||
// Get current prices
|
||||
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
// Get position status
|
||||
string positionStatus = "None";
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
positionStatus = (posType == POSITION_TYPE_BUY) ? "Long" : "Short";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate stop loss and take profit levels
|
||||
double sl = 0;
|
||||
double tp = 0;
|
||||
|
||||
// Prepare crossover info for panel
|
||||
string crossInfo = "None";
|
||||
if(rsiCrossedOverbought) crossInfo = "Overbought";
|
||||
else if(rsiCrossedOversold) crossInfo = "Oversold";
|
||||
else if(rsiCrossedExitLevel) crossInfo = "Exit";
|
||||
|
||||
// Update panel
|
||||
UpdatePanel(rsiCurrent, positionStatus, spreadInPips, GetCurrentSession(), sl, tp, crossInfo);
|
||||
|
||||
// Check for open position
|
||||
bool hasOpenPosition = false;
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
hasOpenPosition = true;
|
||||
|
||||
// Get position details
|
||||
double positionProfit = PositionGetDouble(POSITION_PROFIT);
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
// Check for RSI exit if enabled
|
||||
if(UseRSIExit && rsiCrossedExitLevel)
|
||||
{
|
||||
bool shouldExit = false;
|
||||
|
||||
// For long positions, exit when RSI crosses above exit level
|
||||
if(posType == POSITION_TYPE_BUY && rsiCurrent >= RSIExitLevel && rsiPrevious < RSIExitLevel)
|
||||
{
|
||||
shouldExit = true;
|
||||
}
|
||||
// For short positions, exit when RSI crosses below exit level
|
||||
else if(posType == POSITION_TYPE_SELL && rsiCurrent <= RSIExitLevel && rsiPrevious > RSIExitLevel)
|
||||
{
|
||||
shouldExit = true;
|
||||
}
|
||||
|
||||
if(shouldExit)
|
||||
{
|
||||
CloseAllTrades("RSI Exit Crossover");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for timeout
|
||||
if(TimeCurrent() - positionOpenTime > MaxDuration * 3600)
|
||||
{
|
||||
CloseAllTrades("Timeout");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no position is open, look for entry signals based on RSI crossover
|
||||
if(!hasOpenPosition)
|
||||
{
|
||||
// Place buy order if RSI crosses below oversold level (oversold crossover)
|
||||
if(rsiCrossedOversold)
|
||||
{
|
||||
double sl = UseStopLoss ? currentBid - StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentBid + TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl >= currentBid)
|
||||
return;
|
||||
if(UseTakeProfit && tp <= currentBid)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place buy order using CTrade
|
||||
if(trade.Buy(MaxLotSize, _Symbol, currentAsk, sl, tp, "RSI Oversold Crossover Buy"))
|
||||
{
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentAsk;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
// Place sell order if RSI crosses above overbought level (overbought crossover)
|
||||
else if(rsiCrossedOverbought)
|
||||
{
|
||||
double sl = UseStopLoss ? currentAsk + StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentAsk - TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl <= currentAsk)
|
||||
return;
|
||||
if(UseTakeProfit && tp >= currentAsk)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place sell order using CTrade
|
||||
if(trade.Sell(MaxLotSize, _Symbol, currentBid, sl, tp, "RSI Overbought Crossover Sell"))
|
||||
{
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentBid;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 241 KiB |
@@ -0,0 +1,539 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SimpleRSIReversalAUDUSD.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
// Include trade class
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input int RSIPeriod = 28; // RSI period
|
||||
input double OverboughtLevel = 60; // Overbought level
|
||||
input double OversoldLevel = 8; // Oversold level
|
||||
input int TakeProfitPips = 175; // Take profit in pips
|
||||
input int StopLossPips = 5; // Stop loss in pips
|
||||
input double MaxLotSize = 0.1; // Maximum lot size
|
||||
input int MaxSpread = 1000; // Maximum allowed spread in pips
|
||||
input int MaxDuration = 270; // Maximum trade duration in hours
|
||||
input bool UseStopLoss = false; // Use stop loss
|
||||
input bool UseTakeProfit = false; // Use take profit
|
||||
input bool UseRSIExit = true; // Use RSI for exit
|
||||
input double RSIExitLevel = 55; // RSI level to exit (50 = neutral)
|
||||
input bool CloseOutsideSession = false; // Close trades outside Asian session
|
||||
input color PanelBackground = clrBlack; // Panel background color
|
||||
input color PanelText = clrWhite; // Panel text color
|
||||
input int PanelX = 10; // Panel X position
|
||||
input int PanelY = 20; // Panel Y position
|
||||
|
||||
// Global variables
|
||||
CTrade trade;
|
||||
int rsiHandle;
|
||||
bool isPositionOpen = false;
|
||||
double positionOpenPrice = 0;
|
||||
datetime positionOpenTime = 0;
|
||||
ENUM_POSITION_TYPE lastPositionType = POSITION_TYPE_BUY;
|
||||
bool sessionCloseAttempted = false; // Track if we've attempted to close positions for current session
|
||||
|
||||
// RSI crossover variables
|
||||
double rsiCurrent = 0;
|
||||
double rsiPrevious = 0;
|
||||
double rsiPrevious2 = 0;
|
||||
bool rsiCrossedOverbought = false;
|
||||
bool rsiCrossedOversold = false;
|
||||
bool rsiCrossedExitLevel = false;
|
||||
|
||||
// Panel objects
|
||||
string panelName = "RSIPanel";
|
||||
int panelWidth = 200;
|
||||
int panelHeight = 200;
|
||||
int labelHeight = 20;
|
||||
int labelSpacing = 5;
|
||||
|
||||
// Session times (UTC)
|
||||
const int AsianSessionStart = 0; // 00:00 UTC
|
||||
const int AsianSessionEnd = 8; // 08:00 UTC
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create panel |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreatePanel()
|
||||
{
|
||||
// Create panel background
|
||||
ObjectCreate(0, panelName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XDISTANCE, PanelX);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YDISTANCE, PanelY);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XSIZE, panelWidth);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YSIZE, panelHeight);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, PanelBackground);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTED, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_HIDDEN, true);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_ZORDER, 0);
|
||||
|
||||
// Create title label
|
||||
ObjectCreate(0, panelName + "Title", OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_YDISTANCE, PanelY + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + "Title", OBJPROP_TEXT, "RSI Reversal");
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_FONTSIZE, 10);
|
||||
|
||||
// Create score labels
|
||||
CreateScoreLabel("RSI", "RSI: ", 0);
|
||||
CreateScoreLabel("Position", "Position: ", 1);
|
||||
CreateScoreLabel("Spread", "Spread: ", 2);
|
||||
CreateScoreLabel("Session", "Session: ", 3);
|
||||
CreateScoreLabel("SL", "Stop Loss: ", 4);
|
||||
CreateScoreLabel("TP", "Take Profit: ", 5);
|
||||
CreateScoreLabel("Cross", "Cross: ", 6);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create score label |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreateScoreLabel(string name, string text, int index)
|
||||
{
|
||||
ObjectCreate(0, panelName + name, OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_YDISTANCE, PanelY + 30 + index * (labelHeight + labelSpacing));
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + name, OBJPROP_TEXT, text);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_FONTSIZE, 8);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update panel values |
|
||||
//+------------------------------------------------------------------+
|
||||
void UpdatePanel(double rsi, string position, int spread, string session, double sl, double tp, string crossInfo)
|
||||
{
|
||||
ObjectSetString(0, panelName + "RSI", OBJPROP_TEXT, "RSI: " + DoubleToString(rsi, 2));
|
||||
ObjectSetString(0, panelName + "Position", OBJPROP_TEXT, "Position: " + position);
|
||||
ObjectSetString(0, panelName + "Spread", OBJPROP_TEXT, "Spread: " + IntegerToString(spread) + " pips");
|
||||
ObjectSetString(0, panelName + "Session", OBJPROP_TEXT, "Session: " + session);
|
||||
ObjectSetString(0, panelName + "SL", OBJPROP_TEXT, "Stop Loss: " + IntegerToString(StopLossPips) + " pips");
|
||||
ObjectSetString(0, panelName + "TP", OBJPROP_TEXT, "Take Profit: " + IntegerToString(TakeProfitPips) + " pips");
|
||||
ObjectSetString(0, panelName + "Cross", OBJPROP_TEXT, "Cross: " + crossInfo);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if current time is in Asian session |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsAsianSession()
|
||||
{
|
||||
datetime currentTime = TimeCurrent();
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
|
||||
return (timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get current session name |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetCurrentSession()
|
||||
{
|
||||
datetime currentTime = TimeCurrent();
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
|
||||
if(timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd)
|
||||
return "Asian";
|
||||
else if(timeStruct.hour >= 8 && timeStruct.hour < 16)
|
||||
return "London";
|
||||
else if(timeStruct.hour >= 13 && timeStruct.hour < 21)
|
||||
return "New York";
|
||||
else
|
||||
return "Other";
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if trading is allowed |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsTradingAllowed()
|
||||
{
|
||||
// Check if market is open
|
||||
if(!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough money
|
||||
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check RSI crossover conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckRSICrossover()
|
||||
{
|
||||
// Reset crossover flags
|
||||
rsiCrossedOverbought = false;
|
||||
rsiCrossedOversold = false;
|
||||
rsiCrossedExitLevel = false;
|
||||
|
||||
// Check for overbought crossover (RSI crosses above overbought level)
|
||||
if(rsiPrevious < OverboughtLevel && rsiCurrent >= OverboughtLevel)
|
||||
{
|
||||
rsiCrossedOverbought = true;
|
||||
}
|
||||
|
||||
// Check for oversold crossover (RSI crosses below oversold level)
|
||||
if(rsiPrevious > OversoldLevel && rsiCurrent <= OversoldLevel)
|
||||
{
|
||||
rsiCrossedOversold = true;
|
||||
}
|
||||
|
||||
// Check for exit level crossover
|
||||
if(rsiPrevious < RSIExitLevel && rsiCurrent >= RSIExitLevel)
|
||||
{
|
||||
rsiCrossedExitLevel = true;
|
||||
}
|
||||
else if(rsiPrevious > RSIExitLevel && rsiCurrent <= RSIExitLevel)
|
||||
{
|
||||
rsiCrossedExitLevel = true;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsiHandle = iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE);
|
||||
|
||||
if(rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Wait a bit for the indicator to be ready
|
||||
Sleep(100);
|
||||
|
||||
// Initialize RSI values with retry logic
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
|
||||
int retryCount = 0;
|
||||
bool rsiInitialized = false;
|
||||
|
||||
while(retryCount < 10 && !rsiInitialized)
|
||||
{
|
||||
int copied = CopyBuffer(rsiHandle, 0, 0, 3, rsi);
|
||||
if(copied >= 3)
|
||||
{
|
||||
rsiCurrent = rsi[0];
|
||||
rsiPrevious = rsi[1];
|
||||
rsiPrevious2 = rsi[2];
|
||||
rsiInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
retryCount++;
|
||||
Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
if(!rsiInitialized)
|
||||
{
|
||||
// Don't fail initialization, just set default values
|
||||
rsiCurrent = 50.0;
|
||||
rsiPrevious = 50.0;
|
||||
rsiPrevious2 = 50.0;
|
||||
}
|
||||
|
||||
// Create panel
|
||||
CreatePanel();
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Release indicator handles
|
||||
IndicatorRelease(rsiHandle);
|
||||
|
||||
// Remove panel objects
|
||||
ObjectsDeleteAll(0, panelName);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close all trades for the current symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CloseAllTrades(string reason = "")
|
||||
{
|
||||
bool allClosed = true;
|
||||
int totalPositions = PositionsTotal();
|
||||
|
||||
if(totalPositions == 0)
|
||||
return true;
|
||||
|
||||
// Check if there are any positions with our magic number
|
||||
bool hasOurPositions = false;
|
||||
for(int i = 0; i < totalPositions; i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 123456)
|
||||
{
|
||||
hasOurPositions = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = totalPositions - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
// Try to close position with retry logic
|
||||
int retryCount = 0;
|
||||
bool positionClosed = false;
|
||||
|
||||
while(retryCount < 3 && !positionClosed)
|
||||
{
|
||||
if(trade.PositionClose(_Symbol))
|
||||
{
|
||||
isPositionOpen = false;
|
||||
positionClosed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = GetLastError();
|
||||
|
||||
// If error is 4756 (Trade disabled), wait longer before retry
|
||||
if(error == 4756)
|
||||
{
|
||||
Sleep(5000); // Wait 5 seconds before retry
|
||||
retryCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For other errors, break the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!positionClosed)
|
||||
{
|
||||
allClosed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allClosed;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if trading is allowed
|
||||
if(!IsTradingAllowed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we're in Asian session
|
||||
if(!IsAsianSession())
|
||||
{
|
||||
// Close all positions if outside Asian session and CloseOutsideSession is true
|
||||
if(CloseOutsideSession && !sessionCloseAttempted)
|
||||
{
|
||||
CloseAllTrades("Outside Asian session");
|
||||
sessionCloseAttempted = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the session close attempt flag when we enter Asian session
|
||||
sessionCloseAttempted = false;
|
||||
}
|
||||
|
||||
// Get current spread
|
||||
double spread = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
int spreadInPips = (int)(spread / _Point);
|
||||
|
||||
// Check if spread is too high
|
||||
if(spreadInPips > MaxSpread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get RSI values from bar data
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
|
||||
int copied = CopyBuffer(rsiHandle, 0, 0, 3, rsi);
|
||||
if(copied < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update RSI values
|
||||
rsiPrevious2 = rsiPrevious;
|
||||
rsiPrevious = rsiCurrent;
|
||||
rsiCurrent = rsi[0];
|
||||
|
||||
// Validate RSI values
|
||||
if(rsiCurrent == 0 || rsiPrevious == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for RSI crossovers
|
||||
CheckRSICrossover();
|
||||
|
||||
// Get current prices
|
||||
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
// Get position status
|
||||
string positionStatus = "None";
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
positionStatus = (posType == POSITION_TYPE_BUY) ? "Long" : "Short";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate stop loss and take profit levels
|
||||
double sl = 0;
|
||||
double tp = 0;
|
||||
|
||||
// Prepare crossover info for panel
|
||||
string crossInfo = "None";
|
||||
if(rsiCrossedOverbought) crossInfo = "Overbought";
|
||||
else if(rsiCrossedOversold) crossInfo = "Oversold";
|
||||
else if(rsiCrossedExitLevel) crossInfo = "Exit";
|
||||
|
||||
// Update panel
|
||||
UpdatePanel(rsiCurrent, positionStatus, spreadInPips, GetCurrentSession(), sl, tp, crossInfo);
|
||||
|
||||
// Check for open position
|
||||
bool hasOpenPosition = false;
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
hasOpenPosition = true;
|
||||
|
||||
// Get position details
|
||||
double positionProfit = PositionGetDouble(POSITION_PROFIT);
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
// Check for RSI exit if enabled
|
||||
if(UseRSIExit && rsiCrossedExitLevel)
|
||||
{
|
||||
bool shouldExit = false;
|
||||
|
||||
// For long positions, exit when RSI crosses above exit level
|
||||
if(posType == POSITION_TYPE_BUY && rsiCurrent >= RSIExitLevel && rsiPrevious < RSIExitLevel)
|
||||
{
|
||||
shouldExit = true;
|
||||
}
|
||||
// For short positions, exit when RSI crosses below exit level
|
||||
else if(posType == POSITION_TYPE_SELL && rsiCurrent <= RSIExitLevel && rsiPrevious > RSIExitLevel)
|
||||
{
|
||||
shouldExit = true;
|
||||
}
|
||||
|
||||
if(shouldExit)
|
||||
{
|
||||
CloseAllTrades("RSI Exit Crossover");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for timeout
|
||||
if(TimeCurrent() - positionOpenTime > MaxDuration * 3600)
|
||||
{
|
||||
CloseAllTrades("Timeout");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no position is open, look for entry signals based on RSI crossover
|
||||
if(!hasOpenPosition)
|
||||
{
|
||||
// Place buy order if RSI crosses below oversold level (oversold crossover)
|
||||
if(rsiCrossedOversold)
|
||||
{
|
||||
double sl = UseStopLoss ? currentBid - StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentBid + TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl >= currentBid)
|
||||
return;
|
||||
if(UseTakeProfit && tp <= currentBid)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place buy order using CTrade
|
||||
if(trade.Buy(MaxLotSize, _Symbol, currentAsk, sl, tp, "RSI Oversold Crossover Buy"))
|
||||
{
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentAsk;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
// Place sell order if RSI crosses above overbought level (overbought crossover)
|
||||
else if(rsiCrossedOverbought)
|
||||
{
|
||||
double sl = UseStopLoss ? currentAsk + StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentAsk - TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl <= currentAsk)
|
||||
return;
|
||||
if(UseTakeProfit && tp >= currentAsk)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place sell order using CTrade
|
||||
if(trade.Sell(MaxLotSize, _Symbol, currentBid, sl, tp, "RSI Overbought Crossover Sell"))
|
||||
{
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentBid;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 250 KiB |
@@ -5,7 +5,7 @@
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property version "1.01"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include "../_united/MagicNumberHelpers.mqh"
|
||||
@@ -92,6 +92,8 @@ void OnTick()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
// Check for existing position
|
||||
CheckExistingPosition();
|
||||
@@ -120,6 +122,18 @@ bool UpdateRSI()
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -272,20 +286,22 @@ void OpenSellPosition()
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
// Close position using helper function that verifies symbol AND magic number
|
||||
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
// Position doesn't exist or wrong magic number - reset tracking anyway
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD: close failed (will retry on next bar). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DeepMarkovRegimeModel.mqh |
|
||||
//| Hierarchical latent Markov stack + online regime-conditioned |
|
||||
//| RSI parameter blending and self-tuning from trade feedback. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026"
|
||||
#property strict
|
||||
|
||||
#define DMR_NUM_STATES 4
|
||||
|
||||
void DMR_NormalizePi(double &p[])
|
||||
{
|
||||
double s = 0.0;
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
s += p[i];
|
||||
if(s <= 0.0)
|
||||
{
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
p[j] = 1.0 / DMR_NUM_STATES;
|
||||
return;
|
||||
}
|
||||
for(int k = 0; k < DMR_NUM_STATES; k++)
|
||||
p[k] /= s;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Two-level "deep" Markov: macro volatility x micro RSI momentum |
|
||||
//| Combined state s in {0..3} = macro*2 + micro. |
|
||||
//| Belief filtered each bar; transitions learned online. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDeepMarkovRegimeModel
|
||||
{
|
||||
private:
|
||||
int m_seed;
|
||||
double m_learning_trans; // transition matrix EMA
|
||||
double m_learning_emit; // emission center EMA
|
||||
double m_learning_param; // per-state param nudge on wins
|
||||
double m_penalty_param; // nudge on losses
|
||||
|
||||
// Forward belief pi(s), row-stochastic T[s_prev][s_next]
|
||||
double m_pi[DMR_NUM_STATES];
|
||||
double m_T[DMR_NUM_STATES][DMR_NUM_STATES];
|
||||
|
||||
// Gaussian emission centers in feature space (3D): RSI/100, dRSI norm, ATR ratio
|
||||
double m_center[DMR_NUM_STATES][3];
|
||||
double m_emit_sigma; // shared diagonal sigma^2 for simplicity
|
||||
|
||||
// Per-state RSI strategy parameters (learned offsets around base inputs)
|
||||
double m_d_overbought[DMR_NUM_STATES];
|
||||
double m_d_oversold[DMR_NUM_STATES];
|
||||
double m_d_target_buy[DMR_NUM_STATES];
|
||||
double m_d_target_sell[DMR_NUM_STATES];
|
||||
double m_d_bars_scale[DMR_NUM_STATES]; // multiplicative around base BarsToWait
|
||||
|
||||
double m_base_overbought;
|
||||
double m_base_oversold;
|
||||
double m_base_target_buy;
|
||||
double m_base_target_sell;
|
||||
int m_base_bars_wait;
|
||||
|
||||
void NormalizePi()
|
||||
{
|
||||
DMR_NormalizePi(m_pi);
|
||||
}
|
||||
|
||||
void RowNormalizeT()
|
||||
{
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
double row = 0.0;
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
row += m_T[i][j];
|
||||
if(row <= 0.0)
|
||||
{
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[i][j] = 1.0 / DMR_NUM_STATES;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[i][j] /= row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double FeatureDist2(const double f0, const double f1, const double f2, const int state) const
|
||||
{
|
||||
double d0 = f0 - m_center[state][0];
|
||||
double d1 = f1 - m_center[state][1];
|
||||
double d2 = f2 - m_center[state][2];
|
||||
return d0 * d0 + d1 * d1 + d2 * d2;
|
||||
}
|
||||
|
||||
static double Clamp(const double x, const double lo, const double hi)
|
||||
{
|
||||
if(x < lo) return lo;
|
||||
if(x > hi) return hi;
|
||||
return x;
|
||||
}
|
||||
|
||||
public:
|
||||
CDeepMarkovRegimeModel()
|
||||
{
|
||||
m_seed = 0;
|
||||
m_learning_trans = 0.05;
|
||||
m_learning_emit = 0.02;
|
||||
m_learning_param = 0.03;
|
||||
m_penalty_param = 0.015;
|
||||
m_emit_sigma = 0.35;
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
m_pi[i] = 1.0 / DMR_NUM_STATES;
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[i][j] = (i == j) ? 0.55 : 0.15;
|
||||
m_d_overbought[i] = 0.0;
|
||||
m_d_oversold[i] = 0.0;
|
||||
m_d_target_buy[i] = 0.0;
|
||||
m_d_target_sell[i] = 0.0;
|
||||
m_d_bars_scale[i] = 1.0;
|
||||
// Spread default emission prototypes across feature cube corners
|
||||
m_center[i][0] = ((i & 1) != 0) ? 0.75 : 0.35;
|
||||
m_center[i][1] = ((i & 2) != 0) ? 0.6 : 0.25;
|
||||
m_center[i][2] = (double)(i % 3) * 0.25 + 0.2;
|
||||
}
|
||||
RowNormalizeT();
|
||||
}
|
||||
|
||||
void SetLearningRates(const double lr_trans, const double lr_emit, const double lr_win, const double lr_loss)
|
||||
{
|
||||
m_learning_trans = lr_trans;
|
||||
m_learning_emit = lr_emit;
|
||||
m_learning_param = lr_win;
|
||||
m_penalty_param = lr_loss;
|
||||
}
|
||||
|
||||
void SetBaseThresholds(const double ob, const double os, const double tb, const double ts, const int bars_wait)
|
||||
{
|
||||
m_base_overbought = ob;
|
||||
m_base_oversold = os;
|
||||
m_base_target_buy = tb;
|
||||
m_base_target_sell = ts;
|
||||
m_base_bars_wait = bars_wait;
|
||||
}
|
||||
|
||||
void SetSeed(const int seed) { m_seed = seed; }
|
||||
|
||||
// f0: RSI/100, f1: tanh-like scaled delta RSI, f2: ATR short/long ratio capped
|
||||
void Update(const double f0, const double f1, const double f2)
|
||||
{
|
||||
double emit[DMR_NUM_STATES];
|
||||
double max_ll = -1.0e100;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
{
|
||||
double d2 = FeatureDist2(f0, f1, f2, s);
|
||||
emit[s] = MathExp(-0.5 * d2 / (m_emit_sigma * m_emit_sigma + 1.0e-12));
|
||||
if(emit[s] > max_ll) max_ll = emit[s];
|
||||
}
|
||||
// numerical safety
|
||||
for(int s2 = 0; s2 < DMR_NUM_STATES; s2++)
|
||||
if(emit[s2] != emit[s2] || emit[s2] < 1.0e-12)
|
||||
emit[s2] = 1.0e-12;
|
||||
|
||||
double pi_new[DMR_NUM_STATES];
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
{
|
||||
double sum = 0.0;
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
sum += m_pi[i] * m_T[i][j];
|
||||
pi_new[j] = sum * emit[j];
|
||||
}
|
||||
DMR_NormalizePi(pi_new);
|
||||
|
||||
int imax_prev = ArgMaxPi();
|
||||
int imax_new = 0;
|
||||
double best = pi_new[0];
|
||||
for(int j = 1; j < DMR_NUM_STATES; j++)
|
||||
if(pi_new[j] > best)
|
||||
{
|
||||
best = pi_new[j];
|
||||
imax_new = j;
|
||||
}
|
||||
|
||||
// Online transition nudge toward observed edge imax_prev -> imax_new
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[imax_prev][j] *= (1.0 - m_learning_trans);
|
||||
m_T[imax_prev][imax_new] += m_learning_trans;
|
||||
RowNormalizeT();
|
||||
|
||||
// Pull emission center of dominant new state toward observation
|
||||
for(int d = 0; d < 3; d++)
|
||||
{
|
||||
double obs[3] = {f0, f1, f2};
|
||||
m_center[imax_new][d] = (1.0 - m_learning_emit) * m_center[imax_new][d] + m_learning_emit * obs[d];
|
||||
}
|
||||
|
||||
for(int k = 0; k < DMR_NUM_STATES; k++)
|
||||
m_pi[k] = pi_new[k];
|
||||
NormalizePi();
|
||||
}
|
||||
|
||||
int ArgMaxPi() const
|
||||
{
|
||||
int idx = 0;
|
||||
double best = m_pi[0];
|
||||
for(int i = 1; i < DMR_NUM_STATES; i++)
|
||||
if(m_pi[i] > best)
|
||||
{
|
||||
best = m_pi[i];
|
||||
idx = i;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
double Belief(const int s) const
|
||||
{
|
||||
if(s < 0 || s >= DMR_NUM_STATES) return 0.0;
|
||||
return m_pi[s];
|
||||
}
|
||||
|
||||
// Blended effective thresholds (self-optimized offsets)
|
||||
double EffectiveOverbought() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_overbought + m_d_overbought[s]);
|
||||
return Clamp(v, 50.0, 95.0);
|
||||
}
|
||||
|
||||
double EffectiveOversold() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_oversold + m_d_oversold[s]);
|
||||
return Clamp(v, 5.0, 50.0);
|
||||
}
|
||||
|
||||
double EffectiveTargetBuy() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_target_buy + m_d_target_buy[s]);
|
||||
return Clamp(v, 55.0, 99.0);
|
||||
}
|
||||
|
||||
double EffectiveTargetSell() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_target_sell + m_d_target_sell[s]);
|
||||
return Clamp(v, 1.0, 50.0);
|
||||
}
|
||||
|
||||
int EffectiveBarsToWait() const
|
||||
{
|
||||
double acc = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
acc += m_pi[s] * m_d_bars_scale[s];
|
||||
acc = Clamp(acc, 0.5, 2.0);
|
||||
int b = (int)MathRound((double)m_base_bars_wait * acc);
|
||||
return (int)Clamp((double)b, 1.0, 20.0);
|
||||
}
|
||||
|
||||
// Reinforce or soften parameters for the regime active at entry
|
||||
void OnTradeClosed(const int dominant_state_at_entry, const double profit_money)
|
||||
{
|
||||
if(dominant_state_at_entry < 0 || dominant_state_at_entry >= DMR_NUM_STATES)
|
||||
return;
|
||||
const int s = dominant_state_at_entry;
|
||||
const double mag = MathMin(1.0, MathAbs(profit_money) / 100.0 + 0.2);
|
||||
if(profit_money > 0.0)
|
||||
{
|
||||
// Slightly widen capture: push targets outward in favorable direction
|
||||
m_d_target_buy[s] += m_learning_param * mag * 0.5;
|
||||
m_d_target_sell[s] -= m_learning_param * mag * 0.5;
|
||||
m_d_overbought[s] += m_learning_param * mag * 0.25;
|
||||
m_d_oversold[s] -= m_learning_param * mag * 0.25;
|
||||
m_d_bars_scale[s] += m_learning_param * 0.05 * mag;
|
||||
}
|
||||
else if(profit_money < 0.0)
|
||||
{
|
||||
// Tighten: mean-revert offsets toward 0 and shorten patience
|
||||
m_d_target_buy[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_target_sell[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_overbought[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_oversold[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_bars_scale[s] -= m_penalty_param * 0.05 * mag;
|
||||
}
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
m_d_overbought[i] = Clamp(m_d_overbought[i], -15.0, 15.0);
|
||||
m_d_oversold[i] = Clamp(m_d_oversold[i], -15.0, 15.0);
|
||||
m_d_target_buy[i] = Clamp(m_d_target_buy[i], -20.0, 20.0);
|
||||
m_d_target_sell[i] = Clamp(m_d_target_sell[i], -20.0, 20.0);
|
||||
m_d_bars_scale[i] = Clamp(m_d_bars_scale[i], 0.5, 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
string DebugStateLine() const
|
||||
{
|
||||
string t = StringFormat("DMR pi=[%.2f,%.2f,%.2f,%.2f] OB=%.1f OS=%.1f TB=%.1f TS=%.1f BW=%d",
|
||||
m_pi[0], m_pi[1], m_pi[2], m_pi[3],
|
||||
EffectiveOverbought(), EffectiveOversold(),
|
||||
EffectiveTargetBuy(), EffectiveTargetSell(),
|
||||
EffectiveBarsToWait());
|
||||
return t;
|
||||
}
|
||||
|
||||
bool SaveToGlobals(const string prefix) const
|
||||
{
|
||||
string p = prefix + IntegerToString(m_seed) + "_";
|
||||
GlobalVariableSet(p + "pi0", m_pi[0]);
|
||||
GlobalVariableSet(p + "pi1", m_pi[1]);
|
||||
GlobalVariableSet(p + "pi2", m_pi[2]);
|
||||
GlobalVariableSet(p + "pi3", m_pi[3]);
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
GlobalVariableSet(p + "dob" + IntegerToString(i), m_d_overbought[i]);
|
||||
GlobalVariableSet(p + "dos" + IntegerToString(i), m_d_oversold[i]);
|
||||
GlobalVariableSet(p + "dtb" + IntegerToString(i), m_d_target_buy[i]);
|
||||
GlobalVariableSet(p + "dts" + IntegerToString(i), m_d_target_sell[i]);
|
||||
GlobalVariableSet(p + "dbs" + IntegerToString(i), m_d_bars_scale[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadFromGlobals(const string prefix)
|
||||
{
|
||||
string p = prefix + IntegerToString(m_seed) + "_";
|
||||
if(!GlobalVariableCheck(p + "pi0"))
|
||||
return false;
|
||||
m_pi[0] = GlobalVariableGet(p + "pi0");
|
||||
m_pi[1] = GlobalVariableGet(p + "pi1");
|
||||
m_pi[2] = GlobalVariableGet(p + "pi2");
|
||||
m_pi[3] = GlobalVariableGet(p + "pi3");
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
m_d_overbought[i] = GlobalVariableGet(p + "dob" + IntegerToString(i));
|
||||
m_d_oversold[i] = GlobalVariableGet(p + "dos" + IntegerToString(i));
|
||||
m_d_target_buy[i] = GlobalVariableGet(p + "dtb" + IntegerToString(i));
|
||||
m_d_target_sell[i] = GlobalVariableGet(p + "dts" + IntegerToString(i));
|
||||
m_d_bars_scale[i] = GlobalVariableGet(p + "dbs" + IntegerToString(i));
|
||||
}
|
||||
NormalizePi();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,157 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MagicNumberHelpers.mqh |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select position by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionSelectByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelect(symbol))
|
||||
return false;
|
||||
|
||||
if(PositionGetInteger(POSITION_MAGIC) != magic_number)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetTicket(i) > 0)
|
||||
{
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select position by ticket and verify magic number and symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionSelectByTicketAndMagic(ulong ticket, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
return false;
|
||||
|
||||
return (PositionGetInteger(POSITION_MAGIC) == magic_number);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select position by ticket and verify symbol, magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionSelectByTicketSymbolAndMagic(ulong ticket, string symbol, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
return false;
|
||||
|
||||
return (PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if position exists with correct magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionExistsByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
return PositionSelectByMagic(symbol, magic_number);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get position ticket by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
ulong GetPositionTicketByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if(ticket > 0)
|
||||
{
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
return ticket;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close position by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
bool ClosePositionByMagic(CTrade &trade_obj, string symbol, ulong magic_number)
|
||||
{
|
||||
ulong ticket = GetPositionTicketByMagic(symbol, magic_number);
|
||||
if(ticket == 0)
|
||||
return false;
|
||||
|
||||
return trade_obj.PositionClose(ticket);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Modify position by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
bool ModifyPositionByMagic(CTrade &trade_obj, string symbol, ulong magic_number,
|
||||
double sl, double tp)
|
||||
{
|
||||
ulong ticket = GetPositionTicketByMagic(symbol, magic_number);
|
||||
if(ticket == 0)
|
||||
return false;
|
||||
|
||||
return trade_obj.PositionModify(ticket, sl, tp);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get position profit by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetPositionProfitByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByMagic(symbol, magic_number))
|
||||
return 0.0;
|
||||
|
||||
return PositionGetDouble(POSITION_PROFIT);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get position type by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_POSITION_TYPE GetPositionTypeByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByMagic(symbol, magic_number))
|
||||
return WRONG_VALUE;
|
||||
|
||||
return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Count positions by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
int CountPositionsByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
int count = 0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if(ticket > 0)
|
||||
{
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,350 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalpingXAUUSD_DeepMarkov.mq5 |
|
||||
//| RSI scalping with online deep Markov regime filter + self-tune. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026"
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "MagicNumberHelpers.mqh"
|
||||
#include "DeepMarkovRegimeModel.mqh"
|
||||
|
||||
//--- Input parameters
|
||||
input group "=== Chart / RSI ==="
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
|
||||
input int RSI_Period = 14;
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE;
|
||||
|
||||
input group "=== Base RSI levels (Markov blends & learns offsets) ==="
|
||||
input double RSI_Overbought = 71;
|
||||
input double RSI_Oversold = 57;
|
||||
input double RSI_Target_Buy = 80;
|
||||
input double RSI_Target_Sell = 57;
|
||||
input int BarsToWait = 4;
|
||||
|
||||
input group "=== Execution ==="
|
||||
input double LotSize = 0.1;
|
||||
input int MagicNumber = 129102316;
|
||||
input int Slippage = 3;
|
||||
|
||||
input group "=== Deep Markov self-optimization ==="
|
||||
input double DMR_LearnTransition = 0.05;
|
||||
input double DMR_LearnEmission = 0.02;
|
||||
input double DMR_LearnWin = 0.03;
|
||||
input double DMR_LearnLoss = 0.015;
|
||||
input bool DMR_PersistGlobals = true;
|
||||
input string DMR_GlobalPrefix = "DMR_XAU_";
|
||||
input bool DMR_LogEachBar = false;
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
CDeepMarkovRegimeModel g_dm;
|
||||
|
||||
int rsi_handle;
|
||||
int atr_fast_handle;
|
||||
int atr_slow_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
double atr_fast, atr_slow;
|
||||
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
int entry_regime = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
return(INIT_FAILED);
|
||||
|
||||
atr_fast_handle = iATR(_Symbol, TimeFrame, 8);
|
||||
atr_slow_handle = iATR(_Symbol, TimeFrame, 34);
|
||||
if(atr_fast_handle == INVALID_HANDLE || atr_slow_handle == INVALID_HANDLE)
|
||||
return(INIT_FAILED);
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
|
||||
g_dm.SetSeed(MagicNumber);
|
||||
g_dm.SetLearningRates(DMR_LearnTransition, DMR_LearnEmission, DMR_LearnWin, DMR_LearnLoss);
|
||||
g_dm.SetBaseThresholds(RSI_Overbought, RSI_Oversold, RSI_Target_Buy, RSI_Target_Sell, BarsToWait);
|
||||
|
||||
if(DMR_PersistGlobals)
|
||||
{
|
||||
if(g_dm.LoadFromGlobals(DMR_GlobalPrefix))
|
||||
Print("RSIScalpingXAUUSD_DeepMarkov: loaded persisted Markov state from globals.");
|
||||
}
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(DMR_PersistGlobals)
|
||||
g_dm.SaveToGlobals(DMR_GlobalPrefix);
|
||||
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
if(atr_fast_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(atr_fast_handle);
|
||||
if(atr_slow_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(atr_slow_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 5)
|
||||
return;
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
return;
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
if(!UpdateRSI())
|
||||
return;
|
||||
|
||||
if(!UpdateATR())
|
||||
return;
|
||||
|
||||
const double f0 = rsi_current / 100.0;
|
||||
const double dr = rsi_current - rsi_prev;
|
||||
const double f1 = MathTanh(dr / 10.0) * 0.5 + 0.5;
|
||||
double ratio = 1.0;
|
||||
if(atr_slow > 1.0e-12)
|
||||
ratio = atr_fast / atr_slow;
|
||||
if(ratio < 0.15)
|
||||
ratio = 0.15;
|
||||
if(ratio > 2.5)
|
||||
ratio = 2.5;
|
||||
const double f2 = ratio / 2.5;
|
||||
|
||||
g_dm.Update(f0, f1, f2);
|
||||
|
||||
if(DMR_LogEachBar)
|
||||
Print(g_dm.DebugStateLine());
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
CheckExistingPosition();
|
||||
|
||||
if(!position_open && !PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
CheckEntrySignals();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
return false;
|
||||
|
||||
rsi_current = rsi_buffer[0];
|
||||
rsi_prev = rsi_buffer[1];
|
||||
rsi_two_bars_ago = rsi_buffer[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateATR()
|
||||
{
|
||||
double af[], as[];
|
||||
ArrayResize(af, 1);
|
||||
ArrayResize(as, 1);
|
||||
ArraySetAsSeries(af, true);
|
||||
ArraySetAsSeries(as, true);
|
||||
if(CopyBuffer(atr_fast_handle, 0, 0, 1, af) < 1)
|
||||
return false;
|
||||
if(CopyBuffer(atr_slow_handle, 0, 0, 1, as) < 1)
|
||||
return false;
|
||||
atr_fast = af[0];
|
||||
atr_slow = as[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
entry_regime = g_dm.ArgMaxPi();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
double EffectiveOverbought() { return g_dm.EffectiveOverbought(); }
|
||||
double EffectiveOversold() { return g_dm.EffectiveOversold(); }
|
||||
double EffectiveTargetBuy() { return g_dm.EffectiveTargetBuy(); }
|
||||
double EffectiveTargetSell() { return g_dm.EffectiveTargetSell(); }
|
||||
int EffectiveBarsToWait() { return g_dm.EffectiveBarsToWait(); }
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
return;
|
||||
|
||||
if(!PositionSelectByTicketAndMagic((ulong)position_ticket, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const double ob = EffectiveOverbought();
|
||||
const double os = EffectiveOversold();
|
||||
const double tb = EffectiveTargetBuy();
|
||||
const double ts = EffectiveTargetSell();
|
||||
const int bw = EffectiveBarsToWait();
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_current < os)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= bw)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
if(rsi_current >= tb)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_current > ob)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= bw)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
if(rsi_current <= ts)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
const double os = EffectiveOversold();
|
||||
const double ob = EffectiveOverbought();
|
||||
|
||||
if(rsi_two_bars_ago <= os && rsi_prev > os)
|
||||
OpenBuyPosition();
|
||||
|
||||
if(rsi_two_bars_ago >= ob && rsi_prev < ob)
|
||||
OpenSellPosition();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
entry_regime = g_dm.ArgMaxPi();
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI DM Buy"))
|
||||
{
|
||||
ulong pt = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)pt;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
entry_regime = g_dm.ArgMaxPi();
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI DM Sell"))
|
||||
{
|
||||
ulong pt = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)pt;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
double profit = 0.0;
|
||||
if(PositionSelectByTicket(position_ticket))
|
||||
profit = PositionGetDouble(POSITION_PROFIT);
|
||||
|
||||
const int regime = entry_regime;
|
||||
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
g_dm.OnTradeClosed(regime, profit);
|
||||
return;
|
||||
}
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
g_dm.OnTradeClosed(regime, profit);
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD_DeepMarkov: close failed (will retry). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalpingXAUUSD_PlusHours.mq5 |
|
||||
//| Same logic as RSIScalpingXAUUSD + trading session filter |
|
||||
//| (server time), day-of-week filter, and optional close-all when |
|
||||
//| outside allowed hours/days |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include "../_united/MagicNumberHelpers.mqh"
|
||||
|
||||
input group "=== RSI (same as RSIScalpingXAUUSD) ==="
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
|
||||
input int RSI_Period = 14;
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE;
|
||||
input double RSI_Overbought = 71;
|
||||
input double RSI_Oversold = 57;
|
||||
input double RSI_Target_Buy = 80;
|
||||
input double RSI_Target_Sell = 57;
|
||||
input int BarsToWait = 4;
|
||||
input double LotSize = 0.1;
|
||||
input int MagicNumber = 129102317;
|
||||
input int Slippage = 3;
|
||||
|
||||
input group "=== Trading hours (broker server time) ==="
|
||||
input bool InpUseTradingHours = true;
|
||||
input int InpTradeHourStart = 8;
|
||||
input int InpTradeHourEnd = 22;
|
||||
input bool InpCloseOutsideTradingHours = true;
|
||||
|
||||
input group "=== Trading days (broker server time) ==="
|
||||
input bool InpUseTradingDays = true;
|
||||
input bool InpTradeMonday = true;
|
||||
input bool InpTradeTuesday = true;
|
||||
input bool InpTradeWednesday = true;
|
||||
input bool InpTradeThursday = true;
|
||||
input bool InpTradeFriday = true;
|
||||
input bool InpTradeSaturday = true;
|
||||
input bool InpTradeSunday = true;
|
||||
input bool InpCloseOutsideTradingDays = true;
|
||||
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
bool IsWithinTradingHours()
|
||||
{
|
||||
if(!InpUseTradingHours)
|
||||
return true;
|
||||
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(TimeCurrent(), dt);
|
||||
const int h = dt.hour;
|
||||
const int hs = MathMax(0, MathMin(23, InpTradeHourStart));
|
||||
const int he = MathMax(0, MathMin(23, InpTradeHourEnd));
|
||||
|
||||
if(hs == he)
|
||||
return true;
|
||||
|
||||
if(hs < he)
|
||||
return (h >= hs && h < he);
|
||||
|
||||
return (h >= hs || h < he);
|
||||
}
|
||||
|
||||
bool IsTradingDayAllowed()
|
||||
{
|
||||
if(!InpUseTradingDays)
|
||||
return true;
|
||||
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(TimeCurrent(), dt);
|
||||
switch(dt.day_of_week)
|
||||
{
|
||||
case 0: return InpTradeSunday;
|
||||
case 1: return InpTradeMonday;
|
||||
case 2: return InpTradeTuesday;
|
||||
case 3: return InpTradeWednesday;
|
||||
case 4: return InpTradeThursday;
|
||||
case 5: return InpTradeFriday;
|
||||
case 6: return InpTradeSaturday;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
return(INIT_FAILED);
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
}
|
||||
|
||||
void OnTick()
|
||||
{
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
|
||||
return;
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
return;
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
if(!UpdateRSI())
|
||||
return;
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
const bool inHours = IsWithinTradingHours();
|
||||
const bool inDays = IsTradingDayAllowed();
|
||||
const bool inSession = inHours && inDays;
|
||||
|
||||
if(position_open && !inSession &&
|
||||
((InpUseTradingHours && InpCloseOutsideTradingHours && !inHours) ||
|
||||
(InpUseTradingDays && InpCloseOutsideTradingDays && !inDays)))
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
|
||||
CheckExistingPosition();
|
||||
|
||||
if(!position_open && !PositionExistsByMagic(_Symbol, (ulong)MagicNumber) && inSession)
|
||||
CheckEntrySignals();
|
||||
}
|
||||
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
return false;
|
||||
|
||||
rsi_current = rsi_buffer[0];
|
||||
rsi_prev = rsi_buffer[1];
|
||||
rsi_two_bars_ago = rsi_buffer[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
return;
|
||||
|
||||
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
OpenBuyPosition();
|
||||
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
OpenSellPosition();
|
||||
}
|
||||
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Hours Buy"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)t;
|
||||
position_open = (position_ticket != 0);
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Hours Sell"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)t;
|
||||
position_open = (position_ticket != 0);
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ClosePosition()
|
||||
{
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD_PlusHours: close failed (will retry). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalpingXAUUSD_Trailing.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.06"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include "../_united/MagicNumberHelpers.mqh"
|
||||
|
||||
//--- Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
||||
input int RSI_Period = 14; // RSI Period
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE; // RSI Applied Price
|
||||
input double RSI_Overbought = 71; // RSI Overbought Level
|
||||
input double RSI_Oversold = 57; // RSI Oversold Level
|
||||
input double RSI_Target_Buy = 80; // RSI Target for Buy Exit
|
||||
input double RSI_Target_Sell = 57; // RSI Target for Sell Exit
|
||||
input int BarsToWait = 4; // Bars to wait when RSI goes against position
|
||||
input bool UseRSI_StopLoss = true; // Close on RSI stop (separate timeframe below)
|
||||
input ENUM_TIMEFRAMES RSI_StopLoss_TimeFrame = PERIOD_H1; // RSI timeframe for stop-loss only
|
||||
input double RSI_StopLoss_BuyBelow = 30; // Close buy when stop-timeframe RSI drops below this
|
||||
input double RSI_StopLoss_SellAbove = 70; // Close sell when stop-timeframe RSI rises above this
|
||||
input double LotSize = 0.1; // Lot Size
|
||||
input int MagicNumber = 129102316; // Magic Number (distinct from non-trailing EA)
|
||||
input int Slippage = 3; // Slippage in points
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
int rsi_stoploss_handle = INVALID_HANDLE;
|
||||
double rsi_buffer[];
|
||||
double rsi_stoploss_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
double rsi_stoploss_current = 0.0;
|
||||
MqlTick rsi_stoploss_last_tick;
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
rsi_stoploss_handle = iRSI(_Symbol, RSI_StopLoss_TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_stoploss_handle == INVALID_HANDLE)
|
||||
{
|
||||
IndicatorRelease(rsi_handle);
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
ArraySetAsSeries(rsi_stoploss_buffer, true);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
if(rsi_stoploss_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_stoploss_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
const int min_bars = RSI_Period + 2;
|
||||
if(position_open)
|
||||
{
|
||||
if(UseRSI_StopLoss && Bars(_Symbol, RSI_StopLoss_TimeFrame) >= min_bars)
|
||||
{
|
||||
if(UpdateRSI_StopLoss())
|
||||
CheckRSIStopLossClose();
|
||||
}
|
||||
}
|
||||
|
||||
if(Bars(_Symbol, TimeFrame) < min_bars)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
if(!UpdateRSI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
CheckExistingPosition();
|
||||
|
||||
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||
{
|
||||
CheckEntrySignals();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update RSI values |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rsi_current = rsi_buffer[0];
|
||||
rsi_prev = rsi_buffer[1];
|
||||
rsi_two_bars_ago = rsi_buffer[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stop-loss RSI (RSI_StopLoss_TimeFrame) |
|
||||
//| Uses latest MqlTick before CopyBuffer so RSI matches current quote. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI_StopLoss()
|
||||
{
|
||||
if(rsi_stoploss_handle == INVALID_HANDLE)
|
||||
return false;
|
||||
if(!SymbolInfoTick(_Symbol, rsi_stoploss_last_tick))
|
||||
return false;
|
||||
|
||||
int calc = BarsCalculated(rsi_stoploss_handle);
|
||||
if(calc <= 0)
|
||||
return false;
|
||||
|
||||
if(CopyBuffer(rsi_stoploss_handle, 0, 0, 1, rsi_stoploss_buffer) < 1)
|
||||
return false;
|
||||
rsi_stoploss_current = rsi_stoploss_buffer[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSI-based stop: RSI_StopLoss_TimeFrame series (independent of TimeFrame) |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckRSIStopLossClose()
|
||||
{
|
||||
if(!UseRSI_StopLoss || !position_open)
|
||||
return;
|
||||
|
||||
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_stoploss_current < RSI_StopLoss_BuyBelow)
|
||||
ClosePosition();
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_stoploss_current > RSI_StopLoss_SellAbove)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for entry signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
OpenBuyPosition();
|
||||
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
OpenSellPosition();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t != 0)
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t != 0)
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close current position |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD: close failed (will retry on next bar). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
//--- Input Parameters
|
||||
input group "=== Trading Settings ==="
|
||||
input string InpSymbol = "XAUUSD"; // Trading Symbol (set was tuned on BTCUSD)
|
||||
input string InpSymbol = "XAUUSD"; // Default gold; same numbers as secret_sauce.set (that file uses BTCUSD as symbol)
|
||||
input double InpLotSize = 0.1; // Lot Size (Profiles/Tester/secret_sauce.set)
|
||||
input int InpMagicNumber = 789012; // Magic Number
|
||||
input int InpSlippage = 10; // Slippage in points
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
; SuperEMA — defaults aligned with lab/EAs/SuperEMA.mq5 (v1.01)
|
||||
; Load from Strategy Tester → Inputs → context menu → Load
|
||||
;
|
||||
; === Market ===
|
||||
InpSymbol=
|
||||
InpTimeframe=15||15||0||49153||N
|
||||
InpLots=0.01||0.01||0.01||0.10||N
|
||||
InpSlippagePoints=55||20||5||120||Y
|
||||
InpMagic=940001||940001||1||9400010||N
|
||||
; === EMA (trend & structure) ===
|
||||
InpEmaFast=40||20||10||120||Y
|
||||
InpEmaMid=180||60||15||200||Y
|
||||
InpEmaSlow=125||100||25||400||Y
|
||||
InpEmaTrendBars=3||1||1||3||Y
|
||||
; === CCI ===
|
||||
InpCciPeriod=17||7||1||28||Y
|
||||
InpCciOverbought=80.0||80.0||10.0||140.0||Y
|
||||
InpCciOversold=-140.0||-140.0||10.0||-80.0||Y
|
||||
InpPullbackCciLookback=20||4||2||24||Y
|
||||
; === MACD (histogram = main - signal) ===
|
||||
InpMacdFast=14||8||2||20||Y
|
||||
InpMacdSlow=38||20||2||40||Y
|
||||
InpMacdSignal=9||5||1||15||Y
|
||||
; === Strategy ===
|
||||
InpEntryStyle=1||0||1||2||Y
|
||||
InpOneTradeOnly=true||false||0||true||N
|
||||
InpUseStructuralSL=false||false||0||true||Y
|
||||
InpSlBufferPoints=110.0||20.0||10.0||200.0||Y
|
||||
; === Exits (so trades do not run forever) ===
|
||||
InpExitOnTrendFlip=false||false||0||true||Y
|
||||
InpExitOnMacdFlip=false||false||0||true||Y
|
||||
InpExitOnCciZeroCross=true||false||0||true||Y
|
||||
InpMaxHoldingBars=168||48||24||480||Y
|
||||
InpExitBelowMidEma=false||false||0||true||Y
|
||||
; === Debug ===
|
||||
InpDebugLogs=false||false||0||true||N
|
||||
@@ -0,0 +1,448 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SuperEMA.mq5 |
|
||||
//| EMA + CCI + MACD histogram — trend filter, momentum confirmation |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
#property version "1.01"
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
enum ENUM_ENTRY_STYLE
|
||||
{
|
||||
ENTRY_CCIZERO_MACD = 0, // EMA trend + CCI crosses zero + MACD histogram agrees
|
||||
ENTRY_LAMBERT = 1, // EMA trend + CCI crosses ±100 + MACD histogram agrees
|
||||
ENTRY_PULLBACK = 2 // Uptrend: pullback to fast EMA + CCI was oversold + CCI crosses up through 0 + MACD > 0 (mirror for sells)
|
||||
};
|
||||
|
||||
input group "=== Market ==="
|
||||
input string InpSymbol = "";
|
||||
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_M15;
|
||||
input double InpLots = 0.01;
|
||||
input int InpSlippagePoints = 55;
|
||||
input int InpMagic = 940001;
|
||||
|
||||
input group "=== EMA (trend & structure) ==="
|
||||
input int InpEmaFast = 40;
|
||||
input int InpEmaMid = 180;
|
||||
input int InpEmaSlow = 125;
|
||||
input int InpEmaTrendBars = 3; // closed bar shift for EMA reads
|
||||
|
||||
input group "=== CCI ==="
|
||||
input int InpCciPeriod = 17;
|
||||
input double InpCciOverbought = 80.0;
|
||||
input double InpCciOversold = -140.0;
|
||||
input int InpPullbackCciLookback = 20; // bars to check prior CCI oversold/overbought
|
||||
|
||||
input group "=== MACD (histogram = main - signal) ==="
|
||||
input int InpMacdFast = 14;
|
||||
input int InpMacdSlow = 38;
|
||||
input int InpMacdSignal = 9;
|
||||
|
||||
input group "=== Strategy ==="
|
||||
input ENUM_ENTRY_STYLE InpEntryStyle = ENTRY_LAMBERT;
|
||||
input bool InpOneTradeOnly = true;
|
||||
input bool InpUseStructuralSL = false;
|
||||
input double InpSlBufferPoints = 110;
|
||||
|
||||
input group "=== Exits (so trades do not run forever) ==="
|
||||
input bool InpExitOnTrendFlip = false; // close when price vs slow EMA flips against position
|
||||
input bool InpExitOnMacdFlip = false; // close when MACD histogram flips against position
|
||||
input bool InpExitOnCciZeroCross = true; // long: CCI crosses below 0; short: CCI crosses above 0
|
||||
input int InpMaxHoldingBars = 168; // 0 = disabled (e.g. ~8 days M15)
|
||||
input bool InpExitBelowMidEma = false; // long: close if close < mid EMA (invalidation)
|
||||
|
||||
input group "=== Debug ==="
|
||||
input bool InpDebugLogs = false;
|
||||
|
||||
CTrade trade;
|
||||
datetime g_lastBarTime = 0;
|
||||
|
||||
string WorkSymbol()
|
||||
{
|
||||
return (InpSymbol == "" || InpSymbol == NULL) ? _Symbol : InpSymbol;
|
||||
}
|
||||
|
||||
void Log(const string s)
|
||||
{
|
||||
if(InpDebugLogs)
|
||||
Print("[SuperEMA] ", s);
|
||||
}
|
||||
|
||||
bool IsNewBar(const string sym, const ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
datetime t = iTime(sym, tf, 0);
|
||||
if(t <= 0 || t == g_lastBarTime)
|
||||
return false;
|
||||
g_lastBarTime = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
double EmaAt(const string sym, const ENUM_TIMEFRAMES tf, const int period, const int shift)
|
||||
{
|
||||
int h = iMA(sym, tf, period, 0, MODE_EMA, PRICE_CLOSE);
|
||||
if(h == INVALID_HANDLE)
|
||||
return 0.0;
|
||||
double b[1];
|
||||
if(CopyBuffer(h, 0, shift, 1, b) <= 0)
|
||||
{
|
||||
IndicatorRelease(h);
|
||||
return 0.0;
|
||||
}
|
||||
IndicatorRelease(h);
|
||||
return b[0];
|
||||
}
|
||||
|
||||
double CciAt(const string sym, const ENUM_TIMEFRAMES tf, const int period, const int shift)
|
||||
{
|
||||
int h = iCCI(sym, tf, period, PRICE_TYPICAL);
|
||||
if(h == INVALID_HANDLE)
|
||||
return 0.0;
|
||||
double b[1];
|
||||
if(CopyBuffer(h, 0, shift, 1, b) <= 0)
|
||||
{
|
||||
IndicatorRelease(h);
|
||||
return 0.0;
|
||||
}
|
||||
IndicatorRelease(h);
|
||||
return b[0];
|
||||
}
|
||||
|
||||
bool MacdHistAt(const string sym, const ENUM_TIMEFRAMES tf, const int fast, const int slow, const int signal, const int shift, double &hist)
|
||||
{
|
||||
int h = iMACD(sym, tf, fast, slow, signal, PRICE_CLOSE);
|
||||
if(h == INVALID_HANDLE)
|
||||
return false;
|
||||
double mainLine[1], sigLine[1];
|
||||
if(CopyBuffer(h, 0, shift, 1, mainLine) <= 0 || CopyBuffer(h, 1, shift, 1, sigLine) <= 0)
|
||||
{
|
||||
IndicatorRelease(h);
|
||||
return false;
|
||||
}
|
||||
IndicatorRelease(h);
|
||||
hist = mainLine[0] - sigLine[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TrendUp(const string sym, const int sh)
|
||||
{
|
||||
double c = iClose(sym, InpTimeframe, sh);
|
||||
double emaS = EmaAt(sym, InpTimeframe, InpEmaSlow, sh);
|
||||
return (emaS > 0.0 && c > emaS);
|
||||
}
|
||||
|
||||
bool TrendDown(const string sym, const int sh)
|
||||
{
|
||||
double c = iClose(sym, InpTimeframe, sh);
|
||||
double emaS = EmaAt(sym, InpTimeframe, InpEmaSlow, sh);
|
||||
return (emaS > 0.0 && c < emaS);
|
||||
}
|
||||
|
||||
bool CciCrossAboveZero(const string sym)
|
||||
{
|
||||
double c1 = CciAt(sym, InpTimeframe, InpCciPeriod, 1);
|
||||
double c2 = CciAt(sym, InpTimeframe, InpCciPeriod, 2);
|
||||
return (c2 <= 0.0 && c1 > 0.0);
|
||||
}
|
||||
|
||||
bool CciCrossBelowZero(const string sym)
|
||||
{
|
||||
double c1 = CciAt(sym, InpTimeframe, InpCciPeriod, 1);
|
||||
double c2 = CciAt(sym, InpTimeframe, InpCciPeriod, 2);
|
||||
return (c2 >= 0.0 && c1 < 0.0);
|
||||
}
|
||||
|
||||
bool CciCrossAbove100(const string sym)
|
||||
{
|
||||
double c1 = CciAt(sym, InpTimeframe, InpCciPeriod, 1);
|
||||
double c2 = CciAt(sym, InpTimeframe, InpCciPeriod, 2);
|
||||
return (c2 < InpCciOverbought && c1 > InpCciOverbought);
|
||||
}
|
||||
|
||||
bool CciCrossBelowMinus100(const string sym)
|
||||
{
|
||||
double c1 = CciAt(sym, InpTimeframe, InpCciPeriod, 1);
|
||||
double c2 = CciAt(sym, InpTimeframe, InpCciPeriod, 2);
|
||||
return (c2 > InpCciOversold && c1 < InpCciOversold);
|
||||
}
|
||||
|
||||
bool HadCciOversoldRecently(const string sym)
|
||||
{
|
||||
for(int i = 2; i <= InpPullbackCciLookback + 1; i++)
|
||||
{
|
||||
double v = CciAt(sym, InpTimeframe, InpCciPeriod, i);
|
||||
if(v <= InpCciOversold)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HadCciOverboughtRecently(const string sym)
|
||||
{
|
||||
for(int i = 2; i <= InpPullbackCciLookback + 1; i++)
|
||||
{
|
||||
double v = CciAt(sym, InpTimeframe, InpCciPeriod, i);
|
||||
if(v >= InpCciOverbought)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PullbackNearFastEmaLong(const string sym)
|
||||
{
|
||||
double emaF = EmaAt(sym, InpTimeframe, InpEmaFast, 1);
|
||||
double lo = iLow(sym, InpTimeframe, 1);
|
||||
if(emaF <= 0.0)
|
||||
return false;
|
||||
return (lo <= emaF + InpSlBufferPoints * _Point * 3.0);
|
||||
}
|
||||
|
||||
bool PullbackNearFastEmaShort(const string sym)
|
||||
{
|
||||
double emaF = EmaAt(sym, InpTimeframe, InpEmaFast, 1);
|
||||
double hi = iHigh(sym, InpTimeframe, 1);
|
||||
if(emaF <= 0.0)
|
||||
return false;
|
||||
return (hi >= emaF - InpSlBufferPoints * _Point * 3.0);
|
||||
}
|
||||
|
||||
int PositionsByMagic(const string sym, const int magic)
|
||||
{
|
||||
int n = 0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong t = PositionGetTicket(i);
|
||||
if(t == 0)
|
||||
continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) == sym && (int)PositionGetInteger(POSITION_MAGIC) == magic)
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void ComputeSLTP(const bool isBuy, const double entry, double &sl, double &tp)
|
||||
{
|
||||
const string sym = WorkSymbol();
|
||||
sl = 0.0;
|
||||
tp = 0.0;
|
||||
if(!InpUseStructuralSL)
|
||||
return;
|
||||
double emaM = EmaAt(sym, InpTimeframe, InpEmaMid, InpEmaTrendBars);
|
||||
double buf = InpSlBufferPoints * _Point;
|
||||
if(isBuy)
|
||||
sl = emaM - buf;
|
||||
else
|
||||
sl = emaM + buf;
|
||||
}
|
||||
|
||||
int BarsSinceOpen(const string sym, const datetime openTime)
|
||||
{
|
||||
if(openTime <= 0)
|
||||
return 0;
|
||||
int sh = iBarShift(sym, InpTimeframe, openTime, false);
|
||||
if(sh < 0)
|
||||
return 999999;
|
||||
return sh;
|
||||
}
|
||||
|
||||
void ClosePositionTicket(const ulong ticket, const string reason)
|
||||
{
|
||||
trade.SetExpertMagicNumber(InpMagic);
|
||||
if(trade.PositionClose(ticket))
|
||||
Log("Close: " + reason);
|
||||
}
|
||||
|
||||
void ManageSuperEMAExits(const string sym)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if(ticket == 0)
|
||||
continue;
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) != sym)
|
||||
continue;
|
||||
if((int)PositionGetInteger(POSITION_MAGIC) != InpMagic)
|
||||
continue;
|
||||
|
||||
ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
|
||||
|
||||
double h1 = 0.0;
|
||||
if(!MacdHistAt(sym, InpTimeframe, InpMacdFast, InpMacdSlow, InpMacdSignal, 1, h1))
|
||||
continue;
|
||||
|
||||
bool closeLong = false;
|
||||
bool closeShort = false;
|
||||
string reason = "";
|
||||
|
||||
if(InpMaxHoldingBars > 0)
|
||||
{
|
||||
int held = BarsSinceOpen(sym, openTime);
|
||||
if(held >= InpMaxHoldingBars)
|
||||
{
|
||||
if(ptype == POSITION_TYPE_BUY)
|
||||
closeLong = true;
|
||||
else
|
||||
closeShort = true;
|
||||
reason = "time stop (max bars)";
|
||||
}
|
||||
}
|
||||
|
||||
if(ptype == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(InpExitOnTrendFlip && TrendDown(sym, InpEmaTrendBars))
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "trend flip (below slow EMA)";
|
||||
}
|
||||
if(InpExitOnMacdFlip && h1 < 0.0)
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "MACD histogram < 0";
|
||||
}
|
||||
if(InpExitOnCciZeroCross && CciCrossBelowZero(sym))
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "CCI crossed below zero";
|
||||
}
|
||||
if(InpExitBelowMidEma)
|
||||
{
|
||||
double c = iClose(sym, InpTimeframe, 1);
|
||||
double emaM = EmaAt(sym, InpTimeframe, InpEmaMid, 1);
|
||||
if(emaM > 0.0 && c < emaM)
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "close below mid EMA";
|
||||
}
|
||||
}
|
||||
if(closeLong)
|
||||
ClosePositionTicket(ticket, reason);
|
||||
}
|
||||
else if(ptype == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(InpExitOnTrendFlip && TrendUp(sym, InpEmaTrendBars))
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "trend flip (above slow EMA)";
|
||||
}
|
||||
if(InpExitOnMacdFlip && h1 > 0.0)
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "MACD histogram > 0";
|
||||
}
|
||||
if(InpExitOnCciZeroCross && CciCrossAboveZero(sym))
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "CCI crossed above zero";
|
||||
}
|
||||
if(InpExitBelowMidEma)
|
||||
{
|
||||
double c = iClose(sym, InpTimeframe, 1);
|
||||
double emaM = EmaAt(sym, InpTimeframe, InpEmaMid, 1);
|
||||
if(emaM > 0.0 && c > emaM)
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "close above mid EMA";
|
||||
}
|
||||
}
|
||||
if(closeShort)
|
||||
ClosePositionTicket(ticket, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
string sym = WorkSymbol();
|
||||
if(!SymbolSelect(sym, true))
|
||||
{
|
||||
Print("SuperEMA: cannot select symbol ", sym);
|
||||
return INIT_FAILED;
|
||||
}
|
||||
trade.SetExpertMagicNumber(InpMagic);
|
||||
trade.SetDeviationInPoints(InpSlippagePoints);
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
void OnTick()
|
||||
{
|
||||
string sym = WorkSymbol();
|
||||
if(_Symbol != sym)
|
||||
{
|
||||
static datetime lastLog = 0;
|
||||
datetime tb = iTime(_Symbol, PERIOD_M1, 0);
|
||||
if(tb != lastLog && InpDebugLogs)
|
||||
{
|
||||
lastLog = tb;
|
||||
Log("Chart symbol differs from WorkSymbol; attach to " + sym + " or set InpSymbol empty.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!IsNewBar(sym, InpTimeframe))
|
||||
return;
|
||||
|
||||
// Exits must run every bar; do not skip when a position exists (otherwise trades never close with SL=0/TP=0).
|
||||
ManageSuperEMAExits(sym);
|
||||
|
||||
if(InpOneTradeOnly && PositionsByMagic(sym, InpMagic) > 0)
|
||||
return;
|
||||
|
||||
const int sh = InpEmaTrendBars;
|
||||
double h1 = 0.0, h2 = 0.0;
|
||||
if(!MacdHistAt(sym, InpTimeframe, InpMacdFast, InpMacdSlow, InpMacdSignal, 1, h1) ||
|
||||
!MacdHistAt(sym, InpTimeframe, InpMacdFast, InpMacdSlow, InpMacdSignal, 2, h2))
|
||||
return;
|
||||
|
||||
bool up = TrendUp(sym, sh);
|
||||
bool dn = TrendDown(sym, sh);
|
||||
|
||||
bool wantBuy = false;
|
||||
bool wantSell = false;
|
||||
|
||||
switch(InpEntryStyle)
|
||||
{
|
||||
case ENTRY_CCIZERO_MACD:
|
||||
if(up && CciCrossAboveZero(sym) && h1 > 0.0)
|
||||
wantBuy = true;
|
||||
if(dn && CciCrossBelowZero(sym) && h1 < 0.0)
|
||||
wantSell = true;
|
||||
break;
|
||||
|
||||
case ENTRY_LAMBERT:
|
||||
if(up && CciCrossAbove100(sym) && h1 > 0.0)
|
||||
wantBuy = true;
|
||||
if(dn && CciCrossBelowMinus100(sym) && h1 < 0.0)
|
||||
wantSell = true;
|
||||
break;
|
||||
|
||||
case ENTRY_PULLBACK:
|
||||
if(up && HadCciOversoldRecently(sym) && CciCrossAboveZero(sym) && h1 > 0.0 && PullbackNearFastEmaLong(sym))
|
||||
wantBuy = true;
|
||||
if(dn && HadCciOverboughtRecently(sym) && CciCrossBelowZero(sym) && h1 < 0.0 && PullbackNearFastEmaShort(sym))
|
||||
wantSell = true;
|
||||
break;
|
||||
}
|
||||
|
||||
MqlTick tick;
|
||||
if(!SymbolInfoTick(sym, tick))
|
||||
return;
|
||||
|
||||
double sl = 0.0, tp = 0.0;
|
||||
|
||||
if(wantBuy && !wantSell)
|
||||
{
|
||||
ComputeSLTP(true, tick.ask, sl, tp);
|
||||
if(trade.Buy(InpLots, sym, tick.ask, sl, tp, "SuperEMA long"))
|
||||
Log(StringFormat("BUY ask=%.5f sl=%.5f cci=%.2f macdHist=%.5f", tick.ask, sl,
|
||||
CciAt(sym, InpTimeframe, InpCciPeriod, 1), h1));
|
||||
}
|
||||
else if(wantSell && !wantBuy)
|
||||
{
|
||||
ComputeSLTP(false, tick.bid, sl, tp);
|
||||
if(trade.Sell(InpLots, sym, tick.bid, sl, tp, "SuperEMA short"))
|
||||
Log(StringFormat("SELL bid=%.5f sl=%.5f cci=%.2f macdHist=%.5f", tick.bid, sl,
|
||||
CciAt(sym, InpTimeframe, InpCciPeriod, 1), h1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,639 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| AdaptiveMonthlyRegime.mqh |
|
||||
//| Streak unit (input): closed calendar MONTHS or closed DAYS |
|
||||
//| (server time). Losing streak -> optional CANARY (next full month |
|
||||
//| or next full day at InpAdaptiveCanaryLotMult). Canary P/L > 0 -> |
|
||||
//| full size; else HARD PAUSE. CanaryLotMult==0 -> hard pause, no |
|
||||
//| canary. Per-strat DD lot cap still uses last closed *month* P/L. |
|
||||
//| Include after all `input` blocks. |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef ADAPTIVE_MONTHLY_REGIME_MQH
|
||||
#define ADAPTIVE_MONTHLY_REGIME_MQH
|
||||
|
||||
#define UNITED_ADAPTIVE_N 13
|
||||
#define UNITED_AD_MAX_DAY_BUCKETS 400
|
||||
|
||||
#define UNITED_AD_DARVAS 0
|
||||
#define UNITED_AD_ES 1
|
||||
#define UNITED_AD_RC 2
|
||||
#define UNITED_AD_RM 3
|
||||
#define UNITED_AD_RS_APPL 4
|
||||
#define UNITED_AD_RS_BTC 5
|
||||
#define UNITED_AD_RS_NVDA 6
|
||||
#define UNITED_AD_RS_TSLA 7
|
||||
#define UNITED_AD_RS_XAU 8
|
||||
#define UNITED_AD_RRA_EUR 9
|
||||
#define UNITED_AD_RRA_AUD 10
|
||||
#define UNITED_AD_RSS 11
|
||||
#define UNITED_AD_SUPEREMA 12
|
||||
|
||||
bool g_adHardPaused[UNITED_ADAPTIVE_N];
|
||||
bool g_adCanaryWaiting[UNITED_ADAPTIVE_N];
|
||||
bool g_adCanaryActive[UNITED_ADAPTIVE_N];
|
||||
datetime g_adCanaryMonthStart[UNITED_ADAPTIVE_N];
|
||||
datetime g_adCanaryMonthEnd[UNITED_ADAPTIVE_N];
|
||||
datetime g_adHardPauseUntil[UNITED_ADAPTIVE_N];
|
||||
datetime g_adPostCanaryCooldownUntil[UNITED_ADAPTIVE_N];
|
||||
|
||||
double g_adLastClosedMonthPl[UNITED_ADAPTIVE_N];
|
||||
|
||||
datetime g_unitedAdaptiveLastUpdate = 0;
|
||||
|
||||
string UnitedAdaptive_StratName(const int s)
|
||||
{
|
||||
const string names[] =
|
||||
{
|
||||
"DarvasBox", "EMASlope", "RSICrossOver", "RM_MidPoint",
|
||||
"RS_Scalp_AAPL", "RS_Scalp_BTC", "RS_Scalp_NVDA", "RS_Scalp_TSLA", "RS_Scalp_XAU",
|
||||
"RRA_EURUSD", "RRA_AUDUSD", "SecretSauce", "SuperEMA"
|
||||
};
|
||||
if(s >= 0 && s < UNITED_ADAPTIVE_N)
|
||||
return names[s];
|
||||
return "?";
|
||||
}
|
||||
|
||||
void UnitedAdaptive_Init()
|
||||
{
|
||||
for(int i = 0; i < UNITED_ADAPTIVE_N; i++)
|
||||
{
|
||||
g_adHardPaused[i] = false;
|
||||
g_adCanaryWaiting[i] = false;
|
||||
g_adCanaryActive[i] = false;
|
||||
g_adCanaryMonthStart[i] = 0;
|
||||
g_adCanaryMonthEnd[i] = 0;
|
||||
g_adHardPauseUntil[i] = 0;
|
||||
g_adPostCanaryCooldownUntil[i] = 0;
|
||||
g_adLastClosedMonthPl[i] = 0.0;
|
||||
}
|
||||
g_unitedAdaptiveLastUpdate = 0;
|
||||
}
|
||||
|
||||
datetime UnitedAdaptive_MonthStartInt(const int y, const int m)
|
||||
{
|
||||
MqlDateTime d;
|
||||
d.year = y;
|
||||
d.mon = m;
|
||||
d.day = 1;
|
||||
d.hour = 0;
|
||||
d.min = 0;
|
||||
d.sec = 0;
|
||||
return StructToTime(d);
|
||||
}
|
||||
|
||||
void UnitedAdaptive_NextYm(int &y, int &m)
|
||||
{
|
||||
m++;
|
||||
if(m > 12)
|
||||
{
|
||||
m = 1;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedAdaptive_ClosedMonthYm(const int offsetFromLastComplete, int &y, int &m)
|
||||
{
|
||||
MqlDateTime now;
|
||||
TimeToStruct(TimeCurrent(), now);
|
||||
int ly = now.year;
|
||||
int lm = now.mon - 1;
|
||||
if(lm < 1)
|
||||
{
|
||||
lm = 12;
|
||||
ly--;
|
||||
}
|
||||
for(int i = 0; i < offsetFromLastComplete; i++)
|
||||
{
|
||||
lm--;
|
||||
if(lm < 1)
|
||||
{
|
||||
lm = 12;
|
||||
ly--;
|
||||
}
|
||||
}
|
||||
y = ly;
|
||||
m = lm;
|
||||
}
|
||||
|
||||
// Start of calendar day: offset 0 = yesterday 00:00 (last fully closed day), 1 = day before, ...
|
||||
datetime UnitedAdaptive_ClosedDayStart(const int offsetFromLastCompleteDay)
|
||||
{
|
||||
MqlDateTime n;
|
||||
TimeToStruct(TimeCurrent(), n);
|
||||
n.hour = 0;
|
||||
n.min = 0;
|
||||
n.sec = 0;
|
||||
const datetime today0 = StructToTime(n);
|
||||
return today0 - (datetime)((offsetFromLastCompleteDay + 1) * 86400);
|
||||
}
|
||||
|
||||
// Bucket index 0 = yesterday. -1 = today (incomplete) or invalid.
|
||||
int UnitedAdaptive_ClosedDayOffsetFromDealTime(const datetime dt)
|
||||
{
|
||||
MqlDateTime d, n;
|
||||
TimeToStruct(dt, d);
|
||||
d.hour = 0;
|
||||
d.min = 0;
|
||||
d.sec = 0;
|
||||
const datetime dealDay0 = StructToTime(d);
|
||||
TimeToStruct(TimeCurrent(), n);
|
||||
n.hour = 0;
|
||||
n.min = 0;
|
||||
n.sec = 0;
|
||||
const datetime today0 = StructToTime(n);
|
||||
const long deltaSec = (long)(today0 - dealDay0);
|
||||
if(deltaSec < 86400L)
|
||||
return -1;
|
||||
const int daysAgo = (int)(deltaSec / 86400L);
|
||||
return daysAgo - 1;
|
||||
}
|
||||
|
||||
datetime UnitedAdaptive_AddMonthsWallClock(const datetime dt0, const int months)
|
||||
{
|
||||
MqlDateTime t;
|
||||
TimeToStruct(dt0, t);
|
||||
for(int i = 0; i < months; i++)
|
||||
{
|
||||
t.mon++;
|
||||
if(t.mon > 12)
|
||||
{
|
||||
t.mon = 1;
|
||||
t.year++;
|
||||
}
|
||||
}
|
||||
return StructToTime(t);
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_RMDealMatches(const long mg)
|
||||
{
|
||||
if(EnableRSIMidPointHijack)
|
||||
{
|
||||
if(RM_InpEnableRSIFollow && mg == (long)RM_InpMagicNumberRSIFollow)
|
||||
return true;
|
||||
if(RM_InpEnableRSIReverse && mg == (long)RM_InpMagicNumberRSIReverse)
|
||||
return true;
|
||||
if(RM_InpEnableEMACross && mg == (long)RM_InpMagicNumberEMACross)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_DealBelongsToStrat(const int s, const long mg)
|
||||
{
|
||||
if(s == UNITED_AD_DARVAS)
|
||||
return EnableDarvasBox && mg == (long)DB_MagicNumber;
|
||||
if(s == UNITED_AD_ES)
|
||||
return EnableEMASlopeDistance && mg == (long)ES_MagicNumber;
|
||||
if(s == UNITED_AD_RC)
|
||||
return EnableRSICrossOverReversal && mg == (long)RC_MagicNumber;
|
||||
if(s == UNITED_AD_RM)
|
||||
return UnitedAdaptive_RMDealMatches(mg);
|
||||
if(s == UNITED_AD_RS_APPL)
|
||||
return EnableRSIScalpingAPPL && mg == (long)RS_APPL_MagicNumber;
|
||||
if(s == UNITED_AD_RS_BTC)
|
||||
return EnableRSIScalpingBTCUSD && mg == (long)RS_BTCUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RS_NVDA)
|
||||
return EnableRSIScalpingNVDA && mg == (long)RS_NVDA_MagicNumber;
|
||||
if(s == UNITED_AD_RS_TSLA)
|
||||
return EnableRSIScalpingTSLA && mg == (long)RS_TSLA_MagicNumber;
|
||||
if(s == UNITED_AD_RS_XAU)
|
||||
return EnableRSIScalpingXAUUSD && mg == (long)RS_XAUUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RRA_EUR)
|
||||
return EnableRSIReversalEURUSD && mg == (long)RRA_EURUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RRA_AUD)
|
||||
return EnableRSIReversalAUDUSD && mg == (long)RRA_AUDUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RSS)
|
||||
return EnableRSISecretSauceXAUUSD && mg == (long)RSS_XAUUSD_MagicNumber;
|
||||
if(s == UNITED_AD_SUPEREMA)
|
||||
return EnableSuperEMA && mg == (long)SE_MagicNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
double UnitedAdaptive_SumStratDealsRange(const int s, const datetime from, const datetime to)
|
||||
{
|
||||
if(from >= to)
|
||||
return 0.0;
|
||||
if(!HistorySelect(from, to))
|
||||
return 0.0;
|
||||
double sum = 0.0;
|
||||
const int n = HistoryDealsTotal();
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
const ulong t = HistoryDealGetTicket(i);
|
||||
if(t == 0)
|
||||
continue;
|
||||
const long mg = (long)HistoryDealGetInteger(t, DEAL_MAGIC);
|
||||
if(!UnitedAdaptive_DealBelongsToStrat(s, mg))
|
||||
continue;
|
||||
sum += HistoryDealGetDouble(t, DEAL_PROFIT);
|
||||
sum += HistoryDealGetDouble(t, DEAL_SWAP);
|
||||
sum += HistoryDealGetDouble(t, DEAL_COMMISSION);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void UnitedAdaptive_StartCanaryWait(const int s)
|
||||
{
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
{
|
||||
MqlDateTime t;
|
||||
TimeToStruct(TimeCurrent(), t);
|
||||
t.hour = 0;
|
||||
t.min = 0;
|
||||
t.sec = 0;
|
||||
const datetime today0 = StructToTime(t);
|
||||
g_adCanaryMonthStart[s] = today0 + 86400;
|
||||
g_adCanaryMonthEnd[s] = g_adCanaryMonthStart[s] + 86400;
|
||||
g_adCanaryWaiting[s] = true;
|
||||
g_adCanaryActive[s] = false;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" -> CANARY WAIT until ", TimeToString(g_adCanaryMonthStart[s], TIME_DATE),
|
||||
" then 1 day at lot x ", DoubleToString(InpAdaptiveCanaryLotMult, 4));
|
||||
return;
|
||||
}
|
||||
MqlDateTime t;
|
||||
TimeToStruct(TimeCurrent(), t);
|
||||
t.mon++;
|
||||
if(t.mon > 12)
|
||||
{
|
||||
t.mon = 1;
|
||||
t.year++;
|
||||
}
|
||||
t.day = 1;
|
||||
t.hour = 0;
|
||||
t.min = 0;
|
||||
t.sec = 0;
|
||||
g_adCanaryMonthStart[s] = StructToTime(t);
|
||||
int ey = t.year;
|
||||
int em = t.mon;
|
||||
UnitedAdaptive_NextYm(ey, em);
|
||||
g_adCanaryMonthEnd[s] = UnitedAdaptive_MonthStartInt(ey, em);
|
||||
g_adCanaryWaiting[s] = true;
|
||||
g_adCanaryActive[s] = false;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" -> CANARY WAIT until ", TimeToString(g_adCanaryMonthStart[s], TIME_DATE),
|
||||
" then 1 month at lot x ", DoubleToString(InpAdaptiveCanaryLotMult, 4));
|
||||
}
|
||||
|
||||
void UnitedAdaptive_TryExpireHardPauses()
|
||||
{
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
{
|
||||
if(InpAdaptiveHardRetryDays <= 0)
|
||||
return;
|
||||
}
|
||||
else if(InpAdaptiveHardRetryMonths <= 0)
|
||||
return;
|
||||
|
||||
const datetime now = TimeCurrent();
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
if(!g_adHardPaused[s])
|
||||
continue;
|
||||
if(g_adHardPauseUntil[s] > 0 && now >= g_adHardPauseUntil[s])
|
||||
{
|
||||
g_adHardPaused[s] = false;
|
||||
g_adHardPauseUntil[s] = 0;
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" hard pause RETRY (after ", InpAdaptiveHardRetryDays, " d)");
|
||||
else
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" hard pause RETRY (after ", InpAdaptiveHardRetryMonths, " mo)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedAdaptive_ProcessCanaryTransitions()
|
||||
{
|
||||
if(!InpAdaptiveEnable)
|
||||
return;
|
||||
|
||||
UnitedAdaptive_TryExpireHardPauses();
|
||||
|
||||
const datetime now = TimeCurrent();
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
if(g_adCanaryWaiting[s] && !g_adCanaryActive[s] && now >= g_adCanaryMonthStart[s])
|
||||
{
|
||||
g_adCanaryWaiting[s] = false;
|
||||
g_adCanaryActive[s] = true;
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s), " CANARY ACTIVE (probation day)");
|
||||
else
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s), " CANARY ACTIVE (probation month)");
|
||||
}
|
||||
|
||||
if(g_adCanaryActive[s] && now >= g_adCanaryMonthEnd[s])
|
||||
{
|
||||
const double pl = UnitedAdaptive_SumStratDealsRange(s, g_adCanaryMonthStart[s], g_adCanaryMonthEnd[s]);
|
||||
g_adCanaryActive[s] = false;
|
||||
g_adCanaryWaiting[s] = false;
|
||||
if(pl > 0.0)
|
||||
{
|
||||
if(InpAdaptivePostCanaryCooldownDays > 0)
|
||||
g_adPostCanaryCooldownUntil[s] = TimeCurrent() + InpAdaptivePostCanaryCooldownDays * 86400;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" canary OK P/L=", DoubleToString(pl, 2), " -> full size");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_adHardPaused[s] = true;
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
{
|
||||
if(InpAdaptiveHardRetryDays > 0)
|
||||
g_adHardPauseUntil[s] = now + (datetime)InpAdaptiveHardRetryDays * 86400;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" canary FAIL P/L=", DoubleToString(pl, 2), " -> HARD PAUSE",
|
||||
(InpAdaptiveHardRetryDays > 0 ? " (auto-retry later)" : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(InpAdaptiveHardRetryMonths > 0)
|
||||
g_adHardPauseUntil[s] = UnitedAdaptive_AddMonthsWallClock(now, InpAdaptiveHardRetryMonths);
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" canary FAIL P/L=", DoubleToString(pl, 2), " -> HARD PAUSE",
|
||||
(InpAdaptiveHardRetryMonths > 0 ? " (auto-retry later)" : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_StratLastMonthIsLosing(const int s)
|
||||
{
|
||||
if(s < 0 || s >= UNITED_ADAPTIVE_N)
|
||||
return false;
|
||||
const double thr = MathMax(0.0, InpDdLotCapStratLossThreshold);
|
||||
return g_adLastClosedMonthPl[s] < -thr;
|
||||
}
|
||||
|
||||
void UnitedAdaptive_RecomputeStreaks()
|
||||
{
|
||||
const bool needMonthPlCap = InpDdLotCapEnable && InpDdLotCapPerStratEnable;
|
||||
const bool adaptMonth = InpAdaptiveEnable && InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_MONTH;
|
||||
const bool adaptDay = InpAdaptiveEnable && InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY;
|
||||
|
||||
int nMonthOff = 0;
|
||||
int streakReqM = 1;
|
||||
if(adaptMonth)
|
||||
{
|
||||
streakReqM = MathMax(1, InpAdaptiveRedStreak);
|
||||
const int L = MathMax(InpAdaptiveLookbackMonths, streakReqM + 1);
|
||||
nMonthOff = MathMin(L, 63);
|
||||
}
|
||||
else if(needMonthPlCap)
|
||||
nMonthOff = 2;
|
||||
|
||||
int nDayOff = 0;
|
||||
int streakReqD = 1;
|
||||
if(adaptDay)
|
||||
{
|
||||
streakReqD = MathMax(1, InpAdaptiveRedStreak);
|
||||
const int L = MathMax(InpAdaptiveLookbackDays, streakReqD + 1);
|
||||
nDayOff = MathMin(L, UNITED_AD_MAX_DAY_BUCKETS);
|
||||
}
|
||||
|
||||
if(nMonthOff == 0 && nDayOff == 0)
|
||||
return;
|
||||
|
||||
const datetime to = TimeCurrent() + 60;
|
||||
datetime from = to;
|
||||
if(nMonthOff > 0)
|
||||
{
|
||||
int oy = 0, om = 0;
|
||||
UnitedAdaptive_ClosedMonthYm(nMonthOff - 1, oy, om);
|
||||
const datetime mf = UnitedAdaptive_MonthStartInt(oy, om);
|
||||
if(mf < from)
|
||||
from = mf;
|
||||
}
|
||||
if(nDayOff > 0)
|
||||
{
|
||||
const datetime df = UnitedAdaptive_ClosedDayStart(nDayOff - 1);
|
||||
if(df < from)
|
||||
from = df;
|
||||
}
|
||||
|
||||
if(from >= to || !HistorySelect(from, to))
|
||||
return;
|
||||
|
||||
double monthBuck[UNITED_ADAPTIVE_N][64];
|
||||
double dayBuck[UNITED_ADAPTIVE_N][UNITED_AD_MAX_DAY_BUCKETS];
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
for(int o = 0; o < 64; o++)
|
||||
monthBuck[s][o] = 0.0;
|
||||
for(int o = 0; o < UNITED_AD_MAX_DAY_BUCKETS; o++)
|
||||
dayBuck[s][o] = 0.0;
|
||||
}
|
||||
|
||||
const int total = HistoryDealsTotal();
|
||||
for(int i = 0; i < total; i++)
|
||||
{
|
||||
const ulong tk = HistoryDealGetTicket(i);
|
||||
if(tk == 0)
|
||||
continue;
|
||||
const long mg = (long)HistoryDealGetInteger(tk, DEAL_MAGIC);
|
||||
const datetime dt = (datetime)HistoryDealGetInteger(tk, DEAL_TIME);
|
||||
const double pl = HistoryDealGetDouble(tk, DEAL_PROFIT)
|
||||
+ HistoryDealGetDouble(tk, DEAL_SWAP)
|
||||
+ HistoryDealGetDouble(tk, DEAL_COMMISSION);
|
||||
|
||||
if(nMonthOff > 0)
|
||||
{
|
||||
for(int o = 0; o < nMonthOff; o++)
|
||||
{
|
||||
int y = 0, m = 0;
|
||||
UnitedAdaptive_ClosedMonthYm(o, y, m);
|
||||
const datetime ms = UnitedAdaptive_MonthStartInt(y, m);
|
||||
int ny = y, nm = m;
|
||||
UnitedAdaptive_NextYm(ny, nm);
|
||||
const datetime me = UnitedAdaptive_MonthStartInt(ny, nm);
|
||||
if(dt < ms || dt >= me)
|
||||
continue;
|
||||
|
||||
if(EnableDarvasBox && mg == (long)DB_MagicNumber)
|
||||
monthBuck[UNITED_AD_DARVAS][o] += pl;
|
||||
if(EnableEMASlopeDistance && mg == (long)ES_MagicNumber)
|
||||
monthBuck[UNITED_AD_ES][o] += pl;
|
||||
if(EnableRSICrossOverReversal && mg == (long)RC_MagicNumber)
|
||||
monthBuck[UNITED_AD_RC][o] += pl;
|
||||
if(UnitedAdaptive_RMDealMatches(mg))
|
||||
monthBuck[UNITED_AD_RM][o] += pl;
|
||||
if(EnableRSIScalpingAPPL && mg == (long)RS_APPL_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_APPL][o] += pl;
|
||||
if(EnableRSIScalpingBTCUSD && mg == (long)RS_BTCUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_BTC][o] += pl;
|
||||
if(EnableRSIScalpingNVDA && mg == (long)RS_NVDA_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_NVDA][o] += pl;
|
||||
if(EnableRSIScalpingTSLA && mg == (long)RS_TSLA_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_TSLA][o] += pl;
|
||||
if(EnableRSIScalpingXAUUSD && mg == (long)RS_XAUUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_XAU][o] += pl;
|
||||
if(EnableRSIReversalEURUSD && mg == (long)RRA_EURUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RRA_EUR][o] += pl;
|
||||
if(EnableRSIReversalAUDUSD && mg == (long)RRA_AUDUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RRA_AUD][o] += pl;
|
||||
if(EnableRSISecretSauceXAUUSD && mg == (long)RSS_XAUUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RSS][o] += pl;
|
||||
if(EnableSuperEMA && mg == (long)SE_MagicNumber)
|
||||
monthBuck[UNITED_AD_SUPEREMA][o] += pl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nDayOff > 0)
|
||||
{
|
||||
const int dOff = UnitedAdaptive_ClosedDayOffsetFromDealTime(dt);
|
||||
if(dOff >= 0 && dOff < nDayOff)
|
||||
{
|
||||
if(EnableDarvasBox && mg == (long)DB_MagicNumber)
|
||||
dayBuck[UNITED_AD_DARVAS][dOff] += pl;
|
||||
if(EnableEMASlopeDistance && mg == (long)ES_MagicNumber)
|
||||
dayBuck[UNITED_AD_ES][dOff] += pl;
|
||||
if(EnableRSICrossOverReversal && mg == (long)RC_MagicNumber)
|
||||
dayBuck[UNITED_AD_RC][dOff] += pl;
|
||||
if(UnitedAdaptive_RMDealMatches(mg))
|
||||
dayBuck[UNITED_AD_RM][dOff] += pl;
|
||||
if(EnableRSIScalpingAPPL && mg == (long)RS_APPL_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_APPL][dOff] += pl;
|
||||
if(EnableRSIScalpingBTCUSD && mg == (long)RS_BTCUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_BTC][dOff] += pl;
|
||||
if(EnableRSIScalpingNVDA && mg == (long)RS_NVDA_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_NVDA][dOff] += pl;
|
||||
if(EnableRSIScalpingTSLA && mg == (long)RS_TSLA_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_TSLA][dOff] += pl;
|
||||
if(EnableRSIScalpingXAUUSD && mg == (long)RS_XAUUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_XAU][dOff] += pl;
|
||||
if(EnableRSIReversalEURUSD && mg == (long)RRA_EURUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RRA_EUR][dOff] += pl;
|
||||
if(EnableRSIReversalAUDUSD && mg == (long)RRA_AUDUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RRA_AUD][dOff] += pl;
|
||||
if(EnableRSISecretSauceXAUUSD && mg == (long)RSS_XAUUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RSS][dOff] += pl;
|
||||
if(EnableSuperEMA && mg == (long)SE_MagicNumber)
|
||||
dayBuck[UNITED_AD_SUPEREMA][dOff] += pl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(nMonthOff > 0)
|
||||
{
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
g_adLastClosedMonthPl[s] = monthBuck[s][0];
|
||||
}
|
||||
|
||||
if(!InpAdaptiveEnable)
|
||||
return;
|
||||
|
||||
const double thr = MathMax(0.0, InpAdaptiveRedThreshold);
|
||||
const bool useDay = adaptDay;
|
||||
const int streakReq = useDay ? streakReqD : streakReqM;
|
||||
const int nOff = useDay ? nDayOff : nMonthOff;
|
||||
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
if(g_adHardPaused[s])
|
||||
continue;
|
||||
if(g_adCanaryActive[s] || g_adCanaryWaiting[s])
|
||||
{
|
||||
int consecOk = 0;
|
||||
for(int o = 0; o < streakReq && o < nOff; o++)
|
||||
{
|
||||
const double bpl = useDay ? dayBuck[s][o] : monthBuck[s][o];
|
||||
if(bpl < -thr)
|
||||
consecOk++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
const bool streakBad = (consecOk >= streakReq);
|
||||
if(!streakBad && g_adCanaryWaiting[s] && !g_adCanaryActive[s])
|
||||
{
|
||||
g_adCanaryWaiting[s] = false;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s), " canary wait CANCELLED (streak cleared)");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int consec = 0;
|
||||
for(int o = 0; o < streakReq && o < nOff; o++)
|
||||
{
|
||||
const double bpl = useDay ? dayBuck[s][o] : monthBuck[s][o];
|
||||
if(bpl < -thr)
|
||||
consec++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
const bool streakBad = (consec >= streakReq);
|
||||
if(!streakBad)
|
||||
continue;
|
||||
|
||||
const bool prevHard = g_adHardPaused[s];
|
||||
if(InpAdaptiveCanaryLotMult > 0.0)
|
||||
{
|
||||
if(!g_adCanaryWaiting[s] && !g_adCanaryActive[s])
|
||||
{
|
||||
if(g_adPostCanaryCooldownUntil[s] > TimeCurrent())
|
||||
continue;
|
||||
UnitedAdaptive_StartCanaryWait(s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_adHardPaused[s] = true;
|
||||
if(!prevHard && useDay && InpAdaptiveHardRetryDays > 0)
|
||||
g_adHardPauseUntil[s] = TimeCurrent() + (datetime)InpAdaptiveHardRetryDays * 86400;
|
||||
else if(!prevHard && !useDay && InpAdaptiveHardRetryMonths > 0)
|
||||
g_adHardPauseUntil[s] = UnitedAdaptive_AddMonthsWallClock(TimeCurrent(), InpAdaptiveHardRetryMonths);
|
||||
if(!prevHard)
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" HARD PAUSE (streak, canary disabled)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedAdaptive_UpdateIfDue()
|
||||
{
|
||||
if(!InpAdaptiveEnable && (!InpDdLotCapEnable || !InpDdLotCapPerStratEnable))
|
||||
{
|
||||
UnitedAdaptive_Init();
|
||||
return;
|
||||
}
|
||||
|
||||
int everySec = 3600;
|
||||
if(InpAdaptiveEnable)
|
||||
everySec = MathMin(everySec, MathMax(60, InpAdaptiveUpdateSeconds));
|
||||
if(InpDdLotCapEnable && InpDdLotCapPerStratEnable)
|
||||
everySec = MathMin(everySec, MathMax(60, InpDdLotCapUpdateSeconds));
|
||||
|
||||
if(g_unitedAdaptiveLastUpdate > 0 && (TimeCurrent() - g_unitedAdaptiveLastUpdate) < everySec)
|
||||
return;
|
||||
|
||||
g_unitedAdaptiveLastUpdate = TimeCurrent();
|
||||
UnitedAdaptive_RecomputeStreaks();
|
||||
}
|
||||
|
||||
double UnitedAdaptive_GetLotMult(const int stratId)
|
||||
{
|
||||
if(stratId < 0 || stratId >= UNITED_ADAPTIVE_N)
|
||||
return 1.0;
|
||||
if(!InpAdaptiveEnable)
|
||||
return 1.0;
|
||||
if(g_adCanaryActive[stratId])
|
||||
return MathMax(0.0, InpAdaptiveCanaryLotMult);
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_StrategyActive(const int stratId)
|
||||
{
|
||||
if(stratId < 0 || stratId >= UNITED_ADAPTIVE_N)
|
||||
return true;
|
||||
if(!InpAdaptiveEnable)
|
||||
return true;
|
||||
if(g_adHardPaused[stratId])
|
||||
return false;
|
||||
if(g_adCanaryWaiting[stratId] && !g_adCanaryActive[stratId])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,438 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSISecretSauceStrategy.mqh |
|
||||
//| RSI Secret Sauce: leave 70/30 zone, re-enter, peak/bottom entry |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
struct RSISecretSauceData
|
||||
{
|
||||
string symbol;
|
||||
bool isInitialized;
|
||||
CTrade trade;
|
||||
CPositionInfo positionInfo;
|
||||
int rsiHandle;
|
||||
int atrHandle;
|
||||
double rsiBuffer[];
|
||||
double atrBuffer[];
|
||||
double highBuffer[];
|
||||
double lowBuffer[];
|
||||
bool rsiWasOverbought;
|
||||
bool rsiWasOversold;
|
||||
bool rsiBackInRange;
|
||||
datetime lastRSIExitTime;
|
||||
datetime lastRSIReentryTime;
|
||||
datetime lastTradeTime;
|
||||
datetime lastBarTime;
|
||||
ENUM_TIMEFRAMES timeframe;
|
||||
int rsiPeriod;
|
||||
double rsiOverbought;
|
||||
double rsiOversold;
|
||||
int rsiLookback;
|
||||
int peakBars;
|
||||
bool requireDivergence;
|
||||
double stopLossATR;
|
||||
double takeProfitATR;
|
||||
int atrPeriod;
|
||||
bool useSwingStopLoss;
|
||||
int swingLookback;
|
||||
int maxPositions;
|
||||
int minBarsBetweenTrades;
|
||||
int magicNumber;
|
||||
int slippage;
|
||||
};
|
||||
|
||||
bool RSS_UpdateIndicators(RSISecretSauceData& d);
|
||||
void RSS_UpdateRSIState(RSISecretSauceData& d);
|
||||
bool RSS_CanOpenNewPosition(RSISecretSauceData& d);
|
||||
void RSS_CheckEntrySignals(RSISecretSauceData& d, const double lotSize);
|
||||
bool RSS_IsRSIPeak(RSISecretSauceData& d);
|
||||
bool RSS_IsRSIBottom(RSISecretSauceData& d);
|
||||
void RSS_OpenPosition(RSISecretSauceData& d, ENUM_POSITION_TYPE type, const double lotSize);
|
||||
bool RSS_CalculateStops(RSISecretSauceData& d, double price, ENUM_POSITION_TYPE type, double& sl, double& tp);
|
||||
double RSS_GetSwingStopLoss(RSISecretSauceData& d, ENUM_POSITION_TYPE type);
|
||||
|
||||
bool InitRSISecretSauce(RSISecretSauceData& d,
|
||||
const string symbol,
|
||||
const ENUM_TIMEFRAMES timeframe,
|
||||
const int rsiPeriod,
|
||||
const double rsiOverbought,
|
||||
const double rsiOversold,
|
||||
const int rsiLookback,
|
||||
const int peakBars,
|
||||
const bool requireDivergence,
|
||||
const double stopLossATR,
|
||||
const double takeProfitATR,
|
||||
const int atrPeriod,
|
||||
const bool useSwingStopLoss,
|
||||
const int swingLookback,
|
||||
const int maxPositions,
|
||||
const int minBarsBetweenTrades,
|
||||
const int magicNumber,
|
||||
const int slippage)
|
||||
{
|
||||
d.symbol = symbol;
|
||||
if(StringLen(d.symbol) == 0)
|
||||
d.symbol = _Symbol;
|
||||
d.isInitialized = false;
|
||||
d.rsiHandle = INVALID_HANDLE;
|
||||
d.atrHandle = INVALID_HANDLE;
|
||||
d.rsiWasOverbought = false;
|
||||
d.rsiWasOversold = false;
|
||||
d.rsiBackInRange = false;
|
||||
d.lastRSIExitTime = 0;
|
||||
d.lastRSIReentryTime = 0;
|
||||
d.lastTradeTime = 0;
|
||||
d.lastBarTime = 0;
|
||||
|
||||
if(!SymbolSelect(d.symbol, true))
|
||||
{
|
||||
Print("RSISecretSauce: Symbol '", d.symbol, "' not available in Market Watch.");
|
||||
return false;
|
||||
}
|
||||
|
||||
d.timeframe = timeframe;
|
||||
d.rsiPeriod = rsiPeriod;
|
||||
d.rsiOverbought = rsiOverbought;
|
||||
d.rsiOversold = rsiOversold;
|
||||
d.rsiLookback = rsiLookback;
|
||||
d.peakBars = peakBars;
|
||||
d.requireDivergence = requireDivergence;
|
||||
d.stopLossATR = stopLossATR;
|
||||
d.takeProfitATR = takeProfitATR;
|
||||
d.atrPeriod = atrPeriod;
|
||||
d.useSwingStopLoss = useSwingStopLoss;
|
||||
d.swingLookback = swingLookback;
|
||||
d.maxPositions = maxPositions;
|
||||
d.minBarsBetweenTrades = minBarsBetweenTrades;
|
||||
d.magicNumber = magicNumber;
|
||||
d.slippage = slippage;
|
||||
|
||||
Sleep(100);
|
||||
int retry = 0;
|
||||
while(retry < 5 && d.rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
d.rsiHandle = iRSI(d.symbol, d.timeframe, d.rsiPeriod, PRICE_CLOSE);
|
||||
if(d.rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
if(GetLastError() == 4805 && retry < 4)
|
||||
{
|
||||
Sleep(1000);
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
Print("RSISecretSauce: Failed to create RSI for '", d.symbol, "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
retry = 0;
|
||||
while(retry < 5 && d.atrHandle == INVALID_HANDLE)
|
||||
{
|
||||
d.atrHandle = iATR(d.symbol, d.timeframe, d.atrPeriod);
|
||||
if(d.atrHandle == INVALID_HANDLE)
|
||||
{
|
||||
if(GetLastError() == 4805 && retry < 4)
|
||||
{
|
||||
Sleep(1000);
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
Print("RSISecretSauce: Failed to create ATR for '", d.symbol, "'");
|
||||
IndicatorRelease(d.rsiHandle);
|
||||
d.rsiHandle = INVALID_HANDLE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ArraySetAsSeries(d.rsiBuffer, true);
|
||||
ArraySetAsSeries(d.atrBuffer, true);
|
||||
ArraySetAsSeries(d.highBuffer, true);
|
||||
ArraySetAsSeries(d.lowBuffer, true);
|
||||
|
||||
d.trade.SetExpertMagicNumber(d.magicNumber);
|
||||
d.trade.SetDeviationInPoints(d.slippage);
|
||||
d.trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
d.isInitialized = true;
|
||||
Print("RSISecretSauce: Initialized for '", d.symbol, "' TF=", EnumToString(d.timeframe));
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeinitRSISecretSauce(RSISecretSauceData& d)
|
||||
{
|
||||
if(d.rsiHandle != INVALID_HANDLE)
|
||||
IndicatorRelease(d.rsiHandle);
|
||||
if(d.atrHandle != INVALID_HANDLE)
|
||||
IndicatorRelease(d.atrHandle);
|
||||
d.rsiHandle = INVALID_HANDLE;
|
||||
d.atrHandle = INVALID_HANDLE;
|
||||
d.isInitialized = false;
|
||||
}
|
||||
|
||||
bool RSS_UpdateIndicators(RSISecretSauceData& d)
|
||||
{
|
||||
int rsiBarsNeeded = d.rsiLookback + 5;
|
||||
if(CopyBuffer(d.rsiHandle, 0, 0, rsiBarsNeeded, d.rsiBuffer) < rsiBarsNeeded)
|
||||
return false;
|
||||
if(CopyBuffer(d.atrHandle, 0, 0, 2, d.atrBuffer) < 2)
|
||||
return false;
|
||||
if(CopyHigh(d.symbol, d.timeframe, 0, d.swingLookback + 5, d.highBuffer) < d.swingLookback + 5)
|
||||
return false;
|
||||
if(CopyLow(d.symbol, d.timeframe, 0, d.swingLookback + 5, d.lowBuffer) < d.swingLookback + 5)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RSS_UpdateRSIState(RSISecretSauceData& d)
|
||||
{
|
||||
double rsiCurrent = d.rsiBuffer[0];
|
||||
double rsiPrev = d.rsiBuffer[1];
|
||||
|
||||
if(rsiPrev >= d.rsiOverbought && rsiCurrent < d.rsiOverbought)
|
||||
{
|
||||
d.rsiWasOverbought = true;
|
||||
d.rsiBackInRange = true;
|
||||
d.lastRSIExitTime = TimeCurrent();
|
||||
d.lastRSIReentryTime = TimeCurrent();
|
||||
}
|
||||
|
||||
if(rsiPrev <= d.rsiOversold && rsiCurrent > d.rsiOversold)
|
||||
{
|
||||
d.rsiWasOversold = true;
|
||||
d.rsiBackInRange = true;
|
||||
d.lastRSIExitTime = TimeCurrent();
|
||||
d.lastRSIReentryTime = TimeCurrent();
|
||||
}
|
||||
|
||||
if(rsiCurrent >= d.rsiOverbought)
|
||||
{
|
||||
d.rsiWasOverbought = false;
|
||||
d.rsiBackInRange = false;
|
||||
}
|
||||
|
||||
if(rsiCurrent <= d.rsiOversold)
|
||||
{
|
||||
d.rsiWasOversold = false;
|
||||
d.rsiBackInRange = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RSS_CanOpenNewPosition(RSISecretSauceData& d)
|
||||
{
|
||||
int positionCount = 0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
if(d.positionInfo.SelectByIndex(i))
|
||||
{
|
||||
if(d.positionInfo.Symbol() == d.symbol && d.positionInfo.Magic() == d.magicNumber)
|
||||
positionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(positionCount >= d.maxPositions)
|
||||
return false;
|
||||
|
||||
if(d.lastTradeTime > 0)
|
||||
{
|
||||
int barsSince = Bars(d.symbol, d.timeframe, d.lastTradeTime, TimeCurrent());
|
||||
if(barsSince < d.minBarsBetweenTrades)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RSS_IsRSIPeak(RSISecretSauceData& d)
|
||||
{
|
||||
if(ArraySize(d.rsiBuffer) < d.peakBars + 2)
|
||||
return false;
|
||||
|
||||
double currentRSI = d.rsiBuffer[0];
|
||||
bool isPeak = true;
|
||||
|
||||
for(int i = 1; i <= d.peakBars; i++)
|
||||
{
|
||||
if(d.rsiBuffer[i] >= currentRSI)
|
||||
{
|
||||
isPeak = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(d.rsiBuffer[1] >= currentRSI)
|
||||
isPeak = false;
|
||||
|
||||
return isPeak;
|
||||
}
|
||||
|
||||
bool RSS_IsRSIBottom(RSISecretSauceData& d)
|
||||
{
|
||||
if(ArraySize(d.rsiBuffer) < d.peakBars + 2)
|
||||
return false;
|
||||
|
||||
double currentRSI = d.rsiBuffer[0];
|
||||
bool isBottom = true;
|
||||
|
||||
for(int i = 1; i <= d.peakBars; i++)
|
||||
{
|
||||
if(d.rsiBuffer[i] <= currentRSI)
|
||||
{
|
||||
isBottom = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(d.rsiBuffer[1] <= currentRSI)
|
||||
isBottom = false;
|
||||
|
||||
return isBottom;
|
||||
}
|
||||
|
||||
void RSS_CheckEntrySignals(RSISecretSauceData& d, const double lotSize)
|
||||
{
|
||||
if(d.rsiWasOverbought && d.rsiBackInRange)
|
||||
{
|
||||
if(d.rsiBuffer[0] < d.rsiOverbought)
|
||||
{
|
||||
if(RSS_IsRSIPeak(d))
|
||||
RSS_OpenPosition(d, POSITION_TYPE_BUY, lotSize);
|
||||
}
|
||||
}
|
||||
|
||||
if(d.rsiWasOversold && d.rsiBackInRange)
|
||||
{
|
||||
if(d.rsiBuffer[0] > d.rsiOversold)
|
||||
{
|
||||
if(RSS_IsRSIBottom(d))
|
||||
RSS_OpenPosition(d, POSITION_TYPE_SELL, lotSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RSS_CalculateStops(RSISecretSauceData& d, double price, ENUM_POSITION_TYPE type, double& sl, double& tp)
|
||||
{
|
||||
double atrValue = d.atrBuffer[0];
|
||||
if(atrValue <= 0)
|
||||
atrValue = price * 0.01;
|
||||
|
||||
double slDistance = atrValue * d.stopLossATR;
|
||||
double tpDistance = atrValue * d.takeProfitATR;
|
||||
|
||||
int digits = (int)SymbolInfoInteger(d.symbol, SYMBOL_DIGITS);
|
||||
double point = SymbolInfoDouble(d.symbol, SYMBOL_POINT);
|
||||
int stopsLevel = (int)SymbolInfoInteger(d.symbol, SYMBOL_TRADE_STOPS_LEVEL);
|
||||
double minStopDistance = MathMax(stopsLevel * point, point * 10);
|
||||
|
||||
if(d.useSwingStopLoss)
|
||||
{
|
||||
double swingStop = RSS_GetSwingStopLoss(d, type);
|
||||
if(swingStop > 0)
|
||||
{
|
||||
if(type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(swingStop < price && (price - swingStop) > minStopDistance)
|
||||
slDistance = price - swingStop;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(swingStop > price && (swingStop - price) > minStopDistance)
|
||||
slDistance = swingStop - price;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(slDistance < minStopDistance)
|
||||
slDistance = minStopDistance;
|
||||
if(tpDistance < minStopDistance)
|
||||
tpDistance = minStopDistance;
|
||||
|
||||
if(type == POSITION_TYPE_BUY)
|
||||
{
|
||||
sl = NormalizeDouble(price - slDistance, digits);
|
||||
tp = NormalizeDouble(price + tpDistance, digits);
|
||||
}
|
||||
else
|
||||
{
|
||||
sl = NormalizeDouble(price + slDistance, digits);
|
||||
tp = NormalizeDouble(price - tpDistance, digits);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
double RSS_GetSwingStopLoss(RSISecretSauceData& d, ENUM_POSITION_TYPE type)
|
||||
{
|
||||
if(type == POSITION_TYPE_BUY)
|
||||
{
|
||||
double lowestLow = d.lowBuffer[0];
|
||||
for(int i = 1; i < d.swingLookback && i < ArraySize(d.lowBuffer); i++)
|
||||
{
|
||||
if(d.lowBuffer[i] < lowestLow)
|
||||
lowestLow = d.lowBuffer[i];
|
||||
}
|
||||
return lowestLow;
|
||||
}
|
||||
|
||||
double highestHigh = d.highBuffer[0];
|
||||
for(int i = 1; i < d.swingLookback && i < ArraySize(d.highBuffer); i++)
|
||||
{
|
||||
if(d.highBuffer[i] > highestHigh)
|
||||
highestHigh = d.highBuffer[i];
|
||||
}
|
||||
return highestHigh;
|
||||
}
|
||||
|
||||
void RSS_OpenPosition(RSISecretSauceData& d, ENUM_POSITION_TYPE type, const double lotSize)
|
||||
{
|
||||
double price = (type == POSITION_TYPE_BUY) ?
|
||||
SymbolInfoDouble(d.symbol, SYMBOL_ASK) :
|
||||
SymbolInfoDouble(d.symbol, SYMBOL_BID);
|
||||
|
||||
if(price <= 0)
|
||||
return;
|
||||
|
||||
double sl = 0.0, tp = 0.0;
|
||||
if(!RSS_CalculateStops(d, price, type, sl, tp))
|
||||
return;
|
||||
|
||||
string comment = "RSI_Secret_" + (type == POSITION_TYPE_BUY ? "LONG" : "SHORT");
|
||||
|
||||
bool result = false;
|
||||
if(type == POSITION_TYPE_BUY)
|
||||
result = d.trade.Buy(lotSize, d.symbol, 0, sl, tp, comment);
|
||||
else
|
||||
result = d.trade.Sell(lotSize, d.symbol, 0, sl, tp, comment);
|
||||
|
||||
if(result)
|
||||
{
|
||||
d.lastTradeTime = TimeCurrent();
|
||||
if(type == POSITION_TYPE_BUY)
|
||||
d.rsiWasOverbought = false;
|
||||
else
|
||||
d.rsiWasOversold = false;
|
||||
d.rsiBackInRange = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessRSISecretSauce(RSISecretSauceData& d, const double lotSize)
|
||||
{
|
||||
if(!d.isInitialized)
|
||||
return;
|
||||
|
||||
int requiredBars = MathMax(d.rsiLookback, d.swingLookback) + 10;
|
||||
if(Bars(d.symbol, d.timeframe) < requiredBars)
|
||||
return;
|
||||
|
||||
datetime currentBarTime = iTime(d.symbol, d.timeframe, 0);
|
||||
if(currentBarTime == d.lastBarTime)
|
||||
return;
|
||||
|
||||
d.lastBarTime = currentBarTime;
|
||||
|
||||
if(!RSS_UpdateIndicators(d))
|
||||
return;
|
||||
|
||||
RSS_UpdateRSIState(d);
|
||||
|
||||
if(RSS_CanOpenNewPosition(d))
|
||||
RSS_CheckEntrySignals(d, lotSize);
|
||||
}
|
||||
@@ -0,0 +1,478 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SuperEMAStrategy.mqh — EMA + CCI + MACD (United EA module) |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef SUPER_EMA_STRATEGY_MQH
|
||||
#define SUPER_EMA_STRATEGY_MQH
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
enum ENUM_SE_ENTRY_STYLE
|
||||
{
|
||||
SE_ENTRY_CCIZERO_MACD = 0,
|
||||
SE_ENTRY_LAMBERT = 1,
|
||||
SE_ENTRY_PULLBACK = 2
|
||||
};
|
||||
|
||||
struct SuperEMAData
|
||||
{
|
||||
string symbol;
|
||||
ENUM_TIMEFRAMES tf;
|
||||
datetime lastBarTime;
|
||||
CTrade trade;
|
||||
bool isInitialized;
|
||||
int slippagePoints;
|
||||
int magic;
|
||||
int emaFast;
|
||||
int emaMid;
|
||||
int emaSlow;
|
||||
int emaTrendBars;
|
||||
int cciPeriod;
|
||||
double cciOverbought;
|
||||
double cciOversold;
|
||||
int pullbackCciLookback;
|
||||
int macdFast;
|
||||
int macdSlow;
|
||||
int macdSignal;
|
||||
ENUM_SE_ENTRY_STYLE entryStyle;
|
||||
bool oneTradeOnly;
|
||||
bool useStructuralSL;
|
||||
double slBufferPoints;
|
||||
bool exitOnTrendFlip;
|
||||
bool exitOnMacdFlip;
|
||||
bool exitOnCciZeroCross;
|
||||
int maxHoldingBars;
|
||||
bool exitBelowMidEma;
|
||||
bool debugLogs;
|
||||
};
|
||||
|
||||
void SuperEMA_Log(SuperEMAData &d, const string s)
|
||||
{
|
||||
if(d.debugLogs)
|
||||
Print("[SuperEMA] ", s);
|
||||
}
|
||||
|
||||
bool SuperEMA_IsNewBar(SuperEMAData &d)
|
||||
{
|
||||
datetime t = iTime(d.symbol, d.tf, 0);
|
||||
if(t <= 0 || t == d.lastBarTime)
|
||||
return false;
|
||||
d.lastBarTime = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
double SuperEMA_EmaAt(SuperEMAData &d, const int period, const int shift)
|
||||
{
|
||||
int h = iMA(d.symbol, d.tf, period, 0, MODE_EMA, PRICE_CLOSE);
|
||||
if(h == INVALID_HANDLE)
|
||||
return 0.0;
|
||||
double b[1];
|
||||
if(CopyBuffer(h, 0, shift, 1, b) <= 0)
|
||||
{
|
||||
IndicatorRelease(h);
|
||||
return 0.0;
|
||||
}
|
||||
IndicatorRelease(h);
|
||||
return b[0];
|
||||
}
|
||||
|
||||
double SuperEMA_CciAt(SuperEMAData &d, const int shift)
|
||||
{
|
||||
int h = iCCI(d.symbol, d.tf, d.cciPeriod, PRICE_TYPICAL);
|
||||
if(h == INVALID_HANDLE)
|
||||
return 0.0;
|
||||
double b[1];
|
||||
if(CopyBuffer(h, 0, shift, 1, b) <= 0)
|
||||
{
|
||||
IndicatorRelease(h);
|
||||
return 0.0;
|
||||
}
|
||||
IndicatorRelease(h);
|
||||
return b[0];
|
||||
}
|
||||
|
||||
bool SuperEMA_MacdHistAt(SuperEMAData &d, const int shift, double &hist)
|
||||
{
|
||||
int h = iMACD(d.symbol, d.tf, d.macdFast, d.macdSlow, d.macdSignal, PRICE_CLOSE);
|
||||
if(h == INVALID_HANDLE)
|
||||
return false;
|
||||
double mainLine[1], sigLine[1];
|
||||
if(CopyBuffer(h, 0, shift, 1, mainLine) <= 0 || CopyBuffer(h, 1, shift, 1, sigLine) <= 0)
|
||||
{
|
||||
IndicatorRelease(h);
|
||||
return false;
|
||||
}
|
||||
IndicatorRelease(h);
|
||||
hist = mainLine[0] - sigLine[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SuperEMA_TrendUp(SuperEMAData &d, const int sh)
|
||||
{
|
||||
double c = iClose(d.symbol, d.tf, sh);
|
||||
double emaS = SuperEMA_EmaAt(d, d.emaSlow, sh);
|
||||
return (emaS > 0.0 && c > emaS);
|
||||
}
|
||||
|
||||
bool SuperEMA_TrendDown(SuperEMAData &d, const int sh)
|
||||
{
|
||||
double c = iClose(d.symbol, d.tf, sh);
|
||||
double emaS = SuperEMA_EmaAt(d, d.emaSlow, sh);
|
||||
return (emaS > 0.0 && c < emaS);
|
||||
}
|
||||
|
||||
bool SuperEMA_CciCrossAboveZero(SuperEMAData &d)
|
||||
{
|
||||
double c1 = SuperEMA_CciAt(d, 1);
|
||||
double c2 = SuperEMA_CciAt(d, 2);
|
||||
return (c2 <= 0.0 && c1 > 0.0);
|
||||
}
|
||||
|
||||
bool SuperEMA_CciCrossBelowZero(SuperEMAData &d)
|
||||
{
|
||||
double c1 = SuperEMA_CciAt(d, 1);
|
||||
double c2 = SuperEMA_CciAt(d, 2);
|
||||
return (c2 >= 0.0 && c1 < 0.0);
|
||||
}
|
||||
|
||||
bool SuperEMA_CciCrossAbove100(SuperEMAData &d)
|
||||
{
|
||||
double c1 = SuperEMA_CciAt(d, 1);
|
||||
double c2 = SuperEMA_CciAt(d, 2);
|
||||
return (c2 < d.cciOverbought && c1 > d.cciOverbought);
|
||||
}
|
||||
|
||||
bool SuperEMA_CciCrossBelowMinus100(SuperEMAData &d)
|
||||
{
|
||||
double c1 = SuperEMA_CciAt(d, 1);
|
||||
double c2 = SuperEMA_CciAt(d, 2);
|
||||
return (c2 > d.cciOversold && c1 < d.cciOversold);
|
||||
}
|
||||
|
||||
bool SuperEMA_HadCciOversoldRecently(SuperEMAData &d)
|
||||
{
|
||||
for(int i = 2; i <= d.pullbackCciLookback + 1; i++)
|
||||
{
|
||||
double v = SuperEMA_CciAt(d, i);
|
||||
if(v <= d.cciOversold)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SuperEMA_HadCciOverboughtRecently(SuperEMAData &d)
|
||||
{
|
||||
for(int i = 2; i <= d.pullbackCciLookback + 1; i++)
|
||||
{
|
||||
double v = SuperEMA_CciAt(d, i);
|
||||
if(v >= d.cciOverbought)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SuperEMA_PullbackNearFastEmaLong(SuperEMAData &d)
|
||||
{
|
||||
double emaF = SuperEMA_EmaAt(d, d.emaFast, 1);
|
||||
double lo = iLow(d.symbol, d.tf, 1);
|
||||
if(emaF <= 0.0)
|
||||
return false;
|
||||
return (lo <= emaF + d.slBufferPoints * _Point * 3.0);
|
||||
}
|
||||
|
||||
bool SuperEMA_PullbackNearFastEmaShort(SuperEMAData &d)
|
||||
{
|
||||
double emaF = SuperEMA_EmaAt(d, d.emaFast, 1);
|
||||
double hi = iHigh(d.symbol, d.tf, 1);
|
||||
if(emaF <= 0.0)
|
||||
return false;
|
||||
return (hi >= emaF - d.slBufferPoints * _Point * 3.0);
|
||||
}
|
||||
|
||||
int SuperEMA_PositionsByMagic(SuperEMAData &d)
|
||||
{
|
||||
int n = 0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong t = PositionGetTicket(i);
|
||||
if(t == 0)
|
||||
continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) == d.symbol && (int)PositionGetInteger(POSITION_MAGIC) == d.magic)
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void SuperEMA_ComputeSLTP(SuperEMAData &d, const bool isBuy, double &sl, double &tp)
|
||||
{
|
||||
sl = 0.0;
|
||||
tp = 0.0;
|
||||
if(!d.useStructuralSL)
|
||||
return;
|
||||
double emaM = SuperEMA_EmaAt(d, d.emaMid, d.emaTrendBars);
|
||||
double buf = d.slBufferPoints * _Point;
|
||||
if(isBuy)
|
||||
sl = emaM - buf;
|
||||
else
|
||||
sl = emaM + buf;
|
||||
}
|
||||
|
||||
int SuperEMA_BarsSinceOpen(SuperEMAData &d, const datetime openTime)
|
||||
{
|
||||
if(openTime <= 0)
|
||||
return 0;
|
||||
int sh = iBarShift(d.symbol, d.tf, openTime, false);
|
||||
if(sh < 0)
|
||||
return 999999;
|
||||
return sh;
|
||||
}
|
||||
|
||||
void SuperEMA_CloseTicket(SuperEMAData &d, const ulong ticket, const string reason)
|
||||
{
|
||||
d.trade.SetExpertMagicNumber(d.magic);
|
||||
if(d.trade.PositionClose(ticket))
|
||||
SuperEMA_Log(d, "Close: " + reason);
|
||||
}
|
||||
|
||||
void SuperEMA_ManageExits(SuperEMAData &d)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if(ticket == 0)
|
||||
continue;
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) != d.symbol)
|
||||
continue;
|
||||
if((int)PositionGetInteger(POSITION_MAGIC) != d.magic)
|
||||
continue;
|
||||
|
||||
ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
|
||||
|
||||
double h1 = 0.0;
|
||||
if(!SuperEMA_MacdHistAt(d, 1, h1))
|
||||
continue;
|
||||
|
||||
bool closeLong = false;
|
||||
bool closeShort = false;
|
||||
string reason = "";
|
||||
|
||||
if(d.maxHoldingBars > 0)
|
||||
{
|
||||
int held = SuperEMA_BarsSinceOpen(d, openTime);
|
||||
if(held >= d.maxHoldingBars)
|
||||
{
|
||||
if(ptype == POSITION_TYPE_BUY)
|
||||
closeLong = true;
|
||||
else
|
||||
closeShort = true;
|
||||
reason = "time stop (max bars)";
|
||||
}
|
||||
}
|
||||
|
||||
if(ptype == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(d.exitOnTrendFlip && SuperEMA_TrendDown(d, d.emaTrendBars))
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "trend flip (below slow EMA)";
|
||||
}
|
||||
if(d.exitOnMacdFlip && h1 < 0.0)
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "MACD histogram < 0";
|
||||
}
|
||||
if(d.exitOnCciZeroCross && SuperEMA_CciCrossBelowZero(d))
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "CCI crossed below zero";
|
||||
}
|
||||
if(d.exitBelowMidEma)
|
||||
{
|
||||
double c = iClose(d.symbol, d.tf, 1);
|
||||
double emaM = SuperEMA_EmaAt(d, d.emaMid, 1);
|
||||
if(emaM > 0.0 && c < emaM)
|
||||
{
|
||||
closeLong = true;
|
||||
reason = "close below mid EMA";
|
||||
}
|
||||
}
|
||||
if(closeLong)
|
||||
SuperEMA_CloseTicket(d, ticket, reason);
|
||||
}
|
||||
else if(ptype == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(d.exitOnTrendFlip && SuperEMA_TrendUp(d, d.emaTrendBars))
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "trend flip (above slow EMA)";
|
||||
}
|
||||
if(d.exitOnMacdFlip && h1 > 0.0)
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "MACD histogram > 0";
|
||||
}
|
||||
if(d.exitOnCciZeroCross && SuperEMA_CciCrossAboveZero(d))
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "CCI crossed above zero";
|
||||
}
|
||||
if(d.exitBelowMidEma)
|
||||
{
|
||||
double c = iClose(d.symbol, d.tf, 1);
|
||||
double emaM = SuperEMA_EmaAt(d, d.emaMid, 1);
|
||||
if(emaM > 0.0 && c > emaM)
|
||||
{
|
||||
closeShort = true;
|
||||
reason = "close above mid EMA";
|
||||
}
|
||||
}
|
||||
if(closeShort)
|
||||
SuperEMA_CloseTicket(d, ticket, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InitSuperEMA(SuperEMAData &d,
|
||||
const string symbol,
|
||||
const ENUM_TIMEFRAMES tf,
|
||||
const int slippagePoints,
|
||||
const int magic,
|
||||
const int emaFast,
|
||||
const int emaMid,
|
||||
const int emaSlow,
|
||||
const int emaTrendBars,
|
||||
const int cciPeriod,
|
||||
const double cciOverbought,
|
||||
const double cciOversold,
|
||||
const int pullbackCciLookback,
|
||||
const int macdFast,
|
||||
const int macdSlow,
|
||||
const int macdSignal,
|
||||
const ENUM_SE_ENTRY_STYLE entryStyle,
|
||||
const bool oneTradeOnly,
|
||||
const bool useStructuralSL,
|
||||
const double slBufferPoints,
|
||||
const bool exitOnTrendFlip,
|
||||
const bool exitOnMacdFlip,
|
||||
const bool exitOnCciZeroCross,
|
||||
const int maxHoldingBars,
|
||||
const bool exitBelowMidEma,
|
||||
const bool debugLogs)
|
||||
{
|
||||
d.symbol = symbol;
|
||||
if(StringLen(d.symbol) == 0)
|
||||
d.symbol = _Symbol;
|
||||
d.tf = tf;
|
||||
d.lastBarTime = 0;
|
||||
d.isInitialized = false;
|
||||
d.slippagePoints = slippagePoints;
|
||||
d.magic = magic;
|
||||
d.emaFast = emaFast;
|
||||
d.emaMid = emaMid;
|
||||
d.emaSlow = emaSlow;
|
||||
d.emaTrendBars = emaTrendBars;
|
||||
d.cciPeriod = cciPeriod;
|
||||
d.cciOverbought = cciOverbought;
|
||||
d.cciOversold = cciOversold;
|
||||
d.pullbackCciLookback = pullbackCciLookback;
|
||||
d.macdFast = macdFast;
|
||||
d.macdSlow = macdSlow;
|
||||
d.macdSignal = macdSignal;
|
||||
d.entryStyle = entryStyle;
|
||||
d.oneTradeOnly = oneTradeOnly;
|
||||
d.useStructuralSL = useStructuralSL;
|
||||
d.slBufferPoints = slBufferPoints;
|
||||
d.exitOnTrendFlip = exitOnTrendFlip;
|
||||
d.exitOnMacdFlip = exitOnMacdFlip;
|
||||
d.exitOnCciZeroCross = exitOnCciZeroCross;
|
||||
d.maxHoldingBars = maxHoldingBars;
|
||||
d.exitBelowMidEma = exitBelowMidEma;
|
||||
d.debugLogs = debugLogs;
|
||||
|
||||
if(!SymbolSelect(d.symbol, true))
|
||||
{
|
||||
Print("SuperEMA: symbol not available: ", d.symbol);
|
||||
return false;
|
||||
}
|
||||
d.trade.SetExpertMagicNumber(d.magic);
|
||||
d.trade.SetDeviationInPoints(d.slippagePoints);
|
||||
d.isInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProcessSuperEMA(SuperEMAData &d, const double lots)
|
||||
{
|
||||
if(!d.isInitialized)
|
||||
return;
|
||||
|
||||
if(!SuperEMA_IsNewBar(d))
|
||||
return;
|
||||
|
||||
SuperEMA_ManageExits(d);
|
||||
|
||||
if(d.oneTradeOnly && SuperEMA_PositionsByMagic(d) > 0)
|
||||
return;
|
||||
|
||||
const int sh = d.emaTrendBars;
|
||||
double h1 = 0.0, h2 = 0.0;
|
||||
if(!SuperEMA_MacdHistAt(d, 1, h1) || !SuperEMA_MacdHistAt(d, 2, h2))
|
||||
return;
|
||||
|
||||
bool up = SuperEMA_TrendUp(d, sh);
|
||||
bool dn = SuperEMA_TrendDown(d, sh);
|
||||
|
||||
bool wantBuy = false;
|
||||
bool wantSell = false;
|
||||
|
||||
switch(d.entryStyle)
|
||||
{
|
||||
case SE_ENTRY_CCIZERO_MACD:
|
||||
if(up && SuperEMA_CciCrossAboveZero(d) && h1 > 0.0)
|
||||
wantBuy = true;
|
||||
if(dn && SuperEMA_CciCrossBelowZero(d) && h1 < 0.0)
|
||||
wantSell = true;
|
||||
break;
|
||||
|
||||
case SE_ENTRY_LAMBERT:
|
||||
if(up && SuperEMA_CciCrossAbove100(d) && h1 > 0.0)
|
||||
wantBuy = true;
|
||||
if(dn && SuperEMA_CciCrossBelowMinus100(d) && h1 < 0.0)
|
||||
wantSell = true;
|
||||
break;
|
||||
|
||||
case SE_ENTRY_PULLBACK:
|
||||
if(up && SuperEMA_HadCciOversoldRecently(d) && SuperEMA_CciCrossAboveZero(d) && h1 > 0.0 && SuperEMA_PullbackNearFastEmaLong(d))
|
||||
wantBuy = true;
|
||||
if(dn && SuperEMA_HadCciOverboughtRecently(d) && SuperEMA_CciCrossBelowZero(d) && h1 < 0.0 && SuperEMA_PullbackNearFastEmaShort(d))
|
||||
wantSell = true;
|
||||
break;
|
||||
}
|
||||
|
||||
MqlTick tick;
|
||||
if(!SymbolInfoTick(d.symbol, tick))
|
||||
return;
|
||||
|
||||
double sl = 0.0, tp = 0.0;
|
||||
|
||||
if(wantBuy && !wantSell)
|
||||
{
|
||||
SuperEMA_ComputeSLTP(d, true, sl, tp);
|
||||
if(d.trade.Buy(lots, d.symbol, tick.ask, sl, tp, "United SuperEMA long"))
|
||||
SuperEMA_Log(d, StringFormat("BUY ask=%.5f sl=%.5f", tick.ask, sl));
|
||||
}
|
||||
else if(wantSell && !wantBuy)
|
||||
{
|
||||
SuperEMA_ComputeSLTP(d, false, sl, tp);
|
||||
if(d.trade.Sell(lots, d.symbol, tick.bid, sl, tp, "United SuperEMA short"))
|
||||
SuperEMA_Log(d, StringFormat("SELL bid=%.5f sl=%.5f", tick.bid, sl));
|
||||
}
|
||||
}
|
||||
|
||||
void DeinitSuperEMA(SuperEMAData &d)
|
||||
{
|
||||
d.isInitialized = false;
|
||||
}
|
||||
|
||||
#endif // SUPER_EMA_STRATEGY_MQH
|
||||
@@ -0,0 +1,437 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| UnitedProfitPanel.mqh — chart object P&L by strategy / magic |
|
||||
//| One OBJ_LABEL per line (MT5 often ignores \n in a single label). |
|
||||
//| Include only after all United EA `input` declarations. |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef UNITED_PROFIT_PANEL_MQH
|
||||
#define UNITED_PROFIT_PANEL_MQH
|
||||
|
||||
#define UNITED_PNL_MAX_LINES 48
|
||||
|
||||
struct UnitedPnLRow
|
||||
{
|
||||
string name;
|
||||
long magic;
|
||||
};
|
||||
|
||||
UnitedPnLRow g_unitedPnLRows[];
|
||||
int g_unitedPnLRowCount = 0;
|
||||
int g_unitedPnL_visibleLineCount = 0;
|
||||
|
||||
string UnitedPnL_Obj(const string suffix) { return "UnitedPnL_" + suffix; }
|
||||
|
||||
long UnitedPnL_ChartId() { return ChartID(); }
|
||||
|
||||
string UnitedPnL_LineObjName(const int idx) { return UnitedPnL_Obj("L") + IntegerToString(idx); }
|
||||
|
||||
datetime UnitedPnL_StartOfYear(const datetime now)
|
||||
{
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(now, dt);
|
||||
dt.mon = 1;
|
||||
dt.day = 1;
|
||||
dt.hour = 0;
|
||||
dt.min = 0;
|
||||
dt.sec = 0;
|
||||
return StructToTime(dt);
|
||||
}
|
||||
|
||||
datetime UnitedPnL_StartOfMonth(const datetime now)
|
||||
{
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(now, dt);
|
||||
dt.day = 1;
|
||||
dt.hour = 0;
|
||||
dt.min = 0;
|
||||
dt.sec = 0;
|
||||
return StructToTime(dt);
|
||||
}
|
||||
|
||||
int UnitedPnL_FindRowIndex(const long magic)
|
||||
{
|
||||
for(int r = 0; r < g_unitedPnLRowCount; r++)
|
||||
{
|
||||
if(g_unitedPnLRows[r].magic == magic)
|
||||
return r;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool UnitedPnL_ScanDealsOnce(double &yearPl[], double &monthPl[], const datetime y0, const datetime m0, const datetime now)
|
||||
{
|
||||
const int R = g_unitedPnLRowCount;
|
||||
ArrayResize(yearPl, R);
|
||||
ArrayResize(monthPl, R);
|
||||
for(int j = 0; j < R; j++)
|
||||
{
|
||||
yearPl[j] = 0.0;
|
||||
monthPl[j] = 0.0;
|
||||
}
|
||||
|
||||
if(R <= 0 || y0 >= now)
|
||||
return true;
|
||||
|
||||
datetime to = now;
|
||||
if(to <= y0)
|
||||
to = y0 + 1;
|
||||
|
||||
if(!HistorySelect(y0, to))
|
||||
return false;
|
||||
|
||||
const int n = HistoryDealsTotal();
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
const ulong dealTicket = HistoryDealGetTicket(i);
|
||||
if(dealTicket == 0)
|
||||
continue;
|
||||
|
||||
const long mg = (long)HistoryDealGetInteger(dealTicket, DEAL_MAGIC);
|
||||
const int idx = UnitedPnL_FindRowIndex(mg);
|
||||
if(idx < 0)
|
||||
continue;
|
||||
|
||||
const datetime dt = (datetime)HistoryDealGetInteger(dealTicket, DEAL_TIME);
|
||||
const double p = HistoryDealGetDouble(dealTicket, DEAL_PROFIT)
|
||||
+ HistoryDealGetDouble(dealTicket, DEAL_SWAP)
|
||||
+ HistoryDealGetDouble(dealTicket, DEAL_COMMISSION);
|
||||
|
||||
yearPl[idx] += p;
|
||||
if(dt >= m0)
|
||||
monthPl[idx] += p;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double UnitedPnL_SumFloatingForMagic(const long magic)
|
||||
{
|
||||
double sum = 0.0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
const ulong ticket = PositionGetTicket(i);
|
||||
if(ticket == 0)
|
||||
continue;
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
continue;
|
||||
if((long)PositionGetInteger(POSITION_MAGIC) != magic)
|
||||
continue;
|
||||
sum += PositionGetDouble(POSITION_PROFIT);
|
||||
sum += PositionGetDouble(POSITION_SWAP);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void UnitedPnL_CollectRows()
|
||||
{
|
||||
g_unitedPnLRowCount = 0;
|
||||
ArrayResize(g_unitedPnLRows, 24);
|
||||
|
||||
if(EnableDarvasBox)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "DarvasBox";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)DB_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableEMASlopeDistance)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "EMASlope";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)ES_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSICrossOverReversal)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RSICrossOver";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RC_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIMidPointHijack)
|
||||
{
|
||||
if(RM_InpEnableRSIFollow)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RM_RSIFollow";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RM_InpMagicNumberRSIFollow;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(RM_InpEnableRSIReverse)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RM_RSIRev";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RM_InpMagicNumberRSIReverse;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(RM_InpEnableEMACross)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RM_EMACross";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RM_InpMagicNumberEMACross;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
}
|
||||
if(EnableRSIScalpingAPPL)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_AAPL";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_APPL_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingBTCUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_BTC";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_BTCUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingNVDA)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_NVDA";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_NVDA_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingTSLA)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_TSLA";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_TSLA_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingXAUUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_XAU";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_XAUUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIReversalEURUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RRA_EURUSD";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RRA_EURUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIReversalAUDUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RRA_AUDUSD";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RRA_AUDUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSISecretSauceXAUUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "SecretSauce";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RSS_XAUUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableSuperEMA)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "SuperEMA";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)SE_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
|
||||
ArrayResize(g_unitedPnLRows, MathMax(g_unitedPnLRowCount, 1));
|
||||
}
|
||||
|
||||
void UnitedPnL_EnsureObjects()
|
||||
{
|
||||
const long ch = UnitedPnL_ChartId();
|
||||
const string bg = UnitedPnL_Obj("BG");
|
||||
if(ObjectFind(ch, bg) < 0)
|
||||
{
|
||||
if(!ObjectCreate(ch, bg, OBJ_RECTANGLE_LABEL, 0, 0, 0))
|
||||
{
|
||||
Print("UnitedPnL: BG ObjectCreate failed, err=", GetLastError());
|
||||
return;
|
||||
}
|
||||
ObjectSetInteger(ch, bg, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_COLOR, C'90,90,90');
|
||||
ObjectSetInteger(ch, bg, OBJPROP_BGCOLOR, C'25,25,30');
|
||||
ObjectSetInteger(ch, bg, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_HIDDEN, false);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_ZORDER, 0);
|
||||
}
|
||||
|
||||
for(int i = 0; i < UNITED_PNL_MAX_LINES; i++)
|
||||
{
|
||||
const string nm = UnitedPnL_LineObjName(i);
|
||||
if(ObjectFind(ch, nm) >= 0)
|
||||
continue;
|
||||
if(!ObjectCreate(ch, nm, OBJ_LABEL, 0, 0, 0))
|
||||
{
|
||||
Print("UnitedPnL: line ", i, " ObjectCreate failed, err=", GetLastError());
|
||||
continue;
|
||||
}
|
||||
ObjectSetString(ch, nm, OBJPROP_FONT, "Arial");
|
||||
ObjectSetInteger(ch, nm, OBJPROP_FONTSIZE, UnitedPanel_FontSize);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_HIDDEN, false);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_ZORDER, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedPnL_ApplyGeometry()
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
const long ch = UnitedPnL_ChartId();
|
||||
const string bg = UnitedPnL_Obj("BG");
|
||||
if(ObjectFind(ch, bg) < 0)
|
||||
return;
|
||||
|
||||
const int lineH = UnitedPanel_FontSize + 5;
|
||||
const int vis = MathMax(g_unitedPnL_visibleLineCount, 6);
|
||||
const int h = UnitedPanel_YMargin * 2 + lineH * vis;
|
||||
|
||||
const ENUM_BASE_CORNER corner = (ENUM_BASE_CORNER)UnitedPanel_Corner;
|
||||
ObjectSetInteger(ch, bg, OBJPROP_CORNER, corner);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_XDISTANCE, UnitedPanel_X);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_YDISTANCE, UnitedPanel_Y);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_XSIZE, UnitedPanel_Width);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_YSIZE, MathMax(h, 80));
|
||||
|
||||
const int baseX = UnitedPanel_X + UnitedPanel_XMargin;
|
||||
const int baseY = UnitedPanel_Y + UnitedPanel_YMargin;
|
||||
for(int i = 0; i < UNITED_PNL_MAX_LINES; i++)
|
||||
{
|
||||
const string nm = UnitedPnL_LineObjName(i);
|
||||
if(ObjectFind(ch, nm) < 0)
|
||||
continue;
|
||||
ObjectSetInteger(ch, nm, OBJPROP_CORNER, corner);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_XDISTANCE, baseX);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_YDISTANCE, baseY + i * lineH);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_FONTSIZE, UnitedPanel_FontSize);
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedPnL_RefreshText()
|
||||
{
|
||||
const long ch = UnitedPnL_ChartId();
|
||||
const string bg = UnitedPnL_Obj("BG");
|
||||
if(ObjectFind(ch, bg) < 0)
|
||||
return;
|
||||
|
||||
UnitedPnL_CollectRows();
|
||||
|
||||
const datetime now = TimeCurrent();
|
||||
const datetime y0 = UnitedPnL_StartOfYear(now);
|
||||
const datetime m0 = UnitedPnL_StartOfMonth(now);
|
||||
const string cur = AccountInfoString(ACCOUNT_CURRENCY);
|
||||
|
||||
double yearPl[];
|
||||
double monthPl[];
|
||||
const bool histOk = UnitedPnL_ScanDealsOnce(yearPl, monthPl, y0, m0, now);
|
||||
const string histNote = histOk ? "" : " [hist fail: Toolbox>History]";
|
||||
|
||||
double sumY = 0.0, sumM = 0.0, sumF = 0.0;
|
||||
|
||||
string lines[];
|
||||
int n = 0;
|
||||
ArrayResize(lines, UNITED_PNL_MAX_LINES);
|
||||
|
||||
lines[n++] = "United EA " + cur + histNote;
|
||||
lines[n++] = UnitedPanel_ShowFloating
|
||||
? "Y/M = closed deals | F = open P/L+swap"
|
||||
: "Y/M = closed deal P/L+swap+comm";
|
||||
lines[n++] = "----------------------------------";
|
||||
|
||||
for(int r = 0; r < g_unitedPnLRowCount; r++)
|
||||
{
|
||||
const long mg = g_unitedPnLRows[r].magic;
|
||||
double yv = 0.0, mv = 0.0;
|
||||
if(histOk && r < ArraySize(yearPl))
|
||||
yv = yearPl[r];
|
||||
if(histOk && r < ArraySize(monthPl))
|
||||
mv = monthPl[r];
|
||||
const double fv = UnitedPanel_ShowFloating ? UnitedPnL_SumFloatingForMagic(mg) : 0.0;
|
||||
sumY += yv;
|
||||
sumM += mv;
|
||||
sumF += fv;
|
||||
}
|
||||
|
||||
string tot = "TOTAL Y:" + DoubleToString(sumY, 2) + " M:" + DoubleToString(sumM, 2);
|
||||
if(UnitedPanel_ShowFloating)
|
||||
tot += " F:" + DoubleToString(sumF, 2);
|
||||
lines[n++] = tot;
|
||||
lines[n++] = "----------------------------------";
|
||||
|
||||
if(g_unitedPnLRowCount == 0)
|
||||
lines[n++] = "(no strategies enabled)";
|
||||
else
|
||||
{
|
||||
for(int r = 0; r < g_unitedPnLRowCount; r++)
|
||||
{
|
||||
if(n >= UNITED_PNL_MAX_LINES - 1)
|
||||
break;
|
||||
const long mg = g_unitedPnLRows[r].magic;
|
||||
double yv = 0.0, mv = 0.0;
|
||||
if(histOk && r < ArraySize(yearPl))
|
||||
yv = yearPl[r];
|
||||
if(histOk && r < ArraySize(monthPl))
|
||||
mv = monthPl[r];
|
||||
const double fv = UnitedPanel_ShowFloating ? UnitedPnL_SumFloatingForMagic(mg) : 0.0;
|
||||
|
||||
lines[n++] = g_unitedPnLRows[r].name + " [" + IntegerToString((int)mg) + "]";
|
||||
string row2 = " Y:" + DoubleToString(yv, 2) + " M:" + DoubleToString(mv, 2);
|
||||
if(UnitedPanel_ShowFloating)
|
||||
row2 += " F:" + DoubleToString(fv, 2);
|
||||
lines[n++] = row2;
|
||||
}
|
||||
}
|
||||
|
||||
g_unitedPnL_visibleLineCount = n;
|
||||
|
||||
color c = clrSilver;
|
||||
if(sumM > 0.0001)
|
||||
c = clrPaleGreen;
|
||||
else if(sumM < -0.0001)
|
||||
c = clrTomato;
|
||||
|
||||
for(int i = 0; i < UNITED_PNL_MAX_LINES; i++)
|
||||
{
|
||||
const string nm = UnitedPnL_LineObjName(i);
|
||||
if(ObjectFind(ch, nm) < 0)
|
||||
continue;
|
||||
if(i < n)
|
||||
{
|
||||
ObjectSetString(ch, nm, OBJPROP_TEXT, lines[i]);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_COLOR, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectSetString(ch, nm, OBJPROP_TEXT, "");
|
||||
}
|
||||
}
|
||||
|
||||
UnitedPnL_ApplyGeometry();
|
||||
ChartRedraw(ch);
|
||||
}
|
||||
|
||||
void UnitedProfitPanelInit()
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
UnitedPnL_EnsureObjects();
|
||||
UnitedPnL_CollectRows();
|
||||
g_unitedPnL_visibleLineCount = 6;
|
||||
UnitedPnL_ApplyGeometry();
|
||||
UnitedPnL_RefreshText();
|
||||
}
|
||||
|
||||
void UnitedProfitPanelDeinit()
|
||||
{
|
||||
ObjectsDeleteAll(UnitedPnL_ChartId(), "UnitedPnL_");
|
||||
}
|
||||
|
||||
void UnitedProfitPanelRefresh()
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
UnitedPnL_RefreshText();
|
||||
}
|
||||
|
||||
void UnitedProfitPanelOnChartEvent(const int id)
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
if(id == CHARTEVENT_CHART_CHANGE)
|
||||
{
|
||||
UnitedPnL_CollectRows();
|
||||
UnitedPnL_ApplyGeometry();
|
||||
ChartRedraw(UnitedPnL_ChartId());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.07"
|
||||
#property version "1.17"
|
||||
#property strict
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
@@ -20,6 +20,8 @@ double g_RC_LotSize;
|
||||
double g_RM_LotSize;
|
||||
double g_DB_LotSize;
|
||||
double g_DynMultLast = 1.0;
|
||||
double g_equityPeakHighWater = 0.0; // for drawdown lot cap (updated each tick via Refresh)
|
||||
datetime g_ddLotCapAnchorTime = 0; // tester/attach start — grace period before DD cap may apply
|
||||
|
||||
// Include strategy implementations early so structs are available
|
||||
#include "Strategies/DarvasBoxStrategy.mqh"
|
||||
@@ -28,6 +30,8 @@ double g_DynMultLast = 1.0;
|
||||
#include "Strategies/RSIMidPointHijackStrategy.mqh"
|
||||
#include "Strategies/RSIScalpingStrategy.mqh"
|
||||
#include "Strategies/RSIReversalAsianStrategy.mqh"
|
||||
#include "Strategies/RSISecretSauceStrategy.mqh"
|
||||
#include "Strategies/SuperEMAStrategy.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy Enable/Disable Switches |
|
||||
@@ -42,8 +46,41 @@ input bool EnableRSIScalpingBTCUSD = true;
|
||||
input bool EnableRSIScalpingNVDA = true;
|
||||
input bool EnableRSIScalpingTSLA = true;
|
||||
input bool EnableRSIScalpingXAUUSD = true;
|
||||
input bool EnableRSIReversalAsianEURUSD = true;
|
||||
input bool EnableRSIReversalAsianAUDUSD = true;
|
||||
input bool EnableRSIReversalEURUSD = true; // RSI Reversal Asian session (EURUSD)
|
||||
input bool EnableRSIReversalAUDUSD = true; // RSI Reversal Asian session (AUDUSD)
|
||||
input bool EnableRSISecretSauceXAUUSD = true;
|
||||
input bool EnableSuperEMA = true;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| SuperEMA — EMA + CCI + MACD (XAUUSD default) |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== SuperEMA (EMA + CCI + MACD) ==="
|
||||
input string SE_Symbol = "XAUUSD";
|
||||
input ENUM_TIMEFRAMES SE_Timeframe = PERIOD_M15;
|
||||
input double SE_LotSize = 0.01;
|
||||
input int SE_SlippagePoints = 55;
|
||||
input int SE_MagicNumber = 940001;
|
||||
input int SE_EmaFast = 40;
|
||||
input int SE_EmaMid = 180;
|
||||
input int SE_EmaSlow = 125;
|
||||
input int SE_EmaTrendBars = 3;
|
||||
input int SE_CciPeriod = 17;
|
||||
input double SE_CciOverbought = 80.0;
|
||||
input double SE_CciOversold = -140.0;
|
||||
input int SE_PullbackCciLookback = 20;
|
||||
input int SE_MacdFast = 14;
|
||||
input int SE_MacdSlow = 38;
|
||||
input int SE_MacdSignal = 9;
|
||||
input ENUM_SE_ENTRY_STYLE SE_EntryStyle = SE_ENTRY_LAMBERT;
|
||||
input bool SE_OneTradeOnly = true;
|
||||
input bool SE_UseStructuralSL = false;
|
||||
input double SE_SlBufferPoints = 110;
|
||||
input bool SE_ExitOnTrendFlip = false;
|
||||
input bool SE_ExitOnMacdFlip = false;
|
||||
input bool SE_ExitOnCciZeroCross = true;
|
||||
input int SE_MaxHoldingBars = 168;
|
||||
input bool SE_ExitBelowMidEma = false;
|
||||
input bool SE_DebugLogs = false;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dynamic lot sizing — scale base lots vs reference deposit |
|
||||
@@ -58,6 +95,21 @@ input double InpDynamicMaxMult = 0.0; // <=0 动态倍数不封
|
||||
input bool InpDynamicUseEquity = true; // true=ACCOUNT_EQUITY, false=ACCOUNT_BALANCE
|
||||
input double InpDynamicStockLotCap = 0.0; // Extra cap for stock CFDs (0 = none)
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lot cap: optional account-wide DD from peak, and/or per-strategy |
|
||||
//| (last *closed* calendar month losing for that magic). |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Drawdown / loser lot cap ==="
|
||||
input bool InpDdLotCapEnable = true; // master: allow clamping when a mode below triggers
|
||||
input bool InpDdLotCapGlobalEquityEnable = false; // cap *all* robots when equity DD from peak >= X% (after grace)
|
||||
input bool InpDdLotCapPerStratEnable = true; // cap only robots whose last closed month was red (by magic)
|
||||
input bool InpDdLotCapUseEquity = true; // true=ACCOUNT_EQUITY, false=BALANCE (global mode + peak tracking)
|
||||
input double InpDdLotCapFromPeakPercent = 7.0; // global: trigger if (peak-equity)/peak*100 >= this
|
||||
input double InpDdLotCapMaxLots = 0.01; // max volume per order while that mode is triggered
|
||||
input int InpDdLotCapGraceDays = 90; // global only: wait N days from attach before DD cap can apply (0=immediate)
|
||||
input double InpDdLotCapStratLossThreshold = 0.0; // per-strat: month P/L < -this counts as losing (0 = any loss)
|
||||
input int InpDdLotCapUpdateSeconds = 3600; // min 60; refresh last-month P/L when adaptive monthly is off
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 1: DarvasBoxXAUUSD |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -267,12 +319,34 @@ input int RS_XAUUSD_MagicNumber = 129102315;
|
||||
input int RS_XAUUSD_Slippage = 3;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 11-12: RSI Reversal Asian Strategies |
|
||||
//| Each RSI Reversal Asian strategy trades on its own symbol: |
|
||||
//| - EURUSD: Euro/USD |
|
||||
//| - AUDUSD: Australian Dollar/USD |
|
||||
//| Strategy: RSI Secret Sauce XAUUSD (leave zone → re-entry peak/bottom) |
|
||||
//| Defaults match secret_sauce.set except symbol stays XAUUSD here. |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== RSI Reversal Asian EURUSD ==="
|
||||
input group "=== RSI Secret Sauce XAUUSD ==="
|
||||
input string RSS_XAUUSD_Symbol = "XAUUSD"; // not BTCUSD — gold chart / portfolio default
|
||||
input double RSS_XAUUSD_LotSize = 0.1;
|
||||
input int RSS_XAUUSD_MagicNumber = 789012;
|
||||
input int RSS_XAUUSD_Slippage = 10;
|
||||
input ENUM_TIMEFRAMES RSS_XAUUSD_Timeframe = PERIOD_M30;
|
||||
input int RSS_XAUUSD_RSIPeriod = 16;
|
||||
input double RSS_XAUUSD_RSIOverbought = 72.5;
|
||||
input double RSS_XAUUSD_RSIOversold = 32.5;
|
||||
input int RSS_XAUUSD_RSILookback = 60;
|
||||
input int RSS_XAUUSD_PeakBars = 2;
|
||||
input bool RSS_XAUUSD_RequireDivergence = false;
|
||||
input double RSS_XAUUSD_StopLossATR = 2.75;
|
||||
input double RSS_XAUUSD_TakeProfitATR = 5.0;
|
||||
input int RSS_XAUUSD_ATRPeriod = 14;
|
||||
input bool RSS_XAUUSD_UseSwingStopLoss = false;
|
||||
input int RSS_XAUUSD_SwingLookback = 30;
|
||||
input int RSS_XAUUSD_MaxPositions = 1;
|
||||
input int RSS_XAUUSD_MinBarsBetweenTrades = 7;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 11-12: RSI Reversal (Asian session) EURUSD & AUDUSD |
|
||||
//| Same logic as RSIReversalAsianEURUSD / RSIReversalAsianAUDUSD EAs |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== RSI Reversal EURUSD (Asian session) ==="
|
||||
input string RRA_EURUSD_Symbol = "EURUSD";
|
||||
input int RRA_EURUSD_RSIPeriod = 28;
|
||||
input double RRA_EURUSD_OverboughtLevel = 60;
|
||||
@@ -291,7 +365,7 @@ input ENUM_TIMEFRAMES RRA_EURUSD_TimeFrame = PERIOD_M15;
|
||||
input int RRA_EURUSD_MagicNumber = 30001;
|
||||
input int RRA_EURUSD_Slippage = 3;
|
||||
|
||||
input group "=== RSI Reversal Asian AUDUSD ==="
|
||||
input group "=== RSI Reversal AUDUSD (Asian session) ==="
|
||||
input string RRA_AUDUSD_Symbol = "AUDUSD";
|
||||
input int RRA_AUDUSD_RSIPeriod = 28;
|
||||
input double RRA_AUDUSD_OverboughtLevel = 68;
|
||||
@@ -310,6 +384,46 @@ input ENUM_TIMEFRAMES RRA_AUDUSD_TimeFrame = PERIOD_M15;
|
||||
input int RRA_AUDUSD_MagicNumber = 30002;
|
||||
input int RRA_AUDUSD_Slippage = 3;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chart panel: closed-deal P&L by strategy (magic) + optional open |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Chart profit panel (by magic) ==="
|
||||
input bool UnitedPanel_Enable = false; // OBJ_LABEL + background on chart
|
||||
input int UnitedPanel_Seconds = 60; // refresh interval (min 5); history scan once per tick
|
||||
input int UnitedPanel_Corner = 0; // ENUM_BASE_CORNER e.g. 0=left upper
|
||||
input int UnitedPanel_X = 8;
|
||||
input int UnitedPanel_Y = 24;
|
||||
input int UnitedPanel_Width = 360;
|
||||
input int UnitedPanel_FontSize = 9;
|
||||
input int UnitedPanel_XMargin = 6;
|
||||
input int UnitedPanel_YMargin = 6;
|
||||
input bool UnitedPanel_ShowFloating = false; // open P/L+swap per magic
|
||||
|
||||
enum ENUM_ADAPTIVE_STREAK_UNIT
|
||||
{
|
||||
ADAPTIVE_STREAK_BY_MONTH = 0, // consecutive closed calendar months
|
||||
ADAPTIVE_STREAK_BY_DAY = 1 // consecutive closed calendar days (server time)
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Pause strategies after consecutive losing periods (month or day)|
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Adaptive regime (per robot / magic) ==="
|
||||
input bool InpAdaptiveEnable = true; // If false, every other InpAdaptive* input is ignored (no streak / canary / pause). Set true to optimize or use adaptive regime.
|
||||
input ENUM_ADAPTIVE_STREAK_UNIT InpAdaptiveStreakUnit = ADAPTIVE_STREAK_BY_DAY;
|
||||
input int InpAdaptiveRedStreak = 5; // consecutive red months OR red days (see streak unit)
|
||||
input double InpAdaptiveRedThreshold = 0.0; // period P/L < -threshold counts red (0 = any loss)
|
||||
input int InpAdaptiveLookbackMonths = 14; // if unit=MONTH: history depth in months (>= streak+1)
|
||||
input int InpAdaptiveLookbackDays = 36; // if unit=DAY: closed days of history (>= streak+1)
|
||||
input int InpAdaptiveUpdateSeconds = 3600; // min 60; how often to recompute
|
||||
input double InpAdaptiveCanaryLotMult = 0.07; // probation: scale lots (0 = hard pause on streak, no canary)
|
||||
input int InpAdaptiveHardRetryMonths = 3; // if unit=MONTH: 0=no auto retry; else retry after N months
|
||||
input int InpAdaptiveHardRetryDays = 32; // if unit=DAY: 0=no auto retry; else retry after N days
|
||||
input int InpAdaptivePostCanaryCooldownDays = 37; // after successful canary, block re-arming another canary (days)
|
||||
|
||||
#include "UnitedProfitPanel.mqh"
|
||||
#include "AdaptiveMonthlyRegime.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables - DarvasBox |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -412,6 +526,8 @@ RSIScalpingData rsXAUUSDData;
|
||||
//+------------------------------------------------------------------+
|
||||
RSIReversalAsianData rraEURUSDData;
|
||||
RSIReversalAsianData rraAUDUSDData;
|
||||
RSISecretSauceData rsSecretSauceXAUUSDData;
|
||||
SuperEMAData seData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dynamic lot helpers |
|
||||
@@ -444,6 +560,53 @@ double NormalizeVolumeForSymbol(const string symbol, double lots)
|
||||
return lots;
|
||||
}
|
||||
|
||||
void UpdateEquityPeakForDdCap()
|
||||
{
|
||||
if(!InpDdLotCapEnable || !InpDdLotCapGlobalEquityEnable)
|
||||
return;
|
||||
const double cur = InpDdLotCapUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(cur > g_equityPeakHighWater)
|
||||
g_equityPeakHighWater = cur;
|
||||
}
|
||||
|
||||
// After dynamic sizing: global equity DD and/or per-strategy last-month loser -> clamp to InpDdLotCapMaxLots.
|
||||
double LotsAfterDrawdownCap(const string symbol, const double lotsRaw, const int ddStratId = -1)
|
||||
{
|
||||
double lots = NormalizeVolumeForSymbol(symbol, lotsRaw);
|
||||
if(!InpDdLotCapEnable)
|
||||
return lots;
|
||||
|
||||
bool needCap = false;
|
||||
|
||||
if(InpDdLotCapGlobalEquityEnable)
|
||||
{
|
||||
bool globalCheck = true;
|
||||
if(InpDdLotCapGraceDays > 0 && g_ddLotCapAnchorTime > 0)
|
||||
{
|
||||
const long needSec = (long)InpDdLotCapGraceDays * 86400L;
|
||||
if((long)(TimeCurrent() - g_ddLotCapAnchorTime) < needSec)
|
||||
globalCheck = false;
|
||||
}
|
||||
if(globalCheck && g_equityPeakHighWater > 0.0)
|
||||
{
|
||||
const double cur = InpDdLotCapUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(cur < g_equityPeakHighWater)
|
||||
{
|
||||
const double ddPct = 100.0 * (g_equityPeakHighWater - cur) / g_equityPeakHighWater;
|
||||
if(ddPct >= InpDdLotCapFromPeakPercent)
|
||||
needCap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(InpDdLotCapPerStratEnable && ddStratId >= 0 && UnitedAdaptive_StratLastMonthIsLosing(ddStratId))
|
||||
needCap = true;
|
||||
|
||||
if(!needCap)
|
||||
return lots;
|
||||
return NormalizeVolumeForSymbol(symbol, MathMin(lots, InpDdLotCapMaxLots));
|
||||
}
|
||||
|
||||
double GetDynamicMultiplier()
|
||||
{
|
||||
if(!InpDynamicLotEnable)
|
||||
@@ -460,31 +623,33 @@ double GetDynamicMultiplier()
|
||||
}
|
||||
|
||||
// baseLot = size at reference deposit; optionalCap 0 = no extra ceiling (broker min/max still apply)
|
||||
double DynamicLotForSymbol(const string symbol, const double baseLot, const double optionalCap = 0.0)
|
||||
double DynamicLotForSymbol(const string symbol, const double baseLot, const double optionalCap = 0.0, const int ddStratId = -1)
|
||||
{
|
||||
double mult = GetDynamicMultiplier();
|
||||
g_DynMultLast = mult;
|
||||
double v = baseLot * mult;
|
||||
if(optionalCap > 0.0 && v > optionalCap)
|
||||
v = optionalCap;
|
||||
return NormalizeVolumeForSymbol(symbol, v);
|
||||
return LotsAfterDrawdownCap(symbol, v, ddStratId);
|
||||
}
|
||||
|
||||
void RefreshDynamicStrategyLots()
|
||||
{
|
||||
UpdateEquityPeakForDdCap();
|
||||
|
||||
if(!InpDynamicLotEnable)
|
||||
{
|
||||
g_ES_LotSize = NormalizeVolumeForSymbol(ES_Symbol, ES_LotGröße);
|
||||
g_RC_LotSize = NormalizeVolumeForSymbol(RC_Symbol, RC_lotSize);
|
||||
g_RM_LotSize = NormalizeVolumeForSymbol(RM_Symbol, RM_InpLotSize);
|
||||
g_DB_LotSize = NormalizeVolumeForSymbol(DB_Symbol, DB_BaseLotSize);
|
||||
g_ES_LotSize = LotsAfterDrawdownCap(ES_Symbol, ES_LotGröße * UnitedAdaptive_GetLotMult(UNITED_AD_ES), UNITED_AD_ES);
|
||||
g_RC_LotSize = LotsAfterDrawdownCap(RC_Symbol, RC_lotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RC), UNITED_AD_RC);
|
||||
g_RM_LotSize = LotsAfterDrawdownCap(RM_Symbol, RM_InpLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RM), UNITED_AD_RM);
|
||||
g_DB_LotSize = LotsAfterDrawdownCap(DB_Symbol, DB_BaseLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_DARVAS), UNITED_AD_DARVAS);
|
||||
g_DynMultLast = 1.0;
|
||||
return;
|
||||
}
|
||||
g_ES_LotSize = DynamicLotForSymbol(ES_Symbol, ES_LotGröße);
|
||||
g_RC_LotSize = DynamicLotForSymbol(RC_Symbol, RC_lotSize);
|
||||
g_RM_LotSize = DynamicLotForSymbol(RM_Symbol, RM_InpLotSize);
|
||||
g_DB_LotSize = DynamicLotForSymbol(DB_Symbol, DB_BaseLotSize);
|
||||
g_ES_LotSize = DynamicLotForSymbol(ES_Symbol, ES_LotGröße * UnitedAdaptive_GetLotMult(UNITED_AD_ES), 0.0, UNITED_AD_ES);
|
||||
g_RC_LotSize = DynamicLotForSymbol(RC_Symbol, RC_lotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RC), 0.0, UNITED_AD_RC);
|
||||
g_RM_LotSize = DynamicLotForSymbol(RM_Symbol, RM_InpLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RM), 0.0, UNITED_AD_RM);
|
||||
g_DB_LotSize = DynamicLotForSymbol(DB_Symbol, DB_BaseLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_DARVAS), 0.0, UNITED_AD_DARVAS);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -493,7 +658,16 @@ void RefreshDynamicStrategyLots()
|
||||
int OnInit()
|
||||
{
|
||||
int initResult = INIT_SUCCEEDED;
|
||||
|
||||
|
||||
UnitedAdaptive_Init();
|
||||
|
||||
g_equityPeakHighWater = InpDdLotCapUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(g_equityPeakHighWater <= 0.0)
|
||||
g_equityPeakHighWater = MathMax(InpDynamicRefDeposit, 1.0);
|
||||
g_ddLotCapAnchorTime = TimeCurrent();
|
||||
|
||||
UnitedAdaptive_UpdateIfDue();
|
||||
|
||||
RefreshDynamicStrategyLots();
|
||||
|
||||
// Initialize strategies - log warnings but don't fail entire EA if symbol unavailable
|
||||
@@ -530,21 +704,39 @@ int OnInit()
|
||||
InitRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price, RS_XAUUSD_MagicNumber, RS_XAUUSD_Slippage);
|
||||
|
||||
// Initialize RSI Reversal Asian strategies
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
if(EnableRSIReversalEURUSD)
|
||||
if(!InitRSIReversalAsian(rraEURUSDData, RRA_EURUSD_Symbol, RRA_EURUSD_RSIPeriod, RRA_EURUSD_OverboughtLevel, RRA_EURUSD_OversoldLevel,
|
||||
RRA_EURUSD_TakeProfitPips, RRA_EURUSD_StopLossPips, RRA_EURUSD_MaxLotSize,
|
||||
RRA_EURUSD_MaxSpread, RRA_EURUSD_MaxDuration, RRA_EURUSD_UseStopLoss,
|
||||
RRA_EURUSD_UseTakeProfit, RRA_EURUSD_UseRSIExit, RRA_EURUSD_RSIExitLevel,
|
||||
RRA_EURUSD_CloseOutsideSession, RRA_EURUSD_TimeFrame, RRA_EURUSD_MagicNumber, RRA_EURUSD_Slippage))
|
||||
Print("Warning: RSIReversalAsianEURUSD strategy failed to initialize for symbol '", RRA_EURUSD_Symbol, "'");
|
||||
Print("Warning: RSIReversalEURUSD strategy failed to initialize for symbol '", RRA_EURUSD_Symbol, "'");
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
if(EnableRSIReversalAUDUSD)
|
||||
if(!InitRSIReversalAsian(rraAUDUSDData, RRA_AUDUSD_Symbol, RRA_AUDUSD_RSIPeriod, RRA_AUDUSD_OverboughtLevel, RRA_AUDUSD_OversoldLevel,
|
||||
RRA_AUDUSD_TakeProfitPips, RRA_AUDUSD_StopLossPips, RRA_AUDUSD_MaxLotSize,
|
||||
RRA_AUDUSD_MaxSpread, RRA_AUDUSD_MaxDuration, RRA_AUDUSD_UseStopLoss,
|
||||
RRA_AUDUSD_UseTakeProfit, RRA_AUDUSD_UseRSIExit, RRA_AUDUSD_RSIExitLevel,
|
||||
RRA_AUDUSD_CloseOutsideSession, RRA_AUDUSD_TimeFrame, RRA_AUDUSD_MagicNumber, RRA_AUDUSD_Slippage))
|
||||
Print("Warning: RSIReversalAsianAUDUSD strategy failed to initialize for symbol '", RRA_AUDUSD_Symbol, "'");
|
||||
Print("Warning: RSIReversalAUDUSD strategy failed to initialize for symbol '", RRA_AUDUSD_Symbol, "'");
|
||||
|
||||
if(EnableRSISecretSauceXAUUSD)
|
||||
if(!InitRSISecretSauce(rsSecretSauceXAUUSDData, RSS_XAUUSD_Symbol, RSS_XAUUSD_Timeframe, RSS_XAUUSD_RSIPeriod,
|
||||
RSS_XAUUSD_RSIOverbought, RSS_XAUUSD_RSIOversold, RSS_XAUUSD_RSILookback, RSS_XAUUSD_PeakBars,
|
||||
RSS_XAUUSD_RequireDivergence, RSS_XAUUSD_StopLossATR, RSS_XAUUSD_TakeProfitATR, RSS_XAUUSD_ATRPeriod,
|
||||
RSS_XAUUSD_UseSwingStopLoss, RSS_XAUUSD_SwingLookback, RSS_XAUUSD_MaxPositions,
|
||||
RSS_XAUUSD_MinBarsBetweenTrades, RSS_XAUUSD_MagicNumber, RSS_XAUUSD_Slippage))
|
||||
Print("Warning: RSISecretSauceXAUUSD failed to initialize for symbol '", RSS_XAUUSD_Symbol, "'");
|
||||
|
||||
if(EnableSuperEMA)
|
||||
if(!InitSuperEMA(seData, SE_Symbol, SE_Timeframe, SE_SlippagePoints, SE_MagicNumber,
|
||||
SE_EmaFast, SE_EmaMid, SE_EmaSlow, SE_EmaTrendBars,
|
||||
SE_CciPeriod, SE_CciOverbought, SE_CciOversold, SE_PullbackCciLookback,
|
||||
SE_MacdFast, SE_MacdSlow, SE_MacdSignal,
|
||||
SE_EntryStyle, SE_OneTradeOnly, SE_UseStructuralSL, SE_SlBufferPoints,
|
||||
SE_ExitOnTrendFlip, SE_ExitOnMacdFlip, SE_ExitOnCciZeroCross,
|
||||
SE_MaxHoldingBars, SE_ExitBelowMidEma, SE_DebugLogs))
|
||||
Print("Warning: SuperEMA failed to initialize for symbol '", SE_Symbol, "'");
|
||||
|
||||
string acctCur = AccountInfoString(ACCOUNT_CURRENCY);
|
||||
double eq0 = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
@@ -554,7 +746,7 @@ int OnInit()
|
||||
capInit = refvInit;
|
||||
double ratioInit = capInit / refvInit;
|
||||
double rawPowInit = MathPow(ratioInit, InpDynamicExponent);
|
||||
Print("United EA v1.07 ", acctCur, " equity=", DoubleToString(eq0, 2), " equity/ref=", DoubleToString(ratioInit, 6),
|
||||
Print("United EA v1.17 ", acctCur, " equity=", DoubleToString(eq0, 2), " equity/ref=", DoubleToString(ratioInit, 6),
|
||||
" raw^exp=", DoubleToString(rawPowInit, 6), " multOut=", DoubleToString(g_DynMultLast, 6),
|
||||
" minM=", InpDynamicMinMult, " maxM=", InpDynamicMaxMult, " ref=", InpDynamicRefDeposit, " exp=", InpDynamicExponent,
|
||||
" lots ES=", g_ES_LotSize, " RC=", g_RC_LotSize, " RM=", g_RM_LotSize, " DB=", g_DB_LotSize);
|
||||
@@ -568,9 +760,29 @@ int OnInit()
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""),
|
||||
(EnableRSIReversalAsianEURUSD ? "RSIReversalAsianEURUSD " : ""),
|
||||
(EnableRSIReversalAsianAUDUSD ? "RSIReversalAsianAUDUSD " : ""));
|
||||
|
||||
(EnableRSIReversalEURUSD ? "RSIReversalEURUSD " : ""),
|
||||
(EnableRSIReversalAUDUSD ? "RSIReversalAUDUSD " : ""),
|
||||
(EnableRSISecretSauceXAUUSD ? "RSISecretSauceXAUUSD " : ""),
|
||||
(EnableSuperEMA ? "SuperEMA " : ""));
|
||||
|
||||
EventSetTimer(0);
|
||||
int timerSec = 0;
|
||||
if(UnitedPanel_Enable)
|
||||
timerSec = MathMax(5, UnitedPanel_Seconds);
|
||||
if(InpAdaptiveEnable)
|
||||
{
|
||||
const int adSec = MathMax(60, InpAdaptiveUpdateSeconds);
|
||||
timerSec = (timerSec == 0) ? adSec : MathMin(timerSec, adSec);
|
||||
}
|
||||
if(InpDdLotCapEnable && InpDdLotCapPerStratEnable && !InpAdaptiveEnable)
|
||||
{
|
||||
const int ddSec = MathMax(60, InpDdLotCapUpdateSeconds);
|
||||
timerSec = (timerSec == 0) ? ddSec : MathMin(timerSec, ddSec);
|
||||
}
|
||||
if(timerSec > 0)
|
||||
EventSetTimer(timerSec);
|
||||
UnitedProfitPanelInit();
|
||||
|
||||
return initResult;
|
||||
}
|
||||
|
||||
@@ -579,6 +791,9 @@ int OnInit()
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
EventSetTimer(0);
|
||||
UnitedProfitPanelDeinit();
|
||||
|
||||
if(EnableDarvasBox)
|
||||
DeinitDarvasBox();
|
||||
|
||||
@@ -606,11 +821,17 @@ void OnDeinit(const int reason)
|
||||
if(EnableRSIScalpingXAUUSD)
|
||||
DeinitRSIScalping(rsXAUUSDData);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
if(EnableRSIReversalEURUSD)
|
||||
DeinitRSIReversalAsian(rraEURUSDData);
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
if(EnableRSIReversalAUDUSD)
|
||||
DeinitRSIReversalAsian(rraAUDUSDData);
|
||||
|
||||
if(EnableRSISecretSauceXAUUSD)
|
||||
DeinitRSISecretSauce(rsSecretSauceXAUUSDData);
|
||||
|
||||
if(EnableSuperEMA)
|
||||
DeinitSuperEMA(seData);
|
||||
|
||||
Print("United EA deinitialized. Reason: ", reason);
|
||||
}
|
||||
@@ -620,56 +841,84 @@ void OnDeinit(const int reason)
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
UnitedAdaptive_ProcessCanaryTransitions();
|
||||
RefreshDynamicStrategyLots();
|
||||
|
||||
if(EnableDarvasBox)
|
||||
if(EnableDarvasBox && UnitedAdaptive_StrategyActive(UNITED_AD_DARVAS))
|
||||
ProcessDarvasBox(DB_Symbol);
|
||||
|
||||
if(EnableEMASlopeDistance)
|
||||
if(EnableEMASlopeDistance && UnitedAdaptive_StrategyActive(UNITED_AD_ES))
|
||||
ProcessEMASlopeDistance(ES_Symbol);
|
||||
|
||||
if(EnableRSICrossOverReversal)
|
||||
if(EnableRSICrossOverReversal && UnitedAdaptive_StrategyActive(UNITED_AD_RC))
|
||||
ProcessRSICrossOverReversal(RC_Symbol);
|
||||
|
||||
if(EnableRSIMidPointHijack)
|
||||
if(EnableRSIMidPointHijack && UnitedAdaptive_StrategyActive(UNITED_AD_RM))
|
||||
ProcessRSIMidPointHijack(RM_Symbol);
|
||||
|
||||
if(EnableRSIScalpingAPPL)
|
||||
if(EnableRSIScalpingAPPL && UnitedAdaptive_StrategyActive(UNITED_AD_RS_APPL))
|
||||
ProcessRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price,
|
||||
RS_APPL_RSI_Overbought, RS_APPL_RSI_Oversold, RS_APPL_RSI_Target_Buy, RS_APPL_RSI_Target_Sell,
|
||||
RS_APPL_BarsToWait,
|
||||
DynamicLotForSymbol(RS_APPL_Symbol, RS_APPL_LotSize, InpDynamicStockLotCap),
|
||||
DynamicLotForSymbol(RS_APPL_Symbol, RS_APPL_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_APPL), InpDynamicStockLotCap, UNITED_AD_RS_APPL),
|
||||
RS_APPL_MagicNumber);
|
||||
|
||||
if(EnableRSIScalpingBTCUSD)
|
||||
if(EnableRSIScalpingBTCUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RS_BTC))
|
||||
ProcessRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price,
|
||||
RS_BTCUSD_RSI_Overbought, RS_BTCUSD_RSI_Oversold, RS_BTCUSD_RSI_Target_Buy, RS_BTCUSD_RSI_Target_Sell,
|
||||
RS_BTCUSD_BarsToWait, DynamicLotForSymbol(RS_BTCUSD_Symbol, RS_BTCUSD_LotSize), RS_BTCUSD_MagicNumber);
|
||||
RS_BTCUSD_BarsToWait, DynamicLotForSymbol(RS_BTCUSD_Symbol, RS_BTCUSD_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_BTC), 0.0, UNITED_AD_RS_BTC), RS_BTCUSD_MagicNumber);
|
||||
|
||||
if(EnableRSIScalpingNVDA)
|
||||
if(EnableRSIScalpingNVDA && UnitedAdaptive_StrategyActive(UNITED_AD_RS_NVDA))
|
||||
ProcessRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price,
|
||||
RS_NVDA_RSI_Overbought, RS_NVDA_RSI_Oversold, RS_NVDA_RSI_Target_Buy, RS_NVDA_RSI_Target_Sell,
|
||||
RS_NVDA_BarsToWait,
|
||||
DynamicLotForSymbol(RS_NVDA_Symbol, RS_NVDA_LotSize, InpDynamicStockLotCap),
|
||||
DynamicLotForSymbol(RS_NVDA_Symbol, RS_NVDA_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_NVDA), InpDynamicStockLotCap, UNITED_AD_RS_NVDA),
|
||||
RS_NVDA_MagicNumber);
|
||||
|
||||
if(EnableRSIScalpingTSLA)
|
||||
if(EnableRSIScalpingTSLA && UnitedAdaptive_StrategyActive(UNITED_AD_RS_TSLA))
|
||||
ProcessRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price,
|
||||
RS_TSLA_RSI_Overbought, RS_TSLA_RSI_Oversold, RS_TSLA_RSI_Target_Buy, RS_TSLA_RSI_Target_Sell,
|
||||
RS_TSLA_BarsToWait,
|
||||
DynamicLotForSymbol(RS_TSLA_Symbol, RS_TSLA_LotSize, InpDynamicStockLotCap),
|
||||
DynamicLotForSymbol(RS_TSLA_Symbol, RS_TSLA_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_TSLA), InpDynamicStockLotCap, UNITED_AD_RS_TSLA),
|
||||
RS_TSLA_MagicNumber);
|
||||
|
||||
if(EnableRSIScalpingXAUUSD)
|
||||
if(EnableRSIScalpingXAUUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RS_XAU))
|
||||
ProcessRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price,
|
||||
RS_XAUUSD_RSI_Overbought, RS_XAUUSD_RSI_Oversold, RS_XAUUSD_RSI_Target_Buy, RS_XAUUSD_RSI_Target_Sell,
|
||||
RS_XAUUSD_BarsToWait, DynamicLotForSymbol(RS_XAUUSD_Symbol, RS_XAUUSD_LotSize), RS_XAUUSD_MagicNumber);
|
||||
RS_XAUUSD_BarsToWait, DynamicLotForSymbol(RS_XAUUSD_Symbol, RS_XAUUSD_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_XAU), 0.0, UNITED_AD_RS_XAU), RS_XAUUSD_MagicNumber);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
ProcessRSIReversalAsian(rraEURUSDData, DynamicLotForSymbol(RRA_EURUSD_Symbol, RRA_EURUSD_MaxLotSize));
|
||||
if(EnableRSIReversalEURUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RRA_EUR))
|
||||
ProcessRSIReversalAsian(rraEURUSDData, DynamicLotForSymbol(RRA_EURUSD_Symbol, RRA_EURUSD_MaxLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RRA_EUR), 0.0, UNITED_AD_RRA_EUR));
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, DynamicLotForSymbol(RRA_AUDUSD_Symbol, RRA_AUDUSD_MaxLotSize));
|
||||
if(EnableRSIReversalAUDUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RRA_AUD))
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, DynamicLotForSymbol(RRA_AUDUSD_Symbol, RRA_AUDUSD_MaxLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RRA_AUD), 0.0, UNITED_AD_RRA_AUD));
|
||||
|
||||
if(EnableRSISecretSauceXAUUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RSS))
|
||||
ProcessRSISecretSauce(rsSecretSauceXAUUSDData, DynamicLotForSymbol(RSS_XAUUSD_Symbol, RSS_XAUUSD_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RSS), 0.0, UNITED_AD_RSS));
|
||||
|
||||
if(EnableSuperEMA && UnitedAdaptive_StrategyActive(UNITED_AD_SUPEREMA))
|
||||
ProcessSuperEMA(seData, DynamicLotForSymbol(SE_Symbol, SE_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_SUPEREMA), 0.0, UNITED_AD_SUPEREMA));
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer — refresh profit panel (history scan) |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
if(InpAdaptiveEnable)
|
||||
UnitedAdaptive_ProcessCanaryTransitions();
|
||||
if(InpAdaptiveEnable || (InpDdLotCapEnable && InpDdLotCapPerStratEnable))
|
||||
UnitedAdaptive_UpdateIfDue();
|
||||
if(UnitedPanel_Enable)
|
||||
UnitedProfitPanelRefresh();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chart events — panel layout on resize |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
|
||||
{
|
||||
UnitedProfitPanelOnChartEvent(id);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
\begin{figure}[t]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{frontline/MQL5/_united_dynamic/report/pnl_by_magic_robot.pdf}
|
||||
\caption{Net closed P\&L by robot magic number from the united\_dynamic live report export. Bars show net realized P\&L (USD) and the label \texttt{n} is the number of closed trades. Because the MT5 report does not expose per-deal magic directly in this extract, XAUUSD trades that come from multiple XAU strategies are shown as one mixed bucket.}
|
||||
\label{fig:united-dynamic-pnl-by-magic}
|
||||
\end{figure}
|
||||
@@ -0,0 +1,6 @@
|
||||
\begin{figure*}[t]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{frontline/MQL5/_united_dynamic/report/pnl_timeseries_by_robot.pdf}
|
||||
\caption{Cumulative closed P\&L over time split by robot. Non-XAU robots are mapped directly by symbol-to-magic configuration; XAU trades are assigned by ticket-matched strategy comments when available, and otherwise grouped into an unattributed XAU bucket.}
|
||||
\label{fig:united-dynamic-pnl-timeseries-by-robot}
|
||||
\end{figure*}
|
||||
@@ -0,0 +1,6 @@
|
||||
\begin{figure}[t]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{frontline/MQL5/_united_dynamic/report/pnl_timeseries_line.pdf}
|
||||
\caption{Cumulative closed P\&L over time for the united\_dynamic account history in \texttt{ReportHistory-51389369.xlsx}. The curve is formed by sorting closed deals by close timestamp and cumulatively summing realized deal P\&L.}
|
||||
\label{fig:united-dynamic-pnl-timeseries}
|
||||
\end{figure}
|
||||
@@ -0,0 +1,9 @@
|
||||
symbol,magic_number,robot,count,sum
|
||||
MSFT.US,20002,RSI Scalping MSFT,12,-1042.0
|
||||
EURUSD,30001,RSI Reversal Asian EURUSD,20,-264.84999999999997
|
||||
BTCUSD,123459123,RSI Scalping BTCUSD,11,-203.41000000000003
|
||||
NVDA.US,20003,RSI Scalping NVDA,32,-42.54000000000002
|
||||
AAPL.US,20001,RSI Scalping AAPL,5,-2.0
|
||||
AUDUSD,30002,RSI Reversal Asian AUDUSD,14,78.08000000000001
|
||||
XAUUSD,MIXED,XAUUSD Multi-Strategy Bucket,291,1953.66
|
||||
TSLA.US,125421321,RSI Scalping TSLA,16,2352.57
|
||||
|
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
@@ -0,0 +1,386 @@
|
||||
close_time,125421321 RSI Scalping TSLA,XAU Unattributed (multiple robots),129102315 RSI Scalping XAUUSD,30002 RSI Reversal Asian AUDUSD,20003 RSI Scalping NVDA,12350 EMA Slope Distance (XAU),123459123 RSI Scalping BTCUSD,30001 RSI Reversal Asian EURUSD,20002 RSI Scalping MSFT
|
||||
2026-01-05 08:00:00,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
2026-01-05 12:06:01,0.0,0.0,0.0,0.0,0.0,61.98,0.0,0.0,0.0
|
||||
2026-01-05 18:06:21,0.0,0.0,0.0,0.0,0.0,86.07,0.0,0.0,0.0
|
||||
2026-01-06 07:55:38,0.0,0.0,0.0,0.0,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 08:00:00,0.0,0.0,0.0,4.2,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 12:00:00,0.0,0.0,-81.78,4.2,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 15:13:04,0.0,0.0,-78.69,4.2,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 16:39:10,0.0,0.0,-78.69,4.2,0.0,111.69,0.0,-3.0,0.0
|
||||
2026-01-06 19:42:51,0.0,0.0,-78.69,4.2,0.0,101.72999999999999,0.0,-3.0,0.0
|
||||
2026-01-07 08:00:00,0.0,0.0,-78.69,12.2,0.0,101.72999999999999,0.0,-3.0,0.0
|
||||
2026-01-07 11:00:00,0.0,0.0,-78.69,12.2,0.0,29.189999999999984,0.0,-3.0,0.0
|
||||
2026-01-08 08:21:15,0.0,0.0,-78.69,12.2,0.0,29.339999999999982,0.0,-3.0,0.0
|
||||
2026-01-08 18:00:00,0.0,0.0,-78.69,12.2,0.0,29.339999999999982,0.0,-3.0,-49.1
|
||||
2026-01-09 07:00:00,0.0,0.0,-78.69,12.2,0.0,29.339999999999982,0.0,-3.0,-49.1
|
||||
2026-01-12 03:00:00,0.0,0.0,296.85,12.2,0.0,29.339999999999982,0.0,-3.0,-49.1
|
||||
2026-01-12 05:43:32,0.0,0.0,296.85,12.2,0.0,36.11999999999998,0.0,-3.0,-49.1
|
||||
2026-01-12 06:00:00,0.0,0.0,296.85,12.2,0.0,35.399999999999984,0.0,-3.0,-49.1
|
||||
2026-01-12 06:01:28,0.0,0.0,296.85,12.2,0.0,35.399999999999984,0.0,-3.8,-49.1
|
||||
2026-01-13 00:01:01,0.0,0.0,296.85,12.2,0.0,35.399999999999984,0.0,-10.2,-49.1
|
||||
2026-01-13 03:00:00,0.0,0.0,246.06000000000003,12.2,0.0,35.399999999999984,0.0,-10.2,-49.1
|
||||
2026-01-13 16:28:43,0.0,0.0,267.48,12.2,0.0,56.819999999999986,0.0,-10.2,-49.1
|
||||
2026-01-13 20:00:00,0.0,0.0,267.48,12.2,0.0,-63.00000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 05:28:14,0.0,0.0,267.48,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 07:19:03,0.0,0.0,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 15:00:44,0.0,-11.19,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 17:11:47,49.1,-11.19,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-15 03:00:00,49.1,-74.88,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-15 07:28:43,49.1,-69.75,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-15 17:00:00,49.1,-141.66,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-16 08:00:00,49.1,-152.35999999999999,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-19 01:01:01,49.1,-348.98,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-19 02:08:19,49.1,-348.98,305.1,12.2,0.0,-72.63000000000001,0.0,-0.6999999999999993,-49.1
|
||||
2026-01-19 03:00:46,49.1,-354.74,305.1,12.2,0.0,-72.63000000000001,0.0,-0.6999999999999993,-49.1
|
||||
2026-01-19 04:00:26,49.1,-354.74,305.1,12.2,0.0,-72.63000000000001,0.0,9.4,-49.1
|
||||
2026-01-20 00:01:00,49.1,-354.74,305.1,12.2,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 07:24:12,49.1,-282.38,305.1,12.2,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 08:00:00,49.1,-282.38,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 09:51:16,49.1,-271.4,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 10:19:24,49.1,-254.29999999999998,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 12:00:07,49.1,-247.93999999999997,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 15:34:19,49.1,-237.22999999999996,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-21 00:01:00,49.1,-237.22999999999996,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-21 17:24:43,49.1,-145.00999999999996,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 02:00:00,49.1,-361.5799999999999,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 08:00:00,49.1,-459.2299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 18:00:00,23.700000000000003,-459.2299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 18:30:02,23.700000000000003,-434.1799999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 21:27:07,23.700000000000003,-334.9099999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 22:00:00,23.700000000000003,-335.6599999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-23 03:00:00,23.700000000000003,-498.8299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-23 04:44:42,23.700000000000003,-498.8299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-23 05:16:54,23.700000000000003,-506.74999999999994,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-23 08:00:00,23.700000000000003,-506.74999999999994,305.1,-46.0,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-23 11:00:00,23.700000000000003,-388.3399999999999,305.1,-46.0,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-26 04:00:00,23.700000000000003,34.3300000000001,305.1,-46.0,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-26 08:00:00,23.700000000000003,34.3300000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-26 21:00:00,23.700000000000003,65.1700000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-27 00:01:00,23.700000000000003,65.1700000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-214.09999999999997,-49.1
|
||||
2026-01-27 04:00:00,23.700000000000003,-41.089999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-214.09999999999997,-49.1
|
||||
2026-01-27 05:07:00,23.700000000000003,-41.089999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 06:09:45,23.700000000000003,-40.60999999999991,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 08:50:00,23.700000000000003,-5.089999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 09:12:16,23.700000000000003,-0.25999999999990386,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 11:45:33,23.700000000000003,2.560000000000096,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 16:00:00,23.700000000000003,-61.159999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 17:03:41,54.300000000000004,-61.159999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 23:00:30,54.300000000000004,159.3400000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-28 03:31:17,54.300000000000004,159.3400000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 07:01:59,54.300000000000004,588.97,305.1,-34.4,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 08:00:00,54.300000000000004,588.97,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 09:00:38,54.300000000000004,601.69,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 10:12:05,54.300000000000004,603.82,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 14:12:22,54.300000000000004,604.0,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 17:12:17,54.300000000000004,647.86,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 18:53:19,54.300000000000004,647.86,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,2.3999999999999986
|
||||
2026-01-28 19:08:19,54.300000000000004,645.46,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,2.3999999999999986
|
||||
2026-01-29 02:00:01,54.300000000000004,-0.8899999999999864,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,2.3999999999999986
|
||||
2026-01-29 07:58:06,54.300000000000004,-0.8899999999999864,305.1,-27.2,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-29 08:00:00,54.300000000000004,-0.8899999999999864,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-29 12:38:43,54.300000000000004,8.890000000000013,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 01:01:01,54.300000000000004,-650.63,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 04:00:00,54.300000000000004,-1064.69,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 06:00:34,54.300000000000004,-1001.1800000000001,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 07:00:00,54.300000000000004,-1003.58,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 09:00:00,54.300000000000004,-1044.07,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 11:00:10,54.300000000000004,-873.4,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 20:00:04,54.300000000000004,-397.51,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 23:00:03,54.300000000000004,-318.01,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 02:00:00,54.300000000000004,-244.57,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 04:00:10,54.300000000000004,-85.47999999999999,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 07:13:20,54.300000000000004,-60.609999999999985,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 08:00:00,54.300000000000004,-60.609999999999985,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 08:12:16,54.300000000000004,-30.879999999999985,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 09:16:31,54.300000000000004,-23.319999999999986,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 10:24:18,54.300000000000004,32.72000000000001,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 17:27:59,154.4,32.72000000000001,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-04 04:50:05,154.4,32.72000000000001,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 07:00:00,154.4,31.830000000000013,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 07:00:02,154.4,482.03999999999996,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 12:13:15,154.4,487.61999999999995,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 18:24:11,154.4,558.9,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-05 00:01:00,154.4,558.9,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 01:01:00,154.4,305.93999999999994,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 04:00:00,154.4,145.13999999999993,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 08:00:12,154.4,155.80999999999992,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 17:48:31,154.4,177.07999999999993,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 23:01:58,154.4,181.36999999999992,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-06 01:01:01,154.4,131.0399999999999,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-06 04:01:08,154.4,131.0399999999999,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-06 08:00:00,154.4,-452.8200000000001,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 03:51:31,154.4,-249.7200000000001,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 03:59:22,154.4,-83.5700000000001,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 07:00:00,154.4,-87.02000000000011,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 13:00:00,154.4,73.72999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 15:00:02,154.4,69.55999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 17:43:21,-126.6,69.55999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 05:00:00,-126.6,-29.140000000000114,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 07:00:00,-126.6,-30.010000000000115,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 07:15:30,-126.6,50.63999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 10:50:55,-126.6,76.61999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 11:13:05,-126.6,111.65999999999988,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 12:54:34,-126.6,123.17999999999988,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 13:18:10,-126.6,126.59999999999988,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 16:25:00,-126.6,213.71999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 16:45:00,-126.6,213.71999999999989,305.1,9.400000000000006,2.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 17:00:00,-126.6,213.71999999999989,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 17:15:40,-126.6,213.8999999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 21:00:01,-126.6,213.8999999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 04:02:06,-126.6,237.0299999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 07:48:46,-126.6,237.9299999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 08:00:00,-126.6,218.2799999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 11:49:18,-126.6,235.7999999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 12:27:16,-126.6,295.1599999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 13:24:06,-126.6,304.6699999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 17:25:57,-126.6,304.6699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 19:20:00,-126.6,304.6699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 05:00:00,-126.6,174.6699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 07:00:00,-126.6,173.1699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 09:00:00,-126.6,14.919999999999902,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 17:45:00,-126.6,14.919999999999902,305.1,9.400000000000006,17.45,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 18:00:01,-126.6,14.919999999999902,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 20:01:58,-126.6,43.119999999999905,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 23:02:07,-126.6,97.1499999999999,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 05:18:27,-126.6,105.3999999999999,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 08:00:00,-126.6,0.9699999999998994,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 15:42:45,-126.6,-294.7100000000001,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 19:00:00,-126.6,-488.5700000000001,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 21:42:00,-126.6,-488.5700000000001,305.1,9.400000000000006,28.349999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 21:58:36,-126.6,-446.1500000000001,305.1,9.400000000000006,28.349999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 22:00:00,-126.6,-446.1500000000001,305.1,9.400000000000006,32.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-16 02:00:00,-126.6,-446.1500000000001,305.1,9.400000000000006,32.55,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-16 05:00:00,-126.6,-579.1000000000001,305.1,9.400000000000006,32.55,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-17 17:00:00,-49.8,-579.1000000000001,305.1,9.400000000000006,32.55,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-17 17:45:00,-49.8,-579.1000000000001,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-19 22:00:00,-49.8,-133.80000000000013,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-20 07:00:00,-49.8,-201.30000000000013,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-23 02:00:00,-49.8,1316.8999999999999,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 02:00:00,-49.8,407.79999999999984,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 04:00:00,-49.8,860.9999999999998,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 10:01:34,-49.8,880.3799999999998,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 14:01:01,-49.8,873.7799999999997,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 18:00:00,-49.8,759.9899999999998,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 18:15:00,-49.8,759.9899999999998,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 05:55:01,-49.8,762.1799999999998,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 08:00:56,-49.8,811.8899999999999,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 16:00:00,-49.8,634.3899999999999,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 18:07:26,-49.8,624.6399999999999,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 23:00:03,-49.8,442.65999999999985,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-26 03:00:00,-49.8,375.05999999999983,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-26 06:00:00,-49.8,375.05999999999983,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 13:00:00,-49.8,293.0099999999998,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:45:00,-49.8,293.0099999999998,305.1,9.400000000000006,21.699999999999996,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:46:48,-49.8,293.0099999999998,305.1,9.400000000000006,26.399999999999995,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:46:53,-49.8,293.0099999999998,305.1,9.400000000000006,52.099999999999994,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:46:56,-49.8,293.0099999999998,305.1,9.400000000000006,89.94999999999999,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 18:56:28,-49.8,293.0099999999998,305.1,9.400000000000006,89.94999999999999,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-26 20:45:00,-49.8,293.0099999999998,305.1,9.400000000000006,40.44999999999999,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-26 22:30:01,-49.8,293.0099999999998,305.1,9.400000000000006,3.6999999999999886,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 07:00:01,-49.8,292.3299999999998,305.1,9.400000000000006,3.6999999999999886,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 16:45:00,-49.8,292.3299999999998,305.1,9.400000000000006,5.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 18:00:00,-49.8,292.3299999999998,305.1,9.400000000000006,13.199999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 18:00:33,-49.8,329.3799999999998,305.1,9.400000000000006,13.199999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 18:15:00,-49.8,329.3799999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 20:15:53,-49.8,337.0899999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 21:03:14,187.2,337.0899999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 23:01:44,187.2,377.5299999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 01:03:37,187.2,1653.3299999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 02:00:03,187.2,1747.1699999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 06:01:54,187.2,1803.8999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 09:01:24,187.2,1889.0999999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 09:13:03,187.2,1095.8999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 17:00:00,187.2,1730.3999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 18:00:30,187.2,1378.8899999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 23:30:48,187.2,1418.6999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 02:00:21,187.2,1442.7299999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 05:17:20,187.2,1477.2599999999995,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 11:00:00,187.2,530.9999999999995,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 12:00:00,187.2,529.2599999999995,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 13:00:18,187.2,593.6999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 16:31:02,187.2,593.6999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-03 17:00:05,187.2,897.6599999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-03 20:00:21,187.2,935.6399999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-03 22:00:04,187.2,996.3299999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-04 18:00:00,187.2,828.2399999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-04 20:00:10,187.2,844.6499999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-05 04:00:00,187.2,844.6499999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 05:00:00,187.2,668.1899999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 09:00:00,187.2,415.9899999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 16:00:00,187.2,371.4299999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 16:00:11,187.2,456.3299999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 19:02:14,187.2,515.6099999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 20:30:00,187.2,515.6099999999996,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 12:00:00,187.2,417.5299999999996,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 15:00:00,187.2,355.42999999999955,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 17:00:00,187.2,209.44999999999956,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 22:30:00,187.2,209.44999999999956,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 01:01:22,187.2,288.10999999999956,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 04:06:01,187.2,357.8299999999996,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 05:00:00,187.2,-362.5700000000004,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 09:00:00,187.2,-525.8900000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 12:01:35,187.2,-530.5700000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 17:00:00,599.95,-530.5700000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 17:00:25,599.95,-500.0600000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 01:01:33,599.95,-490.52000000000027,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 05:02:32,599.95,-405.5600000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 08:00:01,599.95,-407.40000000000026,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 09:05:27,599.95,-379.41000000000025,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 11:03:06,599.95,-369.30000000000024,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 17:00:17,599.95,-311.97000000000025,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 19:03:01,599.95,-253.23000000000025,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 07:00:00,599.95,-253.71000000000024,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 10:00:00,599.95,299.38999999999976,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 15:00:01,599.95,158.68999999999977,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 16:31:01,510.95000000000005,158.68999999999977,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 18:00:00,510.95000000000005,158.68999999999977,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 03:09:47,510.95000000000005,155.53999999999976,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 06:01:28,510.95000000000005,152.23999999999975,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 11:00:00,510.95000000000005,32.05999999999975,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 12:00:00,510.95000000000005,40.11999999999975,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 17:30:01,510.95000000000005,40.11999999999975,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 18:46:42,510.95000000000005,102.39999999999975,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 19:04:29,510.95000000000005,151.41999999999976,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 21:00:02,510.95000000000005,151.41999999999976,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-12 21:01:15,510.95000000000005,196.56999999999977,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-12 23:01:04,510.95000000000005,216.24999999999977,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 08:00:00,510.95000000000005,195.32999999999976,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 18:00:14,510.95000000000005,286.34999999999974,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 19:30:00,510.95000000000005,286.34999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 23:00:00,510.95000000000005,286.34999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-13 23:00:35,510.95000000000005,330.9299999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 03:00:15,510.95000000000005,355.52999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 05:00:33,510.95000000000005,376.43999999999977,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 11:00:31,510.95000000000005,392.00999999999976,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 13:09:14,510.95000000000005,429.08999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 14:00:00,510.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 15:00:00,510.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-1.2600000000000229,-129.39999999999998,-174.5
|
||||
2026-03-16 17:00:00,501.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-1.2600000000000229,-129.39999999999998,-174.5
|
||||
2026-03-17 11:00:01,501.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 14:00:00,501.95000000000005,401.4499999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 14:08:21,501.95000000000005,421.4899999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 19:18:11,501.95000000000005,429.28999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 23:04:43,501.95000000000005,424.45999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 05:00:33,501.95000000000005,418.78999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 06:00:00,501.95000000000005,401.00999999999976,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 07:24:05,501.95000000000005,394.76999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 14:14:57,501.95000000000005,443.4299999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 16:31:00,503.70000000000005,443.4299999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 16:42:22,503.70000000000005,580.7099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 18:00:39,503.70000000000005,597.5699999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 22:04:29,503.70000000000005,618.3899999999998,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 22:45:00,503.70000000000005,618.3899999999998,305.1,9.400000000000006,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 01:01:09,503.70000000000005,647.6999999999997,305.1,9.400000000000006,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 05:07:38,503.70000000000005,647.6999999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 09:00:35,503.70000000000005,659.9999999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 11:00:07,503.70000000000005,761.2199999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 13:00:36,503.70000000000005,783.0299999999996,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 16:20:36,503.70000000000005,1087.8299999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 16:31:00,1279.2,1087.8299999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 18:00:12,1279.2,1136.1899999999996,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-20 04:50:41,1279.2,1136.1899999999996,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-109.49999999999997,-174.5
|
||||
2026-03-20 18:00:00,1279.2,1136.1899999999996,305.1,51.60000000000001,-186.55,-72.63000000000001,-142.25000000000003,-109.49999999999997,-174.5
|
||||
2026-03-20 20:45:00,1279.2,1136.1899999999996,305.1,51.60000000000001,-275.05,-72.63000000000001,-142.25000000000003,-109.49999999999997,-174.5
|
||||
2026-03-23 23:00:00,1279.2,1136.1899999999996,305.1,51.60000000000001,-275.05,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-24 04:00:00,1279.2,1009.8699999999997,305.1,51.60000000000001,-275.05,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-24 17:30:00,1279.2,1009.8699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-25 02:00:30,1279.2,1028.9499999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-25 04:00:04,1279.2,1065.3699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-25 04:54:18,1279.2,1065.3699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-25 16:31:01,871.7,1065.3699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-25 23:00:00,871.7,871.1799999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 01:01:01,871.7,1292.4799999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 05:00:47,871.7,1284.1699999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 12:00:55,871.7,1305.8899999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 13:00:00,871.7,1353.8899999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 15:00:47,871.7,1347.1999999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 17:30:00,871.7,1347.1999999999996,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 20:00:33,871.7,1457.0299999999995,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 23:11:44,871.7,1488.7099999999996,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 04:00:00,871.7,1421.1099999999997,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 04:00:03,871.7,1417.3899999999996,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 09:00:00,871.7,1308.3699999999997,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 14:00:12,871.7,1330.2699999999998,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 16:31:00,1699.7,1330.2699999999998,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 18:00:01,1699.7,1054.2399999999998,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 20:30:01,1699.7,1054.2399999999998,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 21:00:00,1699.7,1054.2399999999998,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 03:00:01,1699.7,828.9099999999997,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 04:00:13,1699.7,70.40999999999974,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 05:00:00,1699.7,-33.84000000000026,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 09:00:03,1699.7,33.29999999999974,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 10:00:00,1699.7,32.679999999999744,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 12:06:36,1699.7,44.169999999999746,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 15:00:29,1699.7,113.01999999999974,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 22:30:00,1699.7,113.01999999999974,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 23:00:00,1699.7,37.119999999999735,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-31 04:50:01,1699.7,37.119999999999735,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 05:00:17,1699.7,129.66999999999973,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 07:00:00,1699.7,129.30999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 09:00:13,1699.7,122.34999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 11:02:00,1699.7,133.98999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 15:14:01,1699.7,167.58999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 17:09:58,1699.7,253.86999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 21:10:02,1699.7,253.86999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 22:08:48,1699.7,448.26999999999975,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-04-01 03:00:31,1699.7,475.2399999999998,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-04-01 08:00:00,1699.7,475.2399999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-04-02 00:01:00,1699.7,475.2399999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-02 08:00:00,1699.7,1736.6399999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-02 18:00:01,1699.7,1470.8999999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 03:01:14,1699.7,1538.61,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 08:00:00,1699.7,1426.62,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 12:50:29,1699.7,1448.79,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 17:00:00,1699.7,1295.09,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 18:00:00,1699.7,1295.09,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-06 18:40:05,1699.7,1295.09,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-06 20:00:00,1699.7,1195.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-06 20:00:01,2471.7,1195.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 01:00:00,2471.7,1195.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 08:00:01,2471.7,1094.1499999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 14:00:00,2471.7,998.3899999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 16:00:00,2471.7,684.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 17:30:00,2471.7,684.1899999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 18:00:01,2471.7,684.1899999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-07 21:00:00,2471.7,555.0999999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 01:01:06,2471.7,678.7299999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 03:00:07,2471.7,712.4799999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 08:00:00,2471.7,712.4799999999998,305.1,-72.39999999999998,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 09:08:23,2471.7,730.9599999999998,305.1,-72.39999999999998,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 10:00:00,2471.7,730.9599999999998,305.1,-72.39999999999998,-264.04999999999995,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 16:31:00,2471.7,730.9599999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 18:20:00,2471.7,730.9599999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 20:00:00,2471.7,1312.6599999999999,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 21:00:01,2471.7,1056.0099999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-09 00:01:00,2471.7,1056.0099999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-356.5
|
||||
2026-04-09 13:00:01,2471.7,978.8799999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-356.5
|
||||
2026-04-09 16:31:01,2471.7,978.8799999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-09 17:00:38,2471.7,995.0199999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-09 19:13:39,2471.7,1057.1799999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-09 21:01:21,2471.7,1073.4099999999999,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 01:01:52,2471.7,1075.2699999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 05:00:02,2471.7,1155.7699999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 05:00:30,2471.7,1149.5899999999997,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 17:00:01,2471.7,1149.9499999999996,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 18:36:21,2471.7,1149.9499999999996,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-10 21:00:00,2471.7,985.5499999999996,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 01:01:02,2471.7,641.7499999999995,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 01:01:03,2471.7,1087.5699999999995,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 07:33:34,2471.7,1087.5699999999995,305.1,78.08000000000001,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 18:00:01,2471.7,1087.5699999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 20:00:00,2352.5699999999997,787.4099999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 04:00:02,2352.5699999999997,813.0899999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 06:00:57,2352.5699999999997,833.8799999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 08:02:23,2352.5699999999997,847.8799999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 09:00:04,2352.5699999999997,844.2399999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 09:00:07,2352.5699999999997,844.2399999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 12:05:23,2352.5699999999997,851.1599999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 18:00:36,2352.5699999999997,939.3599999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 21:21:16,2352.5699999999997,1039.9199999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 23:00:00,2352.5699999999997,1039.9199999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-211.49999999999997,-1042.0
|
||||
2026-04-14 23:04:34,2352.5699999999997,1068.0699999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-211.49999999999997,-1042.0
|
||||
2026-04-15 00:01:00,2352.5699999999997,1068.0699999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 05:15:57,2352.5699999999997,1086.4199999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 08:30:19,2352.5699999999997,1076.7199999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 12:00:00,2352.5699999999997,1796.5999999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 14:00:00,2352.5699999999997,1721.9599999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
|
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 267 KiB |
@@ -0,0 +1,102 @@
|
||||
close_time,daily_pnl,cum_pnl
|
||||
2026-01-05,85.61999999999999,85.61999999999999
|
||||
2026-01-06,-61.83,23.789999999999992
|
||||
2026-01-07,-64.69000000000001,-40.90000000000002
|
||||
2026-01-08,-48.95,-89.85000000000002
|
||||
2026-01-09,-0.17,-90.02000000000002
|
||||
2026-01-10,0.0,-90.02000000000002
|
||||
2026-01-11,0.0,-90.02000000000002
|
||||
2026-01-12,380.8,290.78
|
||||
2026-01-13,-134.17,156.60999999999999
|
||||
2026-01-14,65.9,222.51
|
||||
2026-01-15,-130.47,92.03999999999999
|
||||
2026-01-16,-10.7,81.33999999999999
|
||||
2026-01-17,0.0,81.33999999999999
|
||||
2026-01-18,0.0,81.33999999999999
|
||||
2026-01-19,-182.78,-101.44000000000001
|
||||
2026-01-20,86.51,-14.930000000000007
|
||||
2026-01-21,16.120000000000005,1.1899999999999977
|
||||
2026-01-22,-243.25,-242.06
|
||||
2026-01-23,-67.38,-309.44
|
||||
2026-01-24,0.0,-309.44
|
||||
2026-01-25,0.0,-309.44
|
||||
2026-01-26,465.11,155.67000000000002
|
||||
2026-01-27,-1.4299999999999784,154.24000000000004
|
||||
2026-01-28,580.72,734.96
|
||||
2026-01-29,-655.47,79.49000000000001
|
||||
2026-01-30,-326.9,-247.40999999999997
|
||||
2026-01-31,0.0,-247.40999999999997
|
||||
2026-02-01,0.0,-247.40999999999997
|
||||
2026-02-02,0.0,-247.40999999999997
|
||||
2026-02-03,447.03,199.62
|
||||
2026-02-04,533.68,733.3
|
||||
2026-02-05,-354.43,378.86999999999995
|
||||
2026-02-06,-563.19,-184.3200000000001
|
||||
2026-02-07,0.0,-184.3200000000001
|
||||
2026-02-08,0.0,-184.3200000000001
|
||||
2026-02-09,241.38,57.05999999999989
|
||||
2026-02-10,123.99000000000001,181.0499999999999
|
||||
2026-02-11,111.97,293.01999999999987
|
||||
2026-02-12,-190.67000000000002,102.34999999999985
|
||||
2026-02-13,-530.6,-428.25000000000017
|
||||
2026-02-14,0.0,-428.25000000000017
|
||||
2026-02-15,0.0,-428.25000000000017
|
||||
2026-02-16,-149.54999999999998,-577.8000000000002
|
||||
2026-02-17,70.7,-507.1000000000002
|
||||
2026-02-18,0.0,-507.1000000000002
|
||||
2026-02-19,445.3,-61.80000000000018
|
||||
2026-02-20,-67.5,-129.30000000000018
|
||||
2026-02-21,0.0,-129.30000000000018
|
||||
2026-02-22,0.0,-129.30000000000018
|
||||
2026-02-23,1518.2,1388.8999999999999
|
||||
2026-02-24,-656.6600000000001,732.2399999999998
|
||||
2026-02-25,-317.33,414.9099999999998
|
||||
2026-02-26,37.540000000000006,452.4499999999998
|
||||
2026-02-27,329.27,781.7199999999998
|
||||
2026-02-28,0.0,781.7199999999998
|
||||
2026-03-01,0.0,781.7199999999998
|
||||
2026-03-02,1041.1699999999998,1822.8899999999996
|
||||
2026-03-03,-502.8700000000001,1320.0199999999995
|
||||
2026-03-04,-151.68,1168.3399999999995
|
||||
2026-03-05,-188.37,979.9699999999995
|
||||
2026-03-06,-376.65999999999997,603.3099999999995
|
||||
2026-03-07,0.0,603.3099999999995
|
||||
2026-03-08,0.0,603.3099999999995
|
||||
2026-03-09,-296.76,306.5499999999995
|
||||
2026-03-10,246.82999999999998,553.3799999999994
|
||||
2026-03-11,290.42,843.7999999999995
|
||||
2026-03-12,113.06,956.8599999999994
|
||||
2026-03-13,-159.65000000000003,797.2099999999994
|
||||
2026-03-14,0.0,797.2099999999994
|
||||
2026-03-15,0.0,797.2099999999994
|
||||
2026-03-16,87.19,884.3999999999994
|
||||
2026-03-17,-173.84,710.5599999999994
|
||||
2026-03-18,177.18,887.7399999999993
|
||||
2026-03-19,1335.5,2223.2399999999993
|
||||
2026-03-20,-220.1,2003.1399999999994
|
||||
2026-03-21,0.0,2003.1399999999994
|
||||
2026-03-22,0.0,2003.1399999999994
|
||||
2026-03-23,-83.66,1919.4799999999993
|
||||
2026-03-24,-243.82,1675.6599999999994
|
||||
2026-03-25,-539.69,1135.9699999999993
|
||||
2026-03-26,618.53,1754.4999999999993
|
||||
2026-03-27,365.03,2119.5299999999993
|
||||
2026-03-28,0.0,2119.5299999999993
|
||||
2026-03-29,0.0,2119.5299999999993
|
||||
2026-03-30,-1182.6200000000001,936.9099999999992
|
||||
2026-03-31,425.55,1362.4599999999991
|
||||
2026-04-01,75.17,1437.6299999999992
|
||||
2026-04-02,951.76,2389.3899999999994
|
||||
2026-04-03,0.0,2389.3899999999994
|
||||
2026-04-04,0.0,2389.3899999999994
|
||||
2026-04-05,0.0,2389.3899999999994
|
||||
2026-04-06,421.78999999999996,2811.1799999999994
|
||||
2026-04-07,-317.53999999999996,2493.6399999999994
|
||||
2026-04-08,798.5600000000001,3292.1999999999994
|
||||
2026-04-09,-652.1,2640.0999999999995
|
||||
2026-04-10,-176.86,2463.2399999999993
|
||||
2026-04-11,0.0,2463.2399999999993
|
||||
2026-04-12,0.0,2463.2399999999993
|
||||
2026-04-13,-408.28000000000003,2054.959999999999
|
||||
2026-04-14,174.01000000000002,2228.9699999999993
|
||||
2026-04-15,600.54,2829.5099999999993
|
||||
|
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
Reference in New Issue
Block a user