Update
This commit is contained in:
@@ -0,0 +1,458 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ScoringTrade.mq5 |
|
||||
//| Generated by ChatGPT |
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input int MagicNumber = 42;
|
||||
input int scoreThreshold = 5200; // Score threshold for trade entry
|
||||
input int slopeThreshold = 93; // EMA slope threshold
|
||||
input double maxScore = 7900; // Max score value for clamping
|
||||
input int cooldownMinutes = 18; // Cooldown period in minutes (37 minutes)
|
||||
input int tradeCooldownMinutes = 24; // Trade debounce cooldown period (5 minutes)
|
||||
input ENUM_TIMEFRAMES emaTimeFrame = PERIOD_H1; // EMA Timeframe
|
||||
input double delayClampAbsolute = 1690;
|
||||
input int emaPeriod = 64; // EMA period
|
||||
input double crossOverStep = 950;
|
||||
input double slopeThresholdStep = 635;
|
||||
input double emaDistanceStep = 150;
|
||||
input double emaDecayStep = 0;
|
||||
input double decayMultiplier = 0.08; // Decay multiplier
|
||||
input double distanceThreshold = 28.5; // Set your distance threshold (adjust as necessary)
|
||||
input double atrMultiplier = 7.6; // Multiplier for dynamic SL and TP calculation
|
||||
input double TrailingStop = 5;
|
||||
input bool UseTrailingStop = true;
|
||||
input int maxCrossoverTrades = 4; // Maximum number of trades per crossover
|
||||
input double max_drawdown = 0.1; // Maximum drawdown percentage
|
||||
input bool resetCrossoverTradeOnDistance = false;
|
||||
input int resetCrossoverNumber = 0;
|
||||
input double minimumLotSize = 0.01;
|
||||
input int maxTimeInPosition = 9;
|
||||
input int tradeLengthThreshold = 98;
|
||||
input int reverseTP = 32;
|
||||
input int reverseLotSizeMultiplier = 15;
|
||||
input int secondaryPositionHoldTime = 32;
|
||||
// Global variables
|
||||
int emaHandle; // EMA handle
|
||||
double prevScore = 0; // Previous score
|
||||
double currentScore = 0; // Current score
|
||||
double emaPrevValue = 0; // Previous EMA value
|
||||
double emaCurrentValue = 0; // Current EMA value
|
||||
double emaSlope = 0; // EMA slope value
|
||||
CTrade trade; // Trading object
|
||||
|
||||
datetime lastCrossoverTime = 0; // Time of last crossover
|
||||
datetime lastTradeTime = 0; // Time of last trade
|
||||
int crossoverTradeCount = 0; // Count of trades after each crossover
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit() {
|
||||
// Create EMA handle (e.g., 14-period EMA on the closing price)
|
||||
emaHandle = iMA(Symbol(), emaTimeFrame, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
|
||||
|
||||
if (emaHandle == INVALID_HANDLE) {
|
||||
Print("Failed to create EMA handle");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason) {
|
||||
if (emaHandle != INVALID_HANDLE) {
|
||||
IndicatorRelease(emaHandle);
|
||||
emaHandle = INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick() {
|
||||
// Buffer to hold the EMA values
|
||||
double emaBuffer[];
|
||||
|
||||
// Get dynamic lot size based on current balance and max drawdown
|
||||
double lotSize = CalculateLotSize();
|
||||
|
||||
if(lotSize < minimumLotSize) {
|
||||
lotSize = minimumLotSize;
|
||||
}
|
||||
|
||||
// Get the current Ask and Bid prices
|
||||
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
|
||||
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
|
||||
|
||||
// Copy the last 2 EMA values (current and previous)
|
||||
int copied = CopyBuffer(emaHandle, 0, 0, 2, emaBuffer);
|
||||
if (copied < 2) {
|
||||
Print("Failed to copy EMA values. Error code: ", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current and previous EMA values
|
||||
emaPrevValue = emaBuffer[1]; // Previous EMA value (index 1)
|
||||
emaCurrentValue = emaBuffer[0]; // Current EMA value (index 0)
|
||||
|
||||
// Calculate the EMA slope (change in EMA values)
|
||||
emaSlope = - (emaCurrentValue - emaPrevValue) * 100;
|
||||
|
||||
// Check for price action crossover with EMA
|
||||
double closePrev = iClose(Symbol(), Period(), 1); // Close of previous bar
|
||||
double closeCurr = iClose(Symbol(), Period(), 0); // Close of current bar
|
||||
|
||||
// Check if enough time has passed for the cooldown (cooldownMinutes)
|
||||
if (TimeCurrent() - lastCrossoverTime >= cooldownMinutes * 60) {
|
||||
if (closePrev < emaPrevValue && closeCurr > emaCurrentValue) { // Bullish crossover
|
||||
Print("Bullish crossover");
|
||||
currentScore += crossOverStep;
|
||||
crossoverTradeCount = 0; // Reset trade count after new crossover
|
||||
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
|
||||
}
|
||||
else if (closePrev > emaPrevValue && closeCurr < emaCurrentValue) { // Bearish crossover
|
||||
Print("Bearish crossover");
|
||||
currentScore -= crossOverStep;
|
||||
crossoverTradeCount = 0; // Reset trade count after new crossover
|
||||
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
|
||||
}
|
||||
}
|
||||
|
||||
// Check EMA slope
|
||||
if (emaSlope > slopeThreshold) { // Positive slope
|
||||
currentScore += slopeThresholdStep;
|
||||
}
|
||||
else if (emaSlope < -slopeThreshold) { // Negative slope
|
||||
currentScore -= slopeThresholdStep;
|
||||
}
|
||||
else {
|
||||
if (MathAbs(currentScore) > delayClampAbsolute) {
|
||||
currentScore *= decayMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
if(UseTrailingStop) {
|
||||
ApplyTrailingStop();
|
||||
}
|
||||
|
||||
// Calculate distance to EMA and adjust score
|
||||
double priceToEmaDistance = closeCurr - emaCurrentValue; // Distance between the current price and the EMA
|
||||
|
||||
if (MathAbs(priceToEmaDistance) > distanceThreshold) {
|
||||
if (priceToEmaDistance > 0) { // Bullish (price above EMA)
|
||||
currentScore += emaDistanceStep;
|
||||
Print("Bullish distance score added. Price: ", closeCurr, " EMA: ", emaCurrentValue);
|
||||
}
|
||||
else if (priceToEmaDistance < 0) { // Bearish (price below EMA)
|
||||
currentScore -= emaDistanceStep;
|
||||
Print("Bearish distance score added. Price: ", closeCurr, " EMA: ", emaCurrentValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (currentScore > 0) {
|
||||
currentScore -= emaDecayStep;
|
||||
}
|
||||
else {
|
||||
currentScore += emaDecayStep;
|
||||
}
|
||||
}
|
||||
|
||||
// Close all positions if score crosses zero
|
||||
if ((prevScore > 0 && currentScore <= 0) || (prevScore < 0 && currentScore >= 0)) {
|
||||
Close_Position_MN(MagicNumber);
|
||||
}
|
||||
|
||||
// Update the previous score
|
||||
prevScore = currentScore;
|
||||
|
||||
if (crossoverTradeCount > maxCrossoverTrades) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce check: Ensure enough time has passed since the last trade
|
||||
if (TimeCurrent() - lastTradeTime >= tradeCooldownMinutes * 60) {
|
||||
// Calculate ATR (Average True Range) for stop loss calculation
|
||||
double atrArray[];
|
||||
int atrPeriod = 14; // ATR period (can be adjusted)
|
||||
int copied = CopyBuffer(iATR(Symbol(), Period(), atrPeriod), 0, 0, 1, atrArray);
|
||||
if (copied < 1) {
|
||||
Print("Failed to get ATR values. Error code: ", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current price (using Bid price)
|
||||
double currentPrice = Bid;
|
||||
// Get ATR value
|
||||
double atrValue = atrArray[0]; // Latest ATR value
|
||||
|
||||
// Get the minimum stop level and freeze level for the symbol
|
||||
long stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
|
||||
long freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL);
|
||||
|
||||
// Calculate the minimum stop loss in price units (converted from pips)
|
||||
double minStopLoss = stopLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
|
||||
double minFreezeLevel = freezeLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
|
||||
|
||||
// Dynamic Stop Loss and Take Profit calculation based on ATR
|
||||
double dynamicSL = atrValue * atrMultiplier;
|
||||
double dynamicTP = atrValue * atrMultiplier;
|
||||
|
||||
// Adjust SL and TP if they are smaller than the minimum stop level
|
||||
dynamicSL = MathMax(dynamicSL, minStopLoss);
|
||||
dynamicTP = MathMax(dynamicTP, dynamicSL); // Ensure TP is at least the same as SL
|
||||
|
||||
// Trade logic based on the score
|
||||
if (currentScore > scoreThreshold) { // Buy signal
|
||||
if ((!PositionSelect(Symbol()) || PositionGetInteger(POSITION_MAGIC) != MagicNumber)
|
||||
&& crossoverTradeCount < maxCrossoverTrades) {
|
||||
Print("maxCrossover");
|
||||
Print(crossoverTradeCount);
|
||||
// Open buy position with dynamic SL and TP
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Buy(lotSize, Symbol(), currentPrice, Bid - dynamicSL, 0)) {
|
||||
Print("Buy order executed with score: ", currentScore);
|
||||
crossoverTradeCount++; // Increment trade count
|
||||
lastTradeTime = TimeCurrent(); // Update the last trade time
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (currentScore < -scoreThreshold) { // Sell signal
|
||||
if ((!PositionSelect(Symbol()) || PositionGetInteger(POSITION_MAGIC) != MagicNumber)
|
||||
&& crossoverTradeCount < maxCrossoverTrades) {
|
||||
Print("maxCrossover");
|
||||
Print(crossoverTradeCount);
|
||||
// Open sell position with dynamic SL and TP
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Sell(lotSize, Symbol(), currentPrice, Ask + dynamicSL, 0)) {
|
||||
Print("Sell order executed with score: ", currentScore);
|
||||
crossoverTradeCount++; // Increment trade count
|
||||
lastTradeTime = TimeCurrent(); // Update the last trade time
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Print("Trade skipped due to debounce: ", currentScore);
|
||||
}
|
||||
|
||||
// Check existing positions for profit and place reverse trade if needed
|
||||
CheckPositions();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing positions for profit and place reverse trade if needed |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing positions for duration and place reverse trade if needed |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckPositions() {
|
||||
// Check if there are any open positions
|
||||
if (PositionsTotal() > 0) {
|
||||
// Check if there are exactly 2 open positions
|
||||
if (PositionsTotal() == 2) {
|
||||
for (int i = 0; i < PositionsTotal(); i++) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
|
||||
long tradeLength = (long)(TimeCurrent() - openTime);
|
||||
|
||||
// Check if the trade has been open for more than the secondaryPositionHoldTime
|
||||
if (tradeLength > secondaryPositionHoldTime * 60) { // Convert threshold to seconds
|
||||
// Close all positions
|
||||
CloseAllPositions();
|
||||
Print("All positions closed due to exceeding secondaryPositionHoldTime");
|
||||
return; // Exit the function after closing all positions
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (PositionsTotal() < 2) {
|
||||
for (int i = 0; i < PositionsTotal(); i++) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
double profit = PositionGetDouble(POSITION_PROFIT);
|
||||
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
|
||||
long tradeLength = (long)(TimeCurrent() - openTime);
|
||||
|
||||
// Check if the trade has been open for more than the tradeLengthThreshold
|
||||
if (tradeLength > tradeLengthThreshold * 60) { // Convert threshold to seconds
|
||||
double lotSize = PositionGetDouble(POSITION_VOLUME);
|
||||
double newLotSize = lotSize * reverseLotSizeMultiplier; // 10 times the original lot size
|
||||
|
||||
crossoverTradeCount = maxCrossoverTrades + 1;
|
||||
|
||||
// Place a reverse trade
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Sell(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_BID))) {
|
||||
Print("Reversal sell order executed with increased lot size");
|
||||
} else {
|
||||
Print("Failed to execute reversal sell order");
|
||||
}
|
||||
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Buy(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_ASK))) {
|
||||
Print("Reversal buy order executed with increased lot size");
|
||||
} else {
|
||||
Print("Failed to execute reversal buy order");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the trade if profit meets the take profit level
|
||||
if (profit >= reverseTP) {
|
||||
Close_Position_MN(MagicNumber);
|
||||
CloseAllPositions();
|
||||
}
|
||||
|
||||
// Check if there is only one position and its volume is lotSize * reverseLotSizeMultiplier
|
||||
if (PositionsTotal() == 1 && PositionGetDouble(POSITION_VOLUME) == minimumLotSize * reverseLotSizeMultiplier) {
|
||||
trade.PositionClose(ticket);
|
||||
Print("Single position with volume equal to lotSize * reverseLotSizeMultiplier closed");
|
||||
}
|
||||
|
||||
// Get the current Ask and Bid prices
|
||||
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
|
||||
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
|
||||
|
||||
|
||||
// Check if the double down trade is exited by stop loss
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetDouble(POSITION_SL) > 0 && Bid <= PositionGetDouble(POSITION_SL)) {
|
||||
// Close the original trade
|
||||
CloseOriginalTrade();
|
||||
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetDouble(POSITION_SL) > 0 && Ask >= PositionGetDouble(POSITION_SL)) {
|
||||
// Close the original trade
|
||||
CloseOriginalTrade();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to close the original trade
|
||||
void CloseOriginalTrade() {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
trade.PositionClose(ticket);
|
||||
Print("Original buy position closed due to double down stop loss.");
|
||||
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
trade.PositionClose(ticket);
|
||||
Print("Original sell position closed due to double down stop loss.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function to close all positions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CloseAllPositions() {
|
||||
// Loop through all positions and close them
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
trade.PositionClose(ticket);
|
||||
Print("Buy position closed at score crossover.");
|
||||
}
|
||||
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
trade.PositionClose(ticket);
|
||||
Print("Sell position closed at score crossover.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyTrailingStop()
|
||||
{
|
||||
for(int i=PositionsTotal()-1; i>=0; i--)
|
||||
{
|
||||
string symbol = PositionGetSymbol(i);
|
||||
ulong PositionTicket = PositionGetTicket(i);
|
||||
long trade_type = PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
|
||||
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
|
||||
|
||||
|
||||
if(trade_type == 0)
|
||||
{
|
||||
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
|
||||
|
||||
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
|
||||
{
|
||||
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
|
||||
{
|
||||
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(trade_type == 1)
|
||||
{
|
||||
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
|
||||
|
||||
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
|
||||
{
|
||||
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
|
||||
{
|
||||
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Close_Position_MN(ulong magicNumber)
|
||||
{
|
||||
int total = PositionsTotal();
|
||||
for(int i = total - 1; i >= 0; i--)
|
||||
{
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
|
||||
// Use PositionSelect by symbol instead of ticket
|
||||
string symbol = PositionGetSymbol(i);
|
||||
if(PositionSelect(symbol))
|
||||
{
|
||||
if (PositionGetInteger(POSITION_MAGIC) == magicNumber && PositionGetInteger(POSITION_TICKET) == ticket)
|
||||
{
|
||||
if(symbol == _Symbol) // Verify the symbol
|
||||
{
|
||||
Print("MN ", magicNumber);
|
||||
trade.PositionClose(ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int errorCode = GetLastError();
|
||||
Print("aaaa PositionSelect failed with error code: ", errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate the dynamic lot size based on max drawdown |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateLotSize()
|
||||
{
|
||||
double balance = AccountInfoDouble(ACCOUNT_BALANCE); // Get account balance
|
||||
double allowedDrawdown = balance * max_drawdown; // Calculate allowed drawdown in account currency
|
||||
double baseDrawdownPerLot = 150; // Assumed drawdown per 0.01 lots as per backtest
|
||||
|
||||
// Calculate lot size based on maximum drawdown
|
||||
double lotSize = (allowedDrawdown / baseDrawdownPerLot) * 0.01;
|
||||
return NormalizeDouble(lotSize, 2); // Normalize lot size to 2 decimal places
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
; READY_EMACrossOverXAUUSD.mq5 — Genetic optimization (sanitized ranges)
|
||||
; Load: Strategy Tester → Inputs → Load
|
||||
; Format: Name=Default||Min||Step||Max||Y/N
|
||||
;
|
||||
; Units (read before optimizing):
|
||||
; slopeThreshold — |ΔEMA|×100 per chart bar; ~93 ≈ $0.93 EMA move (H1 EMA, checked each tick)
|
||||
; distanceThreshold — |price−EMA| in price ($ for XAUUSD)
|
||||
; cooldown* — minutes
|
||||
; atrMultiplier — stop distance = ATR(14) × multiplier (price $)
|
||||
; TrailingStop — trail in symbol POINTS (0.01 pt on XAU: 500≈$5). EA default 5≈$0.05 — set uses 500 for tests.
|
||||
; reverseTP — close reversal basket when profit ≥ this (account currency)
|
||||
; reverseLotSizeMultiplier — reversal volume = position volume × this (dangerous above ~5)
|
||||
; score* — arbitrary units; keep threshold ~4–10× crossOverStep or ~8–15 ticks of slope step
|
||||
;
|
||||
; ENUM_TIMEFRAMES: H1=16385 — fixed; do not sweep enum range.
|
||||
|
||||
; === fixed ===
|
||||
MagicNumber=42||42||1||42||N
|
||||
minimumLotSize=0.01||0.01||0||0.01||N
|
||||
emaTimeFrame=16385||16385||0||16385||N
|
||||
UseTrailingStop=true||false||0||true||N
|
||||
maxScore=7900||7900||0||7900||N
|
||||
emaDecayStep=0||0||0||0||N
|
||||
resetCrossoverTradeOnDistance=false||false||0||false||N
|
||||
resetCrossoverNumber=0||0||0||0||N
|
||||
maxTimeInPosition=9||9||0||9||N
|
||||
max_drawdown=0.1||0.1||0||0.1||N
|
||||
|
||||
; === EMA / slope (price-scaled) ===
|
||||
emaPeriod=64||40||4||88||Y
|
||||
slopeThreshold=93||50||5||140||Y
|
||||
distanceThreshold=28.5||12.0||2.0||45.0||Y
|
||||
|
||||
; === score increments (keep proportional to scoreThreshold) ===
|
||||
scoreThreshold=5200||3500||250||7000||Y
|
||||
crossOverStep=950||600||50||1400||Y
|
||||
slopeThresholdStep=635||350||50||950||Y
|
||||
emaDistanceStep=150||75||25||250||Y
|
||||
delayClampAbsolute=1690||1000||100||2500||Y
|
||||
decayMultiplier=0.08||0.03||0.01||0.15||Y
|
||||
|
||||
; === timing ===
|
||||
cooldownMinutes=18||8||2||35||Y
|
||||
tradeCooldownMinutes=24||12||3||48||Y
|
||||
maxCrossoverTrades=4||2||1||6||Y
|
||||
|
||||
; === stops / trail ===
|
||||
atrMultiplier=7.6||4.0||0.5||12.0||Y
|
||||
TrailingStop=500||200||50||1000||Y
|
||||
|
||||
; === reversal / hold (minutes & account $) ===
|
||||
tradeLengthThreshold=98||60||10||180||Y
|
||||
secondaryPositionHoldTime=32||15||5||60||Y
|
||||
reverseTP=32||15||5||80||Y
|
||||
reverseLotSizeMultiplier=15||4||1||20||Y
|
||||
Reference in New Issue
Block a user