← К каталогу
Исходный код · ID 4398

Double Tap 3D [Neblok]

doubletap3d.mq5

Похожие материалы по тегам

range breakout @meowforex1.pineTradingView · 1 общих тегов#1.mtf_collider_h4_close_13_v18bar.mq4MQL4 / MetaTrader 4 · 1 общих тегов!mth_fasttmaline_edit3.mq4MQL4 / MetaTrader 4 · 1 общих тегов!mth_fasttmaline_edit2.mq4MQL4 / MetaTrader 4 · 1 общих тегов!mth_fasttmaline_edit.mq4MQL4 / MetaTrader 4 · 1 общих теговsmcj, fix.mq5MQL5 / MetaTrader 5 · 1 общих тегов
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Индикатор MetaTrader 5 для обнаружения паттернов «двойная вершина» и «двойная впадина» на ценовом графике. Выполняет расчёт качества каждого найденного паттерна, отображает зоны с эффектом 3D-выпуклости, отслеживает состояние паттернов от формирования до завершения и показывает уровни TP/SL. Включает информационную панель с статистикой по сделкам и поддержку уведомлений (всплывающее окно, push, e-mail).

Настройки программы

НастройкаОписание
Detect Double Tops (InpShowTops) Обнаружение двойных вершин — Включает или отключает поиск паттернов двойной вершины
Detect Double Bottoms (InpShowBots) Обнаружение двойных впадин — Включает или отключает поиск паттернов двойной впадины
Pivot Left Bars (InpPivLeft) Бары слева пивота — Количество баров слева от точки для подтверждения пивота
Pivot Right Bars (confirmation; no repaint) (InpPivRight) Бары справа пивота — Количество баров справа от точки для подтверждения пивота (без перерисовки)
Peak Match Tolerance (x ATR) (InpTolAtr) Допуск совпадения пиков — Допустимое отклонение высоты пиков в кратных ATR
Min Bars Between Peaks (InpMinSpan) Минимум баров между пиками — Минимальное расстояние в барах между двумя пиками паттерна
Max Bars Between Peaks (InpMaxSpan) Максимум баров между пиками — Максимальное расстояние в барах между двумя пиками паттерна
Min Pattern Height (x ATR) (InpMinHeightAtr) Минимальная высота паттерна — Минимальная высота паттерна в кратных ATR
Bars Allowed to Break Neckline (InpExpiryBars) Бары до разрыва линии шеи — Максимальное количество баров, в течение которых допускается разрыв линии шеи
Prior Trend Lookback (InpPriorLook) Откат для предшествующего движения — Глубина отката назад для определения движения перед первым пиком
ATR Length (InpAtrLen) Длина ATR — Период расчёта среднеквадратичного диапазона
Max history bars to scan (performance) (InpMaxBars) Максимум баров для сканирования — Ограничение глубины истории для сканирования (производительность)
Min Quality Score for Signals (0-100) (InpMinScore) Минимальный балл качества — Минимальный балл от 0 до 100 для формирования сигналов
Draw Patterns Below Min Score (InpShowLowQ) Отображение слабых паттернов — Рисовать паттерны с баллом ниже минимального порога
RSI Length (Divergence) (InpRsiLen) Длина RSI — Период расчёта RSI для определения дивергенции
Trend Filter: Signal Only With EMA (InpUseTrend) Фильтр тренда по EMA — Разрешать сигналы только при условии цены относительно EMA
Trend EMA Length (InpEmaLen) Длина EMA фильтра — Период экспоненциальной скользящей средней для фильтра тренда
Require Volume Surge on Break (InpUseVolBrk) Требовать всплеск объёма — Требовать увеличение объёма при пробое линии шеи
Break Volume >= x 20-Bar Avg (InpVolMult) Множитель объёма — Пробной объём должен быть не менее этого множителя от среднего за 20 баров
Stop Buffer Beyond Peaks (x ATR) (InpSlBufAtr) Буфер стопа за пиками — Отступ стопа за линию пиков в кратных ATR
TP1 (x Pattern Height) (InpTp1Mult) Множитель TP1 — Множитель высоты паттерна для первого уровня прибыли
TP2 (x Pattern Height) (InpTp2Mult) Множитель TP2 — Множитель высоты паттерна для второго уровня прибыли
Show TP / SL Lines (InpShowTargets) Отображение TP/SL — Показывать линии уровней Take Profit и Stop Loss
LONG Signals (Double Bottoms) (InpSigLong) Сигналы LONG — Генерировать сигналы на покупку при двойных впадинах
SHORT Signals (Double Tops) (InpSigShort) Сигналы SHORT — Генерировать сигналы на продажу при двойных вершинах
Track Stop at Breakeven After TP1 (InpMoveBE) Безубыток после TP1 — Перемещать стоп в точку входа после достижения TP1
Double Top (InpColTop) Цвет двойной вершины — Цвет линий и зон для паттернов двойной вершины
Double Bottom (InpColBot) Цвет двойной впадины — Цвет линий и зон для паттернов двойной впадины
Success (InpColWin) Цвет успешного исхода — Цвет индикации успешного завершения паттерна
Failed / SL (InpColLoss) Цвет неудачного исхода — Цвет индикации неудачного завершения или срабатывания стопа
Получить полный код

Поиск по коду файла

#property version   "1.00"
#property description "Double Top / Double Bottom detection with quality scoring,"
#property description "measured-move targets, signals, outcome tracking, stats dashboard, 3D zones."
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_label1  "Trend EMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  C'188,19,254'
#property indicator_width1  2

enum ENUM_SZ  { SZ_NORMAL = 0, // Normal
                SZ_LARGE  = 1, // Large
                SZ_HUGE   = 2  // Huge
};
enum ENUM_DPOS { DP_TR = 0, // Top Right
                 DP_TL = 1, // Top Left
                 DP_BR = 2, // Bottom Right
                 DP_BL = 3  // Bottom Left
};

input group "① Detection"
input bool   InpShowTops     = true;   // Detect Double Tops
input bool   InpShowBots     = true;   // Detect Double Bottoms
input int    InpPivLeft      = 8;      // Pivot Left Bars
input int    InpPivRight     = 5;      // Pivot Right Bars (confirmation; no repaint)
input double InpTolAtr       = 0.75;   // Peak Match Tolerance (x ATR)
input int    InpMinSpan      = 10;     // Min Bars Between Peaks
input int    InpMaxSpan      = 150;    // Max Bars Between Peaks
input double InpMinHeightAtr = 1.5;    // Min Pattern Height (x ATR)
input int    InpExpiryBars   = 60;     // Bars Allowed to Break Neckline
input int    InpPriorLook    = 60;     // Prior Trend Lookback
input int    InpAtrLen       = 14;     // ATR Length
input int    InpMaxBars      = 2000;   // Max history bars to scan (performance)

input group "② Quality & Filters"
input int    InpMinScore     = 50;     // Min Quality Score for Signals (0-100)
input bool   InpShowLowQ     = true;   // Draw Patterns Below Min Score
input int    InpRsiLen       = 14;     // RSI Length (Divergence)
input bool   InpUseTrend     = false;  // Trend Filter: Signal Only With EMA
input int    InpEmaLen       = 200;    // Trend EMA Length
input bool   InpUseVolBrk    = false;  // Require Volume Surge on Break
input double InpVolMult      = 1.5;    // Break Volume >= x 20-Bar Avg

input group "③ Targets & Risk"
input double InpSlBufAtr     = 0.25;   // Stop Buffer Beyond Peaks (x ATR)
input double InpTp1Mult      = 1.0;    // TP1 (x Pattern Height)
input double InpTp2Mult      = 1.618;  // TP2 (x Pattern Height)
input bool   InpShowTargets  = true;   // Show TP / SL Lines

input group "④ Signals"
input bool   InpSigLong      = true;   // LONG Signals (Double Bottoms)
input bool   InpSigShort     = true;   // SHORT Signals (Double Tops)
input bool   InpMoveBE       = true;   // Track Stop at Breakeven After TP1

input group "⑤ Visuals"
input color  InpColTop       = C'255,32,121';  // Double Top
input color  InpColBot       = C'0,240,255';   // Double Bottom
input color  InpColWin       = C'57,255,20';   // Success
input color  InpColLoss      = C'255,95,31';   // Failed / SL
input color  InpColTP        = C'255,240,31';  // Targets
input color  InpColNeck      = C'188,19,254';  // Neckline
input bool   InpUse3D        = true;   // 3D Extruded Zones & Shadowed Legs
input int    InpDepthBars    = 4;      // 3D Depth (Bars)
input double InpDepthAtr     = 0.6;    // 3D Depth (x ATR)
input ENUM_SZ InpLblSize     = SZ_LARGE; // Label Size
input int    InpLineW        = 3;      // Pattern Line Width
input int    InpMaxHist      = 5;     // Completed Patterns to Keep
input bool   InpKeepTags     = false;  // Keep TP / SL Tags on Finished Patterns

input group "⑥ Dashboard"
input bool     InpShowDash   = true;   // Show Dashboard
input ENUM_DPOS InpDashPos   = DP_BL;  // Position
input ENUM_SZ  InpDashSize   = SZ_LARGE; // Text Size

input group "⑦ Continuation & Flip Zones (RBS / SBR)"
input bool   InpShowCont     = true;   // Show Bullish / Bearish Continuation tags
input bool   InpShowFlip     = true;   // Show RBS / SBR zones
input int    InpContMaxGap   = 150;    // Continuation: max bars between the two patterns
input int    InpFlipMaxGap   = 200;    // RBS/SBR: max bars from flip to new pattern break
input double InpFlipTolAtr   = 1.0;    // RBS/SBR: new peaks within (x ATR) of old zone
input color  InpColCont      = C'0,200,120';   // Continuation tag color
input color  InpColFlip      = C'255,165,0';   // RBS / SBR zone color

input group "⑧ Alerts"
input bool   InpAlertPopup   = true;   // Popup alert
input bool   InpAlertPush    = false;  // Push notification
input bool   InpAlertMail    = false;  // E-mail

#define PFX            "DT3D_"
#define PIVOT_MEMORY   6

struct Pivot
{
   int    x;
   double p;
   double r;
   double v;
};

struct Pattern
{
   int    id;
   int    dir;          // -1 double top, +1 double bottom
   int    x0;  double p0;
   int    x1;  double p1;
   int    xn;  double neck;
   int    x2;  double p2;
   double height, stop, tp1, tp2, atrV;
   int    score;
   string grade;
   string notes;
   int    state;        // 0 forming, 1 active, 2 success, 3 failed, 5 timed out
   int    xb;  double pb;
   int    xEnd;
   bool   tp1Hit, tp2Hit, signal, beMoved;
   string brkTxt;
   double brkPrice;
   bool   drawn;
   string contTag;      // "BULLISH CONT." / "BEARISH CONT." / ""
   string flipTag;      // "RBS" / "SBR" / ""
   int    zX;           // flip zone start bar
   double zT, zB;       // flip zone top / bottom
};

struct HRec
{
   int    dir;
   int    x1, x2, xb;
   double top, bot;     // peak band of the pattern
   double neck, stop, atrV;
   bool   success;      // broke the neckline and reached at least TP1
   bool   failed;       // stop hit / invalidated
   int    xFail;
   bool   flipped;      // close beyond stop level within FLIP_WINDOW bars of failing
   int    xFlip;
};

#define FLIP_WINDOW 10

Pivot   pHighs[], pLows[];
Pattern live[], done[];
HRec    hist[];
int     stats[12];

int      g_total = 0;
int      g_last  = -1;
int      g_nextId = 0;
string   g_alertMsg = "";
string   g_tf = "";

datetime g_time[];
double   g_high[], g_low[], g_close[], g_vol[];
double   g_tr[], g_atr[], g_gain[], g_loss[], g_ag[], g_al[], g_rsi[], g_ema[], g_volAvg[];

double   EmaBuf[];

template<typename T>
void RemoveAt(T &arr[], const int idx)
{
   int n = ArraySize(arr);
   if(idx < 0 || idx >= n) return;
   for(int k = idx; k < n - 1; k++) arr[k] = arr[k + 1];
   ArrayResize(arr, n - 1);
}

color Mix(const color c, const color bg, const int transp)
{
   int r1 = c & 0xFF,         g1 = (c >> 8) & 0xFF,  b1 = (c >> 16) & 0xFF;
   int r2 = bg & 0xFF,        g2 = (bg >> 8) & 0xFF, b2 = (bg >> 16) & 0xFF;
   int r = (r1 * (100 - transp) + r2 * transp) / 100;
   int g = (g1 * (100 - transp) + g2 * transp) / 100;
   int b = (b1 * (100 - transp) + b2 * transp) / 100;
   return (color)(r | (g << 8) | (b << 16));
}

int FontSz(const ENUM_SZ s)
{
   if(s == SZ_NORMAL) return 9;
   if(s == SZ_HUGE)   return 15;
   return 11;
}

datetime TimeAt(const int idx)
{
   if(idx < g_total) return g_time[MathMax(idx, 0)];
   return g_time[g_total - 1] + (datetime)((idx - g_total + 1) * PeriodSeconds());
}

string Px(const double v) { return DoubleToString(v, _Digits); }

void Bump(const int dir, const int m) { stats[(dir == -1 ? 0 : 6) + m]++; }
int  Stat(const int dir, const int m) { return stats[(dir == -1 ? 0 : 6) + m]; }

void Prep(const string n, const bool back)
{
   ObjectSetInteger(0, n, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, n, OBJPROP_HIDDEN, true);
   ObjectSetInteger(0, n, OBJPROP_BACK, back);
}

void Trend(const string n, const int xa, const double ya, const int xb, const double yb,
           const color c, const int w, const ENUM_LINE_STYLE st)
{
   ObjectCreate(0, n, OBJ_TREND, 0, TimeAt(xa), ya, TimeAt(xb), yb);
   ObjectSetInteger(0, n, OBJPROP_COLOR, c);
   ObjectSetInteger(0, n, OBJPROP_WIDTH, st == STYLE_SOLID ? w : 1); // MT5 only draws styles at width 1
   ObjectSetInteger(0, n, OBJPROP_STYLE, st);
   ObjectSetInteger(0, n, OBJPROP_RAY_RIGHT, false);
   ObjectSetInteger(0, n, OBJPROP_RAY_LEFT, false);
   Prep(n, false);
}

void Rect(const string n, const int xa, const double ya, const int xb, const double yb,
          const color c, const bool fill, const int w)
{
   ObjectCreate(0, n, OBJ_RECTANGLE, 0, TimeAt(xa), ya, TimeAt(xb), yb);
   ObjectSetInteger(0, n, OBJPROP_COLOR, c);
   ObjectSetInteger(0, n, OBJPROP_FILL, fill);
   ObjectSetInteger(0, n, OBJPROP_WIDTH, w);
   Prep(n, fill);
}

void Tri(const string n, const int x1, const double y1, const int x2, const double y2,
         const int x3, const double y3, const color c)
{
   ObjectCreate(0, n, OBJ_TRIANGLE, 0, TimeAt(x1), y1, TimeAt(x2), y2, TimeAt(x3), y3);
   ObjectSetInteger(0, n, OBJPROP_COLOR, c);
   ObjectSetInteger(0, n, OBJPROP_FILL, true);
   Prep(n, true);
}

void Txt(const string n, const int x, const double y, const string t, const color c,
         const int fs, const ENUM_ANCHOR_POINT a, const string tip = "")
{
   ObjectCreate(0, n, OBJ_TEXT, 0, TimeAt(x), y);
   ObjectSetString(0, n, OBJPROP_TEXT, t);
   ObjectSetString(0, n, OBJPROP_FONT, "Arial Bold");
   ObjectSetInteger(0, n, OBJPROP_FONTSIZE, fs);
   ObjectSetInteger(0, n, OBJPROP_COLOR, c);
   ObjectSetInteger(0, n, OBJPROP_ANCHOR, a);
   if(tip != "") ObjectSetString(0, n, OBJPROP_TOOLTIP, tip);
   Prep(n, false);
}

void Compute(const int from, const int n)
{
   for(int i = from; i < n; i++)
   {

      double tr = (i == 0) ? g_high[0] - g_low[0]
                           : MathMax(g_high[i] - g_low[i],
                                     MathMax(MathAbs(g_high[i] - g_close[i - 1]),
                                             MathAbs(g_low[i]  - g_close[i - 1])));
      g_tr[i] = tr;
      if(i < InpAtrLen - 1) g_atr[i] = 0.0;
      else if(i == InpAtrLen - 1)
      {
         double s = 0; for(int k = 0; k <= i; k++) s += g_tr[k];
         g_atr[i] = s / InpAtrLen;
      }
      else g_atr[i] = (g_atr[i - 1] * (InpAtrLen - 1) + tr) / InpAtrLen;

      if(i == 0) { g_gain[0] = 0; g_loss[0] = 0; }
      else
      {
         double ch = g_close[i] - g_close[i - 1];
         g_gain[i] = MathMax(ch, 0.0);
         g_loss[i] = MathMax(-ch, 0.0);
      }
      if(i < InpRsiLen) { g_ag[i] = 0; g_al[i] = 0; g_rsi[i] = 50.0; }
      else
      {
         if(i == InpRsiLen)
         {
            double sg = 0, sl = 0;
            for(int k = 1; k <= InpRsiLen; k++) { sg += g_gain[k]; sl += g_loss[k]; }
            g_ag[i] = sg / InpRsiLen; g_al[i] = sl / InpRsiLen;
         }
         else
         {
            g_ag[i] = (g_ag[i - 1] * (InpRsiLen - 1) + g_gain[i]) / InpRsiLen;
            g_al[i] = (g_al[i - 1] * (InpRsiLen - 1) + g_loss[i]) / InpRsiLen;
         }
         if(g_al[i] == 0)      g_rsi[i] = 100.0;
         else if(g_ag[i] == 0) g_rsi[i] = 0.0;
         else                  g_rsi[i] = 100.0 - 100.0 / (1.0 + g_ag[i] / g_al[i]);
      }

      if(i < InpEmaLen - 1) g_ema[i] = 0.0;
      else if(i == InpEmaLen - 1)
      {
         double s = 0; for(int k = 0; k <= i; k++) s += g_close[k];
         g_ema[i] = s / InpEmaLen;
      }
      else
      {
         double a = 2.0 / (InpEmaLen + 1.0);
         g_ema[i] = g_ema[i - 1] + a * (g_close[i] - g_ema[i - 1]);
      }

      if(i < 19) g_volAvg[i] = 0.0;
      else { double s = 0; for(int k = i - 19; k <= i; k++) s += g_vol[k]; g_volAvg[i] = s / 20.0; }
   }
}

bool PivHigh(const int cur, double &val)
{
   int p = cur - InpPivRight;
   if(p - InpPivLeft < 0) return false;
   double v = g_high[p];
   for(int k = 1; k <= InpPivLeft;  k++) if(g_high[p - k] > v)  return false;
   for(int k = 1; k <= InpPivRight; k++) if(g_high[p + k] >= v) return false;
   val = v; return true;
}

bool PivLow(const int cur, double &val)
{
   int p = cur - InpPivRight;
   if(p - InpPivLeft < 0) return false;
   double v = g_low[p];
   for(int k = 1; k <= InpPivLeft;  k++) if(g_low[p - k] < v)  return false;
   for(int k = 1; k <= InpPivRight; k++) if(g_low[p + k] <= v) return false;
   val = v; return true;
}

int Score(const int dir, Pivot &a, Pivot &b, const int xn, const double h,
          const double priorMove, const double atrV, string &notes)
{
   double matchPct = MathMax(0.0, 1.0 - MathAbs(b.p - a.p) / (InpTolAtr * atrV));
   bool   rsiDiv   = (dir == -1) ? (b.r < a.r) : (b.r > a.r);
   bool   volKnown = (a.v > 0 && b.v > 0);
   bool   volDiv   = volKnown && (b.v < a.v);
   double l1  = xn - a.x;
   double l2  = b.x - xn;
   double sym = MathMin(l1, l2) / MathMax(MathMax(l1, l2), 1.0);
   double trendRatio = MathMin(1.0, priorMove / MathMax(h, _Point));

   double s1 = 25.0 * matchPct;
   double s2 = rsiDiv ? 20.0 : 0.0;
   double s3 = volKnown ? (volDiv ? 15.0 : 0.0) : 7.5;
   double s4 = 15.0 * MathMin(1.0, h / (3.0 * atrV));
   double s5 = 10.0 * sym;
   double s6 = 15.0 * trendRatio;
   int score = (int)MathRound(s1 + s2 + s3 + s4 + s5 + s6);

   notes  = "Peak match: " + DoubleToString(matchPct * 100, 0) + "%";
   notes += "\nRSI divergence: " + (rsiDiv ? "YES" : "no");
   notes += "\nVolume divergence: " + (volKnown ? (volDiv ? "YES" : "no") : "n/a");
   notes += "\nHeight: " + DoubleToString(h / atrV, 1) + " x ATR";
   notes += "\nSymmetry: " + DoubleToString(sym * 100, 0) + "%";
   notes += "\nPrior trend: " + DoubleToString(trendRatio * 100, 0) + "% of height";
   return score;
}

bool Detect(const int dir, Pivot &b, Pivot &piv[], const int cur, Pattern &res)
{
   int    n   = ArraySize(piv);
   double atr = g_atr[cur];
   if(n <= 0 || atr <= 0) return false;

   for(int k = n - 1; k >= 0; k--)
   {
      Pivot a = piv[k];
      int span = b.x - a.x;
      if(span > InpMaxSpan) break;
      if(span >= InpMinSpan && MathAbs(b.p - a.p) <= InpTolAtr * atr)
      {
         double neck = 0, rim = 0;
         bool haveNeck = false, haveRim = false;
         int  xn = a.x + 1;
         for(int x = b.x - 1; x >= a.x + 1; x--)
         {
            if(dir == -1)
            {
               if(!haveNeck || g_low[x] < neck) { neck = g_low[x]; xn = x; haveNeck = true; }
               rim = haveRim ? MathMax(rim, g_high[x]) : g_high[x];
            }
            else
            {
               if(!haveNeck || g_high[x] > neck) { neck = g_high[x]; xn = x; haveNeck = true; }
               rim = haveRim ? MathMin(rim, g_low[x]) : g_low[x];
            }
            haveRim = true;
         }
         if(!haveNeck) continue;

         double ext   = (dir == -1) ? MathMax(a.p, b.p) : MathMin(a.p, b.p);
         bool   clean = (dir == -1) ? (rim <= ext) : (rim >= ext);
         if(!clean) break;   // a higher high / lower low sits between: older pivots can't qualify

         double h = MathAbs(ext - neck);
         if(h >= InpMinHeightAtr * atr)
         {

            double pr = 0; bool havePr = false; int xp = a.x;
            int endX = MathMax(a.x - InpPriorLook, 0);
            for(int x = a.x - 1; x >= endX; x--)
            {
               if(dir == -1) { if(!havePr || g_low[x]  < pr) { pr = g_low[x];  xp = x; havePr = true; } }
               else          { if(!havePr || g_high[x] > pr) { pr = g_high[x]; xp = x; havePr = true; } }
            }
            double p0 = havePr ? pr : a.p;
            double priorMove = (dir == -1) ? MathMax(0.0, a.p - p0) : MathMax(0.0, p0 - a.p);

            string notes;
            int sc = Score(dir, a, b, xn, h, priorMove, atr, notes);

            res.id = 0; res.dir = dir;
            res.x0 = xp; res.p0 = p0;
            res.x1 = a.x; res.p1 = a.p;
            res.xn = xn; res.neck = neck;
            res.x2 = b.x; res.p2 = b.p;
            res.height = h;
            res.stop = (dir == -1) ? ext + InpSlBufAtr * atr : ext - InpSlBufAtr * atr;
            res.tp1  = (dir == -1) ? neck - h * InpTp1Mult   : neck + h * InpTp1Mult;
            res.tp2  = (dir == -1) ? neck - h * InpTp2Mult   : neck + h * InpTp2Mult;
            res.atrV = atr;
            res.score = sc;
            res.grade = sc >= 75 ? "A" : sc >= 55 ? "B" : "C";
            res.notes = notes;
            res.state = 0;
            res.xb = 0; res.pb = 0;
            res.xEnd = cur;
            res.tp1Hit = false; res.tp2Hit = false; res.signal = false; res.beMoved = false;
            res.brkTxt = ""; res.brkPrice = 0;
            res.drawn = false;
            res.contTag = ""; res.flipTag = "";
            res.zX = 0; res.zT = 0; res.zB = 0;
            return true;
         }
      }
   }
   return false;
}

color ColorOf(const Pattern &pt)
{
   if(pt.state == 2) return InpColWin;
   if(pt.state == 3) return InpColLoss;
   return pt.dir == -1 ? InpColTop : InpColBot;
}

void Zone(const Pattern &pt, double &top, double &bot)
{
   top = MathMax(pt.p1, pt.p2);
   bot = MathMin(pt.p1, pt.p2);
   double minT = 0.2 * pt.atrV;
   if(top - bot < minT)
   {
      if(pt.dir == -1) bot = top - minT;
      else             top = bot + minT;
   }
}

string StatusText(const Pattern &pt)
{
   string name = pt.dir == -1 ? "DOUBLE TOP" : "DOUBLE BOTTOM";
   string st;
   switch(pt.state)
   {
      case 0:  st = "FORMING"; break;
      case 1:  st = pt.tp1Hit ? "TP1 HIT" : "ACTIVE"; break;
      case 2:  st = pt.tp2Hit ? "TP2 HIT" : "SUCCESS"; break;
      case 3:  st = "FAILED"; break;
      default: st = "TIMED OUT";
   }
   return name + " | " + st + " | Grade " + pt.grade + " " + IntegerToString(pt.score) + "/100";
}

void DrawLeg(const string pre, const string key, const int xa, const double ya, const int xb,
             const double yb, const color c, const color bg, const double atrV)
{
   if(InpUse3D)
   {
      double sh = 0.18 * atrV;
      Trend(pre + "S" + key, xa + 1, ya - sh, xb + 1, yb - sh, Mix(c, bg, 72), InpLineW, STYLE_SOLID);
   }
   Trend(pre + "L" + key, xa, ya, xb, yb, c, InpLineW, STYLE_SOLID);
}

void DeleteObjs(const int id)
{
   ObjectsDeleteAll(0, PFX + IntegerToString(id) + "_");
}

void DrawPattern(Pattern &pt)
{
   string pre = PFX + IntegerToString(pt.id) + "_";
   ObjectsDeleteAll(0, pre);

   color bg = (color)ChartGetInteger(0, CHART_COLOR_BACKGROUND);
   color c  = ColorOf(pt);
   int   fs = FontSz(InpLblSize);
   double top, bot; Zone(pt, top, bot);

   DrawLeg(pre, "1", pt.x0, pt.p0,   pt.x1, pt.p1,   c, bg, pt.atrV);
   DrawLeg(pre, "2", pt.x1, pt.p1,   pt.xn, pt.neck, c, bg, pt.atrV);
   DrawLeg(pre, "3", pt.xn, pt.neck, pt.x2, pt.p2,   c, bg, pt.atrV);
   if(pt.state >= 1) DrawLeg(pre, "4", pt.x2, pt.p2, pt.xb, pt.pb, c, bg, pt.atrV);

   Tr

Показано первые 50% кода (символов: 25665)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
2 566,50₽ ≈ $31.37