Pingala Prasthara EA
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «pingala_prasthara_ea_v1_1.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Pingala Prasthara EA — торговый советник для MetaTrader 5, реализующий стратегию на основе анализа ценовых паттернов Пингала. Советник работает на структуре двух таймфреймов: сигнальный M5 и подтверждающий M15. Он анализирует свечные паттерны, направленное давление, концентрацию Меру и уровни Матрамеру на основе числовых последовательностей.
Вход в позицию осуществляется при выполнении комплекса условий: наличие паттерна Пингала с достаточным количеством гуру-кандлов, совпадение с уровнями Фибоначчи Матрамеру, подтверждение на старшем таймфрейме и прохождение фильтров по направленному давлению. Советник поддерживает частичное закрытие позиции при достижении первой цели (TP1) с возможностью переноса стоп-лосса в безубыток.
Система управления рисками включает расчёт объёма по процентному риску от баланса, ограничения по максимальной ежедневей убыли и количеству последовательных убытков. Доступны фильтр торговой сессии, ограничение спреда, проверка минимального расстояния стоп-лосса в зависимости от типа инструмента, а также детальное логирование в журнал для отладки.
Настройки программы
| Настройка | Описание |
|---|---|
| MagicNumber | Уникальный идентификатор советника. Используйте разные числа для отдельных настроек советника. |
| SignalTF | Таймфрейм для формирования сигнала. По умолчанию M5. На этом таймфрейме анализируется паттерн Пингала и рассчитываются основные показатели. |
| ConfirmTF | Таймфрейм подтверждения (старший по отношению к сигнальному). По умолчанию M15. Давление на этом таймфрейме должно совпадать с направлением сделки для подтверждения сигнала. |
| OnlyClosedBars | При активации (true) советник торгует только по завершённым свечам. Рекомендуется включать для фильтрации текущей незавершённой свечи. |
| PatternLengthN | Количество свечей в паттерне Пингала. По умолчанию 8. Определяет длину анализируемой последовательности для расчёта бинарного кода и баллов. |
| GuruThresholdATR | Доля ATR, при которой свеча считается Гуру. Свеча становится Гуру, если её движение (по модулю) больше или равно указанной доле ATR. По умолчанию 0.50. |
| MinDirectionalPressure | Минимальное направленное давление B. Значение 0.25 означает ±25%. Сигнал не проходит, если давление ниже этого порога. |
| MinMeruConcentration | Минимальный балл концентрации Меру (в диапазоне 0–100). Сигнал не проходит, если балл ниже этого значения. |
| MinPingalaScore | Минимальный общий балл Пингала (в диапазоне 0–100). Сигнал не проходит, если итоговый балл ниже этого порога. |
| RequireGuruExpansion | Требует наличия недавнего паттерна расширения от Лагху к Гуру. Для покупки: поздние Гуру свечи должны иметь больше бычьих, для продажи — больше медвежьих. |
| ExpansionLookback | Количество баров, проверяемых на наличие паттерна расширения от Лагху к Гуру. По умолчанию 4. |
| RequireMatrameruAlign | При активации требует совпадения показателя S с ближайшим уровнем Фибоначчи Матрамеру или движения к следующему уровню. |
| MatrameruMaxDistance | Максимальное расстояние от ближайшего уровня Матрамеру (в единицах показателя S), при котором считается, что позиция находится вблизи уровня Фибоначчи. |
| AllowMovingTowardNext | Разрешает принимать состояние, при котором текущий показатель S движется к следующему уровню Фибоначчи Матрамеру. Детерминистическая интерпретация: расстояние до следующего уровня Фибоначчи сокращается по сравнению с предыдущим окном. |
| RequireHigherTFConfirm | При активации требует, чтобы давление на таймфрейме ConfirmTF совпадало с направлением сделки (бычье для покупки, медвежье для продажи). |
| ATRPeriod | Период расчёта индикатора ATR (среднекратический диапазон). Используется для оценки волатильности при формировании сигналов и расчёте стоп-лосса. |
| MinATR | Минимальное значение ATR в единицах цены. Если 0 — ограничение отключено. Сделки не открываются при значении ATR ниже этого порога. |
| MaxATR | Максимальное значение ATR в единицах цены. Если 0 — ограничение отключено. Сделки не открываются при превышении этого порога волатильности. |
| MaxSpreadPoints | Максимальный спред в точках брокера (POINTS). Если 0 — ограничение отключено. Сделки не открываются при превышении спреда. |
| StopATRMultiplier | Множитель ATR для расчёта базового стоп-лосса. По умолчанию 1.20. Стоп-лосс рассчитывается как вход ± множитель × ATR. |
| SwingLookback | Количество баров, используемых для определения защитного свечного максимума/минимума (swing high/low), который используется при расчёте стоп-лосса. |
| UseMinimumSL | При активации применяется минимальное расстояние стоп-лосса, зависящее от типа инструмента: пипсы для форекса, цена для золота, цена для прочих символов. |
| MinimumSLForexPips | Минимальное расстояние стоп-лосса для валютных пар (5- и 3-значные котировки), указываемое в пунктах (пипсах). По умолчанию 5.0 = 5 пипсов. |
| MinimumSLGoldPrice | Минимальное расстояние стоп-лосса для символов XAU (золото), указываемое в единицах цены. 0 — отключено. |
| MinimumSLOtherPrice | Минимальное расстояние стоп-лосса для прочих символов, указываемое в единицах цены. 0 — отключено. |
| ScaleTargetsWithMinSL | Если минимальный стоп-лосс расширяет стоп, то цели TP1 и TP2 также расширяются на тот же коэффициент, сохраняя исходную геометрию вознаграждения/риска. |
| TP2Multiplier | Множитель ATR, применяемый к соотношению Пингала для расчёта второй цели (TP2). По умолчанию 1.60. |
| TP1ClosePercent | Процент позиции, закрываемый при достижении первой цели (TP1). По умолчанию 50.0%. |
| MoveSLToBEAfterTP1 | При активации после достижения TP1 происходит частичное закрытие позиции и перенос стоп-лосса оставшейся части в безубыток. |
| BreakEvenPlusPoints | Дополнительные точки брокера (POINTS) сверх точки входа, добавляемые при переносе стоп-лосса в безубыток после достижения TP1. |
| ExitOnPressureFlip | При активации советник закрывает позицию, если направленное давление развернулось против позиции на требуемое количество закрытых баров. |
| PressureFlipBars | Количество последовательных закрытых баров, необходимых для подтверждения разворота направленного давления против позиции при активированном ExitOnPressureFlip. |
| ExitOnOppositeSignal | При активации советник закрывает позицию при формировании полного высокодостоверного противоположного сигнала Пингала. |
| UseRiskPercent | При активации (true) объём лота рассчитывается автоматически на основе риска в процентах от баланса и расстояния стоп-лосса. При деактивации (false) используется фиксированный лот FixedLot. |
| RiskPerTradePercent | Процент баланса счёта, рискуемый на одну сделку. Используется для автоматического расчёта объёма лота при активированном UseRiskPercent. |
| FixedLot | Фиксированный размер лота, используемый только когда параметр UseRiskPercent отключён (false). |
| MaxDailyLossPercent | Процент от баланса счёта. При достижении указанной реализованной убыли за день новые входы блокируются. 0 — ограничение отключено. |
| MaxConsecutiveLosses | Максимальное количество последовательных убытков. При достижении этого числа новые входы блокируются. 0 — ограничение отключено. |
| MaxOpenPositions | Максимальное количество одновременных открытых позиций для данного символа и магического числа. |
| UseSessionFilter | При активации (true) советник торгует только в указанный временной интервал (с SessionStartHour до SessionEndHour) по серверному времени брокера. |
| SessionStartHour | Час начала торговой сессии в серверном времени брокера (0–23). Работает при активированном UseSessionFilter. |
| SessionEndHour | Час окончания торговой сессии в серверном времени брокера (0–23). Работает при активированном UseSessionFilter. |
| PrintDebug | При активации выводятся в журнал (Journal) подробности сигналов, фильтров, стоп-лосса/тейков и торговых операций для отладки. |
Поиск по коду файла
#property strict
#property version "1.10"
#property description "Pingala Prasthara strategy v1.10: M5/M15 structure, symbol-aware minimum SL, clearer inputs and diagnostics."
#include <Trade/Trade.mqh>
CTrade trade;
input group "1. GENERAL / TIMEFRAMES"
input ulong MagicNumber = 26090401; // Unique EA ID - use different number for separate EA setups
input ENUM_TIMEFRAMES SignalTF = PERIOD_M5; // Signal timeframe - strategy default M5
input ENUM_TIMEFRAMES ConfirmTF = PERIOD_M15; // Higher timeframe confirmation - strategy default M15
input bool OnlyClosedBars = true; // true = trade only completed candles (recommended)
input int PatternLengthN = 8; // Number of candles in Pingala pattern - default 8
input double GuruThresholdATR = 0.50; // Candle becomes Guru when move >= this fraction of ATR
input group "2. ENTRY FILTERS / SIGNAL QUALITY"
input double MinDirectionalPressure = 0.25; // Minimum directional pressure B; 0.25 = +/-25%
input double MinMeruConcentration = 65.0; // Minimum Meru concentration score (0-100)
input double MinPingalaScore = 75.0; // Minimum total Pingala score (0-100)
input bool RequireGuruExpansion = true; // Require recent Laghu-to-Guru expansion pattern
input int ExpansionLookback = 4; // Candles checked for expansion; default 4
input bool RequireMatrameruAlign = true; // Require Matrameru/Fibonacci state alignment
input double MatrameruMaxDistance = 1.0; // Maximum distance from nearest Matrameru level
input bool AllowMovingTowardNext = true; // Also accept state moving toward next Matrameru level
input bool RequireHigherTFConfirm = true; // Require ConfirmTF pressure in same trade direction
input group "3. ATR / VOLATILITY / SPREAD"
input int ATRPeriod = 14; // ATR calculation period
input double MinATR = 0.0; // Minimum ATR in PRICE UNITS; 0 = disabled
input double MaxATR = 0.0; // Maximum ATR in PRICE UNITS; 0 = disabled
input int MaxSpreadPoints = 30; // Maximum spread in broker POINTS; 0 = disabled
input group "4. STOP LOSS / TARGETS"
input double StopATRMultiplier = 1.20; // Base ATR stop multiplier; strategy default 1.20
input int SwingLookback = 5; // Bars used to find protective swing high/low
input bool UseMinimumSL = true; // Enforce a minimum stop distance by symbol type
input double MinimumSLForexPips = 5.0; // 5/3-digit forex: minimum SL in PIPS (5.0 = 5 pips)
input double MinimumSLGoldPrice = 0.0; // XAU symbols: minimum SL in PRICE ($); 0 = disabled
input double MinimumSLOtherPrice = 0.0; // Other symbols: minimum SL in PRICE units; 0 = disabled
input bool ScaleTargetsWithMinSL = true; // If minimum SL widens stop, widen TP1/TP2 by same factor
input double TP2Multiplier = 1.60; // TP2 ATR multiplier applied to Pingala ratio
input double TP1ClosePercent = 50.0; // Percent of position closed when TP1 is reached
input bool MoveSLToBEAfterTP1 = true; // Move remaining position stop to breakeven after TP1
input int BreakEvenPlusPoints = 0; // Extra broker POINTS beyond entry when moving to BE
input bool ExitOnPressureFlip = true; // Exit if directional pressure flips against position
input int PressureFlipBars = 2; // Consecutive closed bars required for pressure-flip exit
input bool ExitOnOppositeSignal = true; // Exit on a full opposite high-confidence Pingala signal
input group "5. MONEY / RISK MANAGEMENT"
input bool UseRiskPercent = true; // true = auto lot from SL risk; false = use FixedLot
input double RiskPerTradePercent = 0.50; // Account balance risk per trade in percent
input double FixedLot = 0.10; // Lot size used only when UseRiskPercent=false
input double MaxDailyLossPercent = 2.00; // Stop new entries after this realized daily loss; 0=off
input int MaxConsecutiveLosses = 3; // Stop new entries after this many losses; 0=off
input int MaxOpenPositions = 1; // Maximum simultaneous positions for this symbol/magic
input group "6. TRADING SESSION (BROKER SERVER TIME)"
input bool UseSessionFilter = false; // true = only trade between start/end hours below
input int SessionStartHour = 8; // Session start hour, broker/server time (0-23)
input int SessionEndHour = 18; // Session end hour, broker/server time (0-23)
input group "7. DEBUG / JOURNAL LOGGING"
input bool PrintDebug = true; // Print signal, filter, SL/TP and trade details to Journal
struct PingalaData
{
bool valid;
int N;
int guruCount;
int decimalValue;
int rank;
int matraS;
int nearestF;
int nextF1;
int nextF2;
double ratio1;
double ratio2;
double pressureB;
double meruScore;
double directionalStrength;
double matrameruAlignment;
double patternStrength;
double higherTFScore;
double pingalaScore;
bool nastaValid;
bool matrameruAligned;
bool guruExpansionBuy;
bool guruExpansionSell;
};
datetime g_lastSignalBar = 0;
ulong g_managedTicket = 0;
double g_initialVolume = 0.0;
bool g_tp1Done = false;
void Dbg(string s)
{
if(PrintDebug) Print("PINGALA: ", s);
}
int FibLevels[] = {1,2,3,5,8,13,21,34,55,89,144};
int FindNearestFib(const int S)
{
int best=FibLevels[0];
int bestDist=MathAbs(S-best);
for(int i=1;i<ArraySize(FibLevels);i++)
{
int d=MathAbs(S-FibLevels[i]);
if(d<bestDist)
{
best=FibLevels[i];
bestDist=d;
}
}
return best;
}
void GetFibTriplet(const int S,int &F,int &F1,int &F2)
{
F=FindNearestFib(S);
int idx=0;
for(int i=0;i<ArraySize(FibLevels);i++)
if(FibLevels[i]==F){ idx=i; break; }
F1 = FibLevels[MathMin(idx+1,ArraySize(FibLevels)-1)];
F2 = FibLevels[MathMin(idx+2,ArraySize(FibLevels)-1)];
}
double Combination(const int n,const int k)
{
if(k<0 || k>n) return 0.0;
int kk=MathMin(k,n-k);
double r=1.0;
for(int i=1;i<=kk;i++)
r = r * (n-kk+i) / i;
return r;
}
double GetATR(ENUM_TIMEFRAMES tf,int shift)
{
int h=iATR(_Symbol,tf,ATRPeriod);
if(h==INVALID_HANDLE) return 0.0;
double b[];
ArraySetAsSeries(b,true);
double v=0.0;
if(CopyBuffer(h,0,shift,1,b)==1) v=b[0];
IndicatorRelease(h);
return v;
}
bool IsGoldSymbol()
{
string s=_Symbol;
StringToUpper(s);
return (StringFind(s,"XAU")>=0);
}
double ForexPipSize()
{
int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
if(digits==5 || digits==3) return 10.0*_Point;
return _Point;
}
double MinimumSLDistancePrice()
{
if(!UseMinimumSL) return 0.0;
if(IsGoldSymbol())
return MathMax(0.0,MinimumSLGoldPrice);
int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
if(digits==5 || digits==3)
return MathMax(0.0,MinimumSLForexPips)*ForexPipSize();
return MathMax(0.0,MinimumSLOtherPrice);
}
double NormalizePrice(double p)
{
return NormalizeDouble(p,(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS));
}
double NormalizeVolume(double lots)
{
double minv=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double maxv=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
if(step<=0.0) step=minv;
lots=MathMax(minv,MathMin(maxv,lots));
lots=MathFloor(lots/step + 1e-9)*step;
int vd=2;
if(step>=1.0) vd=0;
else if(step>=0.1) vd=1;
else if(step>=0.01) vd=2;
else vd=3;
return NormalizeDouble(lots,vd);
}
bool InSession()
{
if(!UseSessionFilter) return true;
MqlDateTime dt; TimeToStruct(TimeCurrent(),dt);
if(SessionStartHour==SessionEndHour) return true;
if(SessionStartHour<SessionEndHour)
return (dt.hour>=SessionStartHour && dt.hour<SessionEndHour);
return (dt.hour>=SessionStartHour || dt.hour<SessionEndHour);
}
int CurrentSpreadPoints()
{
MqlTick t;
if(!SymbolInfoTick(_Symbol,t)) return 999999;
return (int)MathRound((t.ask-t.bid)/_Point);
}
int CountOurOpenPositions()
{
int count=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)==_Symbol &&
(ulong)PositionGetInteger(POSITION_MAGIC)==MagicNumber)
count++;
}
return count;
}
bool SelectOurPosition(ulong &ticket)
{
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong t=PositionGetTicket(i);
if(t==0 || !PositionSelectByTicket(t)) continue;
if(PositionGetString(POSITION_SYMBOL)==_Symbol &&
(ulong)PositionGetInteger(POSITION_MAGIC)==MagicNumber)
{
ticket=t;
return true;
}
}
return false;
}
double TodayProfit(int &consecutiveLosses)
{
consecutiveLosses=0;
MqlDateTime dt; TimeToStruct(TimeCurrent(),dt);
dt.hour=0; dt.min=0; dt.sec=0;
datetime dayStart=StructToTime(dt);
if(!HistorySelect(dayStart,TimeCurrent())) return 0.0;
double pnl=0.0;
int deals=HistoryDealsTotal();
for(int i=0;i<deals;i++)
{
ulong d=HistoryDealGetTicket(i);
if(d==0) continue;
if(HistoryDealGetString(d,DEAL_SYMBOL)!=_Symbol) continue;
if((ulong)HistoryDealGetInteger(d,DEAL_MAGIC)!=MagicNumber) continue;
if((ENUM_DEAL_ENTRY)HistoryDealGetInteger(d,DEAL_ENTRY)!=DEAL_ENTRY_OUT) continue;
pnl += HistoryDealGetDouble(d,DEAL_PROFIT)
+ HistoryDealGetDouble(d,DEAL_SWAP)
+ HistoryDealGetDouble(d,DEAL_COMMISSION);
}
for(int i=deals-1;i>=0;i--)
{
ulong d=HistoryDealGetTicket(i);
if(d==0) continue;
if(HistoryDealGetString(d,DEAL_SYMBOL)!=_Symbol) continue;
if((ulong)HistoryDealGetInteger(d,DEAL_MAGIC)!=MagicNumber) continue;
if((ENUM_DEAL_ENTRY)HistoryDealGetInteger(d,DEAL_ENTRY)!=DEAL_ENTRY_OUT) continue;
double p=HistoryDealGetDouble(d,DEAL_PROFIT)
+HistoryDealGetDouble(d,DEAL_SWAP)
+HistoryDealGetDouble(d,DEAL_COMMISSION);
if(p<0.0) consecutiveLosses++;
else if(p>0.0) break;
}
return pnl;
}
bool RiskLimitsOK()
{
int consec=0;
double pnl=TodayProfit(consec);
double bal=AccountInfoDouble(ACCOUNT_BALANCE);
if(MaxDailyLossPercent>0.0 && pnl <= -(bal*MaxDailyLossPercent/100.0))
{
Dbg(StringFormat("BLOCK daily loss: %.2f",pnl));
return false;
}
if(MaxConsecutiveLosses>0 && consec>=MaxConsecutiveLosses)
{
Dbg(StringFormat("BLOCK consecutive losses: %d",consec));
return false;
}
return true;
}
bool BuildPingalaData(ENUM_TIMEFRAMES tf,int startShift,PingalaData &pd)
{
pd.valid=false;
int N=MathMax(2,MathMin(PatternLengthN,16));
pd.N=N;
MqlRates rates[];
ArraySetAsSeries(rates,true);
if(CopyRates(_Symbol,tf,startShift,N+1,rates)<N+1)
return false;
int atrHandle=iATR(_Symbol,tf,ATRPeriod);
if(atrHandle==INVALID_HANDLE) return false;
double atr[];
ArraySetAsSeries(atr,true);
if(CopyBuffer(atrHandle,0,startShift,N+1,atr)<N+1)
{
IndicatorRelease(atrHandle);
return false;
}
IndicatorRelease(atrHandle);
int state[]; ArrayResize(state,N); // 0=L,1=G
int dir[]; ArrayResize(dir,N); // -1,0,+1
int weight[];ArrayResize(weight,N); // 1 or 2
int guru=0, S=0, bull=0, bear=0;
int dec=0;
for(int j=0;j<N;j++)
{
int i=N-1-j; // rates index: oldest selected candle toward newest
double change=rates[i].close-rates[i+1].close;
double a=atr[i];
if(a<=0.0) return false;
double M=MathAbs(change)/a;
state[j]=(M>=GuruThresholdATR ? 1:0);
weight[j]=(state[j]==1 ? 2:1);
dir[j]=(change>0.0 ? 1 : (change<0.0 ? -1:0));
if(state[j]==1) guru++;
S+=weight[j];
if(dir[j]>0) bull+=weight[j];
if(dir[j]<0) bear+=weight[j];
dec=(dec<<1)|state[j];
}
pd.guruCount=guru;
pd.matraS=S;
pd.decimalValue=dec;
pd.rank=(1<<N)-dec; // one-based ordering per infographic
int reconstructed=(1<<N)-pd.rank;
pd.nastaValid=(reconstructed==dec);
double ck=Combination(N,guru);
double cmax=0.0;
for(int k=0;k<=N;k++) cmax=MathMax(cmax,Combination(N,k));
pd.meruScore=(cmax>0.0 ? (1.0-ck/cmax)*100.0 : 0.0);
pd.meruScore=MathMax(0.0,MathMin(100.0,pd.meruScore));
int denom=bull+bear;
pd.pressureB=(denom>0 ? (double)(bull-bear)/(double)denom : 0.0);
pd.directionalStrength=MathAbs(pd.pressureB)*100.0;
GetFibTriplet(S,pd.nearestF,pd.nextF1,pd.nextF2);
pd.ratio1=(pd.nearestF>0 ? (double)pd.nextF1/(double)pd.nearestF : 1.0);
pd.ratio2=(pd.nearestF>0 ? (double)pd.nextF2/(double)pd.nearestF : 1.0);
double dist=MathAbs((double)S-(double)pd.nearestF);
bool near=(dist<=MatrameruMaxDistance);
bool moving=false;
if(AllowMovingTowardNext)
{
MqlRates prevRates[];
ArraySetAsSeries(prevRates,true);
if(CopyRates(_Symbol,tf,startShift+1,N+1,prevRates)>=N+1)
{
int prevS=0;
int prevAtrHandle=iATR(_Symbol,tf,ATRPeriod);
double prevAtr[]; ArraySetAsSeries(prevAtr,true);
if(prevAtrHandle!=INVALID_HANDLE && CopyBuffer(prevAtrHandle,0,startShift+1,N+1,prevAtr)>=N+1)
{
for(int j=0;j<N;j++)
{
int i=N-1-j;
double ch=prevRates[i].close-prevRates[i+1].close;
double aa=prevAtr[i];
int st=(aa>0.0 && MathAbs(ch)/aa>=GuruThresholdATR ? 1:0);
pПоказано первые 50% кода (символов: 22488)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.