指定
//+------------------------------------------------------------------+
//| Expert - Advanced Scalper + Smart Grid (MQL5) |
//| Features: News filter (CSV), Spread filter, Session filter |
//| Dynamic Lot (ATR), Auto Distance Grid, Max Exposure, Drawdown |
//| Volatility filter, Spread explosion block, Night Mode, Timeout |
//| Profit Lock, Recovery Time-Out |
//| Note: Test extensively on demo before live. |
//+------------------------------------------------------------------+
#property copyright "XSprint"
#property version "1.00"
#property strict
#include <Trade\Trade.mqh>
CTrade trade;
//------ INPUTS ------
input double DefaultLot = 0.01; // Default lot
input double MaxExposureLots = 0.20; // Max total lots exposure
input int GridMaxLevels = 4; // Max grid steps
input int GridStepPoints = 150; // Base grid distance in points
input double GridMultiplier[] = {1.0,1.0,2.0,2.0}; // Multipliers per level
input int ATRPeriod = 14;
input double ATRMultiplierForLot = 0.01; // lot = DefaultLot * (ATR / ATRMultiplierForLot) capped
input int MinSpreadPoints = 10; // max allowed spread (points) to open trades
input double MaxSpreadExplosionFactor = 4.0; // block if spread > factor * avgSpread
input int AvgSpreadPeriod = 200; // period to calculate avg spread
input int VolatilityPeriod = 50; // lookback for volatility filter
input double MaxVolatilityPoints = 600; // if volatility > this, block entries
input double DailyDrawdownPercent = 10.0; // stop EA if drawdown % reached
input int NewsBlockMinutesBefore = 30; // block minutes before news
input int NewsBlockMinutesAfter = 45; // block minutes after news
input int RecoveryConsecutiveLosses = 3; // trigger timeout after n losses
input int RecoveryTimeoutMinutes = 60; // minutes to stop after consecutive losses
input double ProfitLockPercent = 0.3; // lock grid when profit target reached as % balance
input bool LondonSessionOnly = true; // restrict to London+NY session default
input int LondonStartHour = 8; // local broker server hours (adjustable)
input int LondonEndHour = 17;
input int NYStartHour = 12;
input int NYEndHour = 21;
input bool NightModeDisableAsia = true; // disable heavy scalping in Asia
// Files
string NewsFile = "news_schedule.csv"; // place in MQL5/Files/
//------ GLOBALS ------
double avgSpread = 0.0;
int spreadSamples = 0;
int consecutiveLosses = 0;
datetime recoveryStopUntil = 0;
bool allowTrading = true;
// Grid tracking structure
struct GridOrder {
ulong ticket;
double volume;
double openPrice;
bool isBuy;
};
CArrayObj gridOrders;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
gridOrders.Clear();
// initialize avg spread
avgSpread = GetAvgSpread();
Print("XSprint initialized. AvgSpread=", avgSpread);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Deinit |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// cleanup
}
//+------------------------------------------------------------------+
//| OnTick |
//+------------------------------------------------------------------+
void OnTick()
{
if(!allowTrading) return;
// recovery timeout check
if(TimeCurrent() < recoveryStopUntil)
{
// still in recovery timeout
return;
}
// spread check
double spread = SymbolInfoDouble(_Symbol,SYMBOL_SPREAD); // in points
UpdateAvgSpread(spread);
if(spread > MinSpreadPoints)
{
// Spread too high -> no new trades
// but allow managing existing trades
}
if(IsSpreadExplosion(spread))
{
Print("Spread explosion detected, blocking new trades. Spread=",spread," avg=",avgSpread);
return;
}
// news filter
if(IsNewsBlocked(TimeCurrent()))
{
// block opening new trades
return;
}
// session filter
if(!IsSessionAllowed(TimeCurrent()))
{
return;
}
// volatility filter
double vol = CalculateVolatility();
if(vol > MaxVolatilityPoints)
{
// too volatile
return;
}
// dynamic lot calculation
double lot = CalculateDynamicLot();
// Check max exposure
double currentLots = GetCurrentExposureLots();
if(currentLots >= MaxExposureLots)
{
Print("Max exposure reached. Current lots=", currentLots);
return;
}
// trading logic: combination of simple scalping entry + grid management
ManageOpenGrid();
// decide new scalping entry
if(CanOpenNewTrade(spread, lot))
{
// Decide direction using short term trend (MA)
bool wantBuy = IsShortTermBull();
double price = wantBuy ? SymbolInfoDouble(_Symbol,SYMBOL_ASK) : SymbolInfoDouble(_Symbol,SYMBOL_BID);
OpenScalp(wantBuy, lot);
}
}
//+------------------------------------------------------------------+
//| Utilities & Core Logic |
//+------------------------------------------------------------------+
double GetAvgSpread()
{
double s=0;
int cnt=0;
for(int i=0;i<MathMin(AvgSpreadPeriod,Bars(_Symbol,PERIOD_M1));i++)
{
double high = iHigh(_Symbol,PERIOD_M1,i);
double low = iLow(_Symbol,PERIOD_M1,i);
double spr = (high - low) / SymbolInfoDouble(_Symbol,SYMBOL_POINT); // approximate rough
s += spr;
cnt++;
}
if(cnt==0) return(SymbolInfoDouble(_Symbol,SYMBOL_SPREAD));
return(s/cnt);
}
void UpdateAvgSpread(double current)
{
// simple rolling average
spreadSamples++;
avgSpread = ((avgSpread*(spreadSamples-1)) + current) / spreadSamples;
}
bool IsSpreadExplosion(double spread)
{
if(avgSpread <= 0) return(false);
if(spread > avgSpread * MaxSpreadExplosionFactor) return(true);
return(false);
}
// News filter: read CSV with date/time of important news
bool IsNewsBlocked(datetime nowtime)
{
// try read file once per tick
string lines[];
if(!FileIsExist(NewsFile))
{
// no file -> not blocked
return(false);
}
int handle = FileOpen(NewsFile,FILE_READ|FILE_ANSI);
if(handle < 0) return(false);
while(!FileIsEnding(handle))
{
string row = FileReadString(handle);
if(StringTrim(row) == "") continue;
// expected CSV: YYYY-MM-DD,HH:MM,importance,desc
string parts[];
int pc = StringSplit(row,',',parts);
if(pc<2) continue;
string dstr = parts[0];
string tstr = parts[1];
string dt = dstr + " " + tstr + ":00";
datetime newsTime = StringToTime(dt);
if(newsTime==0) continue;
// if within before/after window
if( nowtime >= (newsTime - NewsBlockMinutesBefore*60) && nowtime <= (newsTime + NewsBlockMinutesAfter*60) )
{
FileClose(handle);
return(true);
}
}
FileClose(handle);
return(false);
}
// session allowed check
bool IsSessionAllowed(datetime nowtime)
{
// use server time hours
MqlDateTime t;
TimeToStruct(nowtime,t);
int h = t.hour;
if(LondonSessionOnly)
{
// allow London or NY
bool inLondon = (h >= LondonStartHour && h < LondonEndHour);
bool inNY = (h >= NYStartHour && h < NYEndHour);
if(!(inLondon || inNY))
return(false);
}
if(NightModeDisableAsia)
{
// block typical Asia hours (00:00 - 06:00 server)
if(h >= 0 && h < 6) return(false);
}
return(true);
}
// volatility measure: high-low over last VolatilityPeriod M1 bars
double CalculateVolatility()
{
int bars = MathMin(VolatilityPeriod,Bars(_Symbol,PERIOD_M1)-1);
if(bars <= 1) return(0);
double high = iHigh(_Symbol,PERIOD_M1,ArrayMaximum(iHighArray(_Symbol,PERIOD_M1,bars)));
double low = iLow(_Symbol,PERIOD_M1,ArrayMinimum(iLowArray(_Symbol,PERIOD_M1,bars)));
double vol = (high - low) / SymbolInfoDouble(_Symbol,SYMBOL_POINT);
// fallback simple calc
double h = iHigh(_Symbol,PERIOD_M1,0);
double l = iLow(_Symbol,PERIOD_M1,0);
return(MathAbs(h-l)/SymbolInfoDouble(_Symbol,SYMBOL_POINT));
}
// helper arrays for volatility (fallback utilities)
doubleArray iHighArray(string symbol,ENUM_TIMEFRAMES tf,int count)
{
doubleArray arr;
arr.Resize(count);
for(int i=0;i<count;i++) arr[i]=iHigh(symbol,tf,i);
return(arr);
}
doubleArray iLowArray(string symbol,ENUM_TIMEFRAMES tf,int count)
{
doubleArray arr;
arr.Resize(count);
for(int i=0;i<count;i++) arr[i]=iLow(symbol,tf,i);
return(arr);
}
// dynamic lot based on ATR
double CalculateDynamicLot()
{
double atr = iATR(_Symbol,PERIOD_M5,ATRPeriod,0);
if(atr<=0) return(DefaultLot);
// ATR is in price units, convert to points
double atrPoints = atr / SymbolInfoDouble(_Symbol,SYMBOL_POINT);
double lot = DefaultLot * MathMax(1.0, atrPoints * ATRMultiplierForLot);
// cap lot so not exceed MaxExposure when combined
double currentLots = GetCurrentExposureLots();
double maxAdd = MathMax(0.0, MaxExposureLots - currentLots);
lot = MathMin(lot, maxAdd);
// round lot to minimal step
double step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
lot = MathFloor(lot/step)*step;
if(lot < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)) lot = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
return(lot);
}
// count current exposure lots on symbol
double GetCurrentExposureLots()
{
double sum=0;
for(int i=0;i<PositionsTotal();i++)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
if(PositionGetString(POSITION_SYMBOL)==_Symbol)
sum += PositionGetDouble(POSITION_VOLUME);
}
}
return(sum);
}
// decide if can open new trade
bool CanOpenNewTrade(double spread, double lot)
{
if(spread > MinSpreadPoints) return(false);
if(lot < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)) return(false);
// check balance drawdown protection
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
if((balance - equity)/balance*100.0 >= DailyDrawdownPercent)
{
Print("Drawdown limit reached. Stopping EA.");
allowTrading = false;
return(false);
}
return(true);
}
// simple short-term trend filter using moving averages
bool IsShortTermBull()
{
double maFast = iMA(_Symbol,PERIOD_M1,5,0,MODE_SMA,PRICE_CLOSE,0);
double maSlow = iMA(_Symbol,PERIOD_M1,21,0,MODE_SMA,PRICE_CLOSE,0);
return(maFast > maSlow);
}
// Open scalp trade
void OpenScalp(bool buy, double lot)
{
trade.SetTypeFilling(ORDER_FILLING_FOK);
trade.SetExpertMagicNumber(20251121);
bool res=false;
if(buy)
res = trade.Buy(lot,NULL,0,0,"XSprint scalp");
else
res = trade.Sell(lot,NULL,0,0,"XSprint scalp");
if(res)
{
ulong t = trade.ResultOrder();
PrintFormat("Opened scalp %s ticket=%d lot=%.2f", buy?"BUY":"SELL", t, lot);
// add to grid tracking as root position
GridOrder *g = new GridOrder();
g.ticket = t;
g.volume = lot;
g.openPrice = buy ? PositionGetDouble(POSITION_PRICE_OPEN) : PositionGetDouble(POSITION_PRICE_OPEN);
g.isBuy = buy;
gridOrders.Add(g);
}
else
{
Print("OpenScalp failed: ", trade.ResultRetcode(), " description: ", trade.ResultRetcodeDescription());
}
}
// Manage grid orders: if price moves against any position open grid steps
void ManageOpenGrid()
{
// iterate positions on symbol
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(!PositionGetTicket(i)) continue;
}
// For simplicity, check root position from gridOrders
for(int idx=0; idx<gridOrders.Total(); idx++)
{
GridOrder *g = (GridOrder*)gridOrders.At(idx);
if(g==NULL) continue;
// check if position still exists
if(!PositionSelect(_Symbol)) continue;
// find current price
double price = g.isBuy ? SymbolInfoDouble(_Symbol,SYMBOL_BID) : SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double diffPoints = MathAbs((price - g.openPrice)/SymbolInfoDouble(_Symbol,SYMBOL_POINT));
int levelsToOpen = MathFloor(diffPoints / GridStepPoints);
// open additional levels up to GridMaxLevels
int alreadyOpened = CountGridLevel(g.ticket);
for(int lvl = alreadyOpened; lvl< MathMin(levelsToOpen, GridMaxLevels); lvl++)
{
double mult = GridMultiplier[MathMin(lvl, ArraySize(GridMultiplier)-1)];
double addLot = g.volume * mult;
// ensure exposure
double currentLots = GetCurrentExposureLots();
if(currentLots + addLot > MaxExposureLots) break;
bool ok = false;
if(g.isBuy)
ok = trade.Sell(addLot,NULL,0,0,"XSprint grid"); // open opposite to hedge? Here we open same direction to average - adjust as design
else
ok = trade.Buy(addLot,NULL,0,0,"XSprint grid");
if(ok)
{
ulong t = trade.ResultOrder();
GridOrder *newg = new GridOrder();
newg.ticket = t;
newg.volume = addLot;
newg.openPrice = price;
newg.isBuy = !g.isBuy; // new direction
gridOrders.Add(newg);
PrintFormat("Opened grid lvl %d ticket=%d lot=%.2f", lvl, t, addLot);
}
else
{
Print("Grid open failed: ", trade.ResultRetcodeDescription());
}
}
}
// Profit lock / close grid if total profit reached
double profit = CalculateSymbolProfit();
double bal = AccountInfoDouble(ACCOUNT_BALANCE);
if(profit >= bal * ProfitLockPercent/100.0)
{
Print("Profit lock reached. Closing all grid positions with profit=", profit);
CloseAllSymbolPositions();
}
// auto drawdown stop (daily)
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double ddPercent = (balance - equity)/balance*100.0;
if(ddPercent >= DailyDrawdownPercent)
{
Print("Drawdown auto-stop triggered: ", ddPercent, "%");
allowTrading = false;
}
}
// Count number of grid levels for a root ticket (simple count by presence)
int CountGridLevel(ulong rootTicket)
{
int cnt=0;
for(int i=0;i<gridOrders.Total();i++)
{
GridOrder *g = (GridOrder*)gridOrders.At(i);
if(g==NULL) continue;
if(g.ticket==rootTicket) cnt++;
}
return(cnt);
}
// Calculate current profit on symbol (floating)
double CalculateSymbolProfit()
{
double p=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetTicket(i))
{
if(PositionGetString(POSITION_SYMBOL)==_Symbol)
p += PositionGetDouble(POSITION_PROFIT);
}
}
return(p);
}
void CloseAllSymbolPositions()
{
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong t = PositionGetTicket(i);
if(PositionSelectByTicket(t))
{
if(PositionGetString(POSITION_SYMBOL)==_Symbol)
{
double vol = PositionGetDouble(POSITION_VOLUME);
bool isBuy = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY);
if(isBuy) trade.PositionClose(t);
else trade.PositionClose(t);
}
}
}
}
// Simple record of result to detect consecutive losses
void UpdateConsecutiveLosses()
{
// Use history to find last closed trades on this symbol
ulong last_ticket = HistoryOrderGetTicket(HistoryOrderGetInteger(0));
// This is placeholder: in real implementation track closed trades and check P/L sign
}
//+------------------------------------------------------------------+
//| End of EA |
//+------------------------------------------------------------------+
反馈
1
等级
项目
2
0%
仲裁
0
逾期
0
繁忙
1
等级
项目
1
100%
仲裁
2
0%
/
100%
逾期
0
空闲
2
等级
项目
0
0%
仲裁
0
逾期
0
空闲
2
等级
项目
945
47%
仲裁
304
59%
/
26%
逾期
125
13%
工作中
3
等级
项目
1
0%
仲裁
0
逾期
0
空闲
3
等级
项目
0
0%
仲裁
0
逾期
0
空闲
4
等级
项目
0
0%
仲裁
0
逾期
0
工作中
发布者: 2 代码
4
等级
项目
2
0%
仲裁
0
逾期
0
工作中
5
等级
项目
24
38%
仲裁
1
100%
/
0%
逾期
3
13%
工作中
6
等级
项目
249
31%
仲裁
0
逾期
3
1%
空闲
发布者: 2 代码
相似订单
I’m looking for someone who’s proficient in pinescrip latest version. The candidate must understand dealing ranges. I will describe what I need for the range to be considered a dealing. It’s a 2 part indicator. Part 1 spots the dealing ranges based on my requirements and Prager 2: the script draws a circle from start to the end of dealing ranges then count some candles. The rest is simple math. But before moving to
I'm looking to create a Gold trading EA that focuses on rebate earnings rather than trading profits. The key requirement is for it to execute more than 20 trades per day without ending in a daily loss. Scope of work - Develop a Gold trading EA capable of executing over 20 trades per day. - Ensure that the daily trading results do not end in a loss. - Focus on rebate earnings rather than trading profits. Additional
I want an Expert Advisor that is based on core high-frequency scalping strategy. The EA will continuously place pending buy stop and sell stop orders at a fixed distance from the current Bid price, creating a grid around the price action. When price moves and triggers one of these orders, the EA will immediately close the opposite pending order and then place a new pair of buy and sell stop orders around the new
Project title: Forex & Futures Traders Hub
30 - 125 USD
Hello. We are looking for a group of developers or a software company to create a website that offers services for forex and futures traders. We need assistance with website development, launching service sales, and monitoring traders' accounts. If you have experience building websites and integrating service sales, please apply for this job
I Need a Trading Board I Have Replicated ASAP.
40 - 1000 USD
MQL5 Freelance Job Request: Trading Board Relocation & Rebuild Title: Rebuild & Relocate Existing Trading Board (Confluence Signal System) – MT4/MT5 --- Description: I already have a fully working version of a trading board / signal dashboard that generates trade signals based on a confluence of multiple technical factors. The software is unlicensed, not copyrighted, and not protected, and I legally own the files. I
Hello. We are looking for a group of developers or a software company to create a website that offers services for forex and futures traders. We need assistance with website development, launching service sales, and monitoring traders' accounts. If you have experience building websites and integrating service sales, please apply for this job
EA Base on FVG
50+ USD
i want to work with an professional mql developer. it would be better if you have created EA or indicator related to FVG before. Higher Time Frame POI - W , D , 4H Lower Time Frame Entry - 4H , 1H , 15min The EA looks for HTF fvg and then looks for fvg in LTF. if you think you can do it, please contact me
Footprint-based Reversal Entry EA with Multi-Filter Logic We’re seeking an experienced MQL5 developer to build an MT5 EA that enters trades based on reversal patterns detected from the ClusterDelta #Footprint indicator (CME futures volume). The EA must be flexible enough to trade GBPUSD and USDJPY, with parameters adaptable to any pair. Core requirements (see attached specification for full details): Trend Filter
MT5 mobile delayed charts
400 - 1100 USD
I am looking for delayed charts—specifically charts delayed by one day—that maintain the same market conditions and price behavior as the live market, just shifted in time. This could be provided either by a broker that offers delayed-market data or by a standalone Android application similar to MetaTrader 5
i need any gold scalper or flip EA that works that with 100 dollars balance and you can make just 1 dollar daily. i dont really mind the strategy use by the developer , i just want something that can scalp gold and make 1 dollar daily
项目信息
预算
100 - 200 USD
客户
所下订单2
仲裁计数0