Gold Snap Clean Room
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «gold snap v1.0 (1).mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Gold Snap Clean Room — торговый советник для MetaTrader 5, ориентированный на торговлю золотом (XAUUSD/GOLD). Продукт реализует адаптивный анализ ценовой структуры и автоматическое размещение отложенных ордеров при пробое уровней поддержки и сопротивления.
Советник анализирует ценовые данные на выбранном таймфрейме, выявляя свежие максимумы и минимумы. При приближении цены к обнаруженным уровням размещаются отложенные ордера Buy Stop и Sell Stop с адаптивными стоп-лоссами, рассчитанными на основе индикатора ATR.
Встроенная система управления рисками включает расчёт объёма по фиксированному лоту или проценту от риска, трейлинг-стоп с одним или двумя этапами срабатывания, фиксацию безубыточности, контроль спреда и автоматическое удаление отложенных ордеров в пятницу.
Советник отображает информационную панель с текущим статусом системы, значением спреда и состоянием позиций, обновляемую в реальном времени.
Настройки программы
| Настройка | Описание |
|---|---|
| InpMagic | Магический номер для идентификации ордеров и позиций, управляемых советником. |
| InpLotMode | Режим расчёта объёма: фиксированный лот или расчёт по проценту от риска. |
| InpFixedLot | Фиксированный размер лота при ручном режиме расчёта объёма. |
| InpRiskPercent | Процент от баланса счёта, используемый для расчёта объёма при режиме риска. |
| InpAllowBuy | Переключатель разрешения размещения отложенных ордеров Buy Stop при пробое уровня вверх. |
| InpAllowSell | Переключатель разрешения размещения отложенных ордеров Sell Stop при пробое уровня вниз. |
| InpStructureTimeframe | Таймфрейм, на котором анализируется ценовая структура для определения уровней. |
| InpPivotWing | Количество баров по обе стороны от проверяемого бара для подтверждения свежего максимума или минимума. |
| InpMaximumPivotAgeHours | Максимальный возраст ценового уровня в часах, после которого уровень перестаёт учитываться. |
| InpPendingExpiryHours | Время жизни отложенных ордеров в часах. |
| InpEntryBufferPrice | Дополнительный сдвиг цены входа при определении уровней поддержки и сопротивления. |
| InpMinimumLevelDistance | Минимально допустимое расстояние от текущей цены до уровня в пунктах для размещения ордера. |
| InpMaximumLevelDistance | Максимально допустимое расстояние от текущей цены до уровня в пунктах для размещения ордера. |
| InpMaximumSpreadPrice | Максимально допустимый спред в цене для размещения ордеров. |
| InpATRPeriod | Период расчёта индикатора ATR, используемого для адаптивного определения расстояния стоп-лосса. |
| InpStopATRMultiplier | Множитель ATR для расчёта расстояния стоп-лосса. |
| InpMinimumStopPrice | Нижний предел расстояния стоп-лосса в цене. |
| InpMaximumStopPrice | Верхний предел расстояния стоп-лосса в цене. |
| InpRewardRisk | Соотношение целевой прибыли к расстоянию стоп-лосса. |
| InpTrailArmPrice | Уровень прибыли в цене, при достижении которого активируется трейлинг-стоп. |
| InpTrailDistancePrice | Расстояние от текущей цены до уровня трейлинг-стопа в цене. |
| InpTrailStepPrice | Минимальный шаг перемещения трейлинг-стопа в цене. |
| InpUseTwoStageTrail | Переключатель двухэтапного трейлинга с промежуточной фиксацией безубыточности. |
| InpBreakEvenLockPrice | Расстояние в цене для фиксации безубыточности при двухэтапном трейлинге. |
| InpRunnerArmPrice | Уровень прибыли, при котором активируется второй этап трейлинга. |
| InpDeleteFriday | Переключатель автоматического удаления всех отложенных ордеров в пятницу для защиты от выходных рисков. |
| InpFridayDeleteHour | Час в пятницу, после которого автоматически удаляются все отложенные ордера. |
| InpShowPanel | Переключатель отображения информационной панели на графике. |
| InpDarkChart | Переключатель тёмной темы графика при отображении панели. |
Поиск по коду файла
#property version "1.00"
#property strict
#property description "Adaptive XAU support/resistance breakout with fast profit capture"
#include <Trade/Trade.mqh>
enum GS_LOT_MODE { GS_FIXED_LOT=0, GS_RISK_PERCENT=1 };
input group "===== GOLD SNAP CLEAN ROOM ====="
input long InpMagic = 26981;
input GS_LOT_MODE InpLotMode = GS_FIXED_LOT;
input double InpFixedLot = 0.01;
input double InpRiskPercent = 1.00;
input bool InpAllowBuy = true;
input bool InpAllowSell = true;
input group "===== EMBEDDED BEST-PERFORMANCE LOGIC ====="
input ENUM_TIMEFRAMES InpStructureTimeframe = PERIOD_H1;
input int InpPivotWing = 2;
input int InpMaximumPivotAgeHours = 1440;
input int InpPendingExpiryHours = 18;
input double InpEntryBufferPrice = 0.00;
input double InpMinimumLevelDistance = 5.00;
input double InpMaximumLevelDistance = 180.00;
input double InpMaximumSpreadPrice = 0.50;
input group "===== ADAPTIVE PROTECTION ====="
input int InpATRPeriod = 14;
input double InpStopATRMultiplier = 0.60;
input double InpMinimumStopPrice = 7.50;
input double InpMaximumStopPrice = 9.20;
input double InpRewardRisk = 1.90;
input double InpTrailArmPrice = 1.60;
input double InpTrailDistancePrice = 0.30;
input double InpTrailStepPrice = 0.15;
input bool InpUseTwoStageTrail = false;
input double InpBreakEvenLockPrice = 0.20;
input double InpRunnerArmPrice = 5.00;
input bool InpDeleteFriday = true;
input int InpFridayDeleteHour = 20;
input group "===== DISPLAY ====="
input bool InpShowPanel = true;
input bool InpDarkChart = true;
CTrade trade;
int atr_handle=INVALID_HANDLE;
datetime last_scan_bar=0;
string ui_prefix="GSCR_";
string status_text="INITIALIZING";
bool render_panel=false;
const color C_BG=C'9,14,25',C_CARD=C'20,29,46',C_EDGE=C'198,156,69',C_TEXT=C'235,238,244',C_MUTED=C'142,156,181',C_GREEN=C'31,222,156',C_RED=C'255,79,112',C_CYAN=C'70,209,255',C_GOLD=C'241,190,76';
double TickSize()
{
double value=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
if(value<=0.0) value=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
return value;
}
double NormalizePrice(const double price)
{
const double tick=TickSize();
const int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
if(tick<=0.0) return NormalizeDouble(price,digits);
return NormalizeDouble(MathRound(price/tick)*tick,digits);
}
double Clamp(const double value,const double low,const double high)
{
return MathMax(low,MathMin(high,value));
}
double BrokerMinimumDistance()
{
const double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
const long stops=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
const long freeze=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_FREEZE_LEVEL);
return MathMax((double)MathMax(stops,freeze)*point,TickSize()*2.0);
}
double CurrentSpread()
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol,tick)) return DBL_MAX;
return tick.ask-tick.bid;
}
bool IsGold()
{
string upper=_Symbol;
StringToUpper(upper);
return StringFind(upper,"XAU")>=0 || StringFind(upper,"GOLD")>=0;
}
bool SpreadAllowed()
{
return CurrentSpread()<=MathMax(BrokerMinimumDistance(),InpMaximumSpreadPrice);
}
double ATRValue()
{
double value[1];
if(atr_handle==INVALID_HANDLE || CopyBuffer(atr_handle,0,1,1,value)!=1) return 0.0;
return value[0];
}
double NormalizeVolume(double lots)
{
const double minimum=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
const double maximum=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
if(step<=0.0) step=minimum;
lots=Clamp(lots,minimum,maximum);
lots=MathFloor(lots/step+1e-8)*step;
return NormalizeDouble(lots,8);
}
double EntryLots(const ENUM_ORDER_TYPE type,const double entry,const double sl)
{
if(InpLotMode==GS_FIXED_LOT) return NormalizeVolume(InpFixedLot);
const double budget=AccountInfoDouble(ACCOUNT_BALANCE)*Clamp(InpRiskPercent,0.05,10.0)/100.0;
double loss=0.0;
if(!OrderCalcProfit(type,_Symbol,1.0,entry,sl,loss) || loss>=0.0) return NormalizeVolume(InpFixedLot);
return NormalizeVolume(budget/MathAbs(loss));
}
bool MarginAvailable(const ENUM_ORDER_TYPE type,const double lots,const double entry)
{
double margin=0.0;
if(!OrderCalcMargin(type,_Symbol,lots,entry,margin)) return false;
return AccountInfoDouble(ACCOUNT_MARGIN_FREE)>margin*1.10;
}
bool OurPosition(ulong &ticket,long &type,double &open,double &sl,double &tp)
{
for(int i=PositionsTotal()-1;i>=0;i--)
{
const ulong candidate=PositionGetTicket(i);
if(candidate==0 || PositionGetString(POSITION_SYMBOL)!=_Symbol || PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
ticket=candidate; type=PositionGetInteger(POSITION_TYPE); open=PositionGetDouble(POSITION_PRICE_OPEN);
sl=PositionGetDouble(POSITION_SL); tp=PositionGetDouble(POSITION_TP); return true;
}
return false;
}
int PendingCount(const int side)
{
int count=0;
for(int i=OrdersTotal()-1;i>=0;i--)
{
const ulong ticket=OrderGetTicket(i);
if(ticket==0 || OrderGetString(ORDER_SYMBOL)!=_Symbol || OrderGetInteger(ORDER_MAGIC)!=InpMagic) continue;
const ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
if((side>0 && type==ORDER_TYPE_BUY_STOP) || (side<0 && type==ORDER_TYPE_SELL_STOP)) count++;
}
return count;
}
void DeletePending(const string reason)
{
trade.SetExpertMagicNumber(InpMagic);
for(int i=OrdersTotal()-1;i>=0;i--)
{
const ulong ticket=OrderGetTicket(i);
if(ticket==0 || OrderGetString(ORDER_SYMBOL)!=_Symbol || OrderGetInteger(ORDER_MAGIC)!=InpMagic) continue;
const ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
if(type!=ORDER_TYPE_BUY_STOP && type!=ORDER_TYPE_SELL_STOP) continue;
if(!trade.OrderDelete(ticket)) PrintFormat("Gold Snap CR delete rejected %I64u (%u): %s",ticket,trade.ResultRetcode(),trade.ResultRetcodeDescription());
}
if(reason!="") status_text=reason;
}
bool FreshHigh(const MqlRates &rates[],const int shift)
{
const double level=rates[shift].high;
for(int i=1;i<=InpPivotWing;i++) if(rates[shift-i].high>=level || rates[shift+i].high>level) return false;
for(int newer=0;newer<shift;newer++) if(rates[newer].high>=level) return false;
return true;
}
bool FreshLow(const MqlRates &rates[],const int shift)
{
const double level=rates[shift].low;
for(int i=1;i<=InpPivotWing;i++) if(rates[shift-i].low<=level || rates[shift+i].low<level) return false;
for(int newer=0;newer<shift;newer++) if(rates[newer].low<=level) return false;
return true;
}
bool FindFreshLevels(double &buy_level,double &sell_level)
{
buy_level=0.0; sell_level=0.0;
MqlTick tick;
if(!SymbolInfoTick(_Symbol,tick)) return false;
const int bars=MathMax(200,InpMaximumPivotAgeHours*60/PeriodSeconds(InpStructureTimeframe)+InpPivotWing+10);
MqlRates rates[];
ArraySetAsSeries(rates,true);
const int copied=CopyRates(_Symbol,InpStructureTimeframe,0,bars,rates);
if(copied<InpPivotWing*2+20) return false;
double newer_high=-DBL_MAX;
double newer_low=DBL_MAX;
for(int i=0;i<=InpPivotWing;i++)
{
newer_high=MathMax(newer_high,rates[i].high);
newer_low=MathMin(newer_low,rates[i].low);
}
for(int shift=InpPivotWing+1;shift<copied-InpPivotWing;shift++)
{
const double age_hours=(double)(TimeCurrent()-rates[shift].time)/3600.0;
if(age_hours>InpMaximumPivotAgeHours) break;
bool older_high_ok=true,older_low_ok=true;
for(int wing=1;wing<=InpPivotWing;wing++)
{
if(rates[shift+wing].high>rates[shift].high) older_high_ok=false;
if(rates[shift+wing].low<rates[shift].low) older_low_ok=false;
}
if(buy_level==0.0 && rates[shift].high>newer_high && older_high_ok)
{
const double Показано первые 50% кода (символов: 14224)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.