OGT Zone Recovery v1.5
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «ogt zone recovery ea v1.5@amazing_owner.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
OGT Zone Recovery v1.5 — торговый советник для MetaTrader 4, использующий анализ RSI на множестве таймфреймов для генерации сигналов входа в сделку. Советник реализует механизм «зонного восстановления»: после открытия начальной рыночной позиции размещается противоположный отложенный ордер в зоне восстановления. При срабатывании восстановления размер лота увеличивается и открывается новый противоположный отложенный ордер.
В качестве альтернативы фиксированным значениям доступна динамическая оценка зон и уровней тейк-профита на основе индикатора ATR. Встроена система управления рисками с возможностью расчёта размера позиции от процента риска на депозит или использования фиксированного лота с множителем и дополнениями. Предусмотрены 10 наборов пользовательских размеров лотов.
Советник поддерживает ежедневный торговый таймер с настройкой времени начала и окончания в серверном или локальном времени. Встроена визуальная торговая панель с кнопками управления и полями ввода параметров. Доступна фильтрация ордеров по магическому числу, ограничение максимального количества сделок и максимального убытка, а также симуляция комиссии при бэктестировании.
Настройки программы
| Настройка | Описание |
|---|---|
| ZONE RECOVERY SETTINGS ** (RecoverySettings) | ZONE RECOVERY SETTINGS — Заголовок группы настроек зонного восстановления. |
| Recovery Zone Size (points) (__RecoveryZoneSize__) | Recovery Zone Size (points) — Размер зоны восстановления в пунктах. |
| Take Profit (points) (__TakeProfit__) | Take Profit (points) — Тейк-профит начальной позиции в пунктах. |
| Max Trades (0 for unlimited) (MaxTrades) | Max Trades — Максимальное количество одновременных сделок (0 — без ограничений). |
| Max Loss after Max Trades reached? (SetMaxLoss) | Max Loss after Max Trades reached? — Включает ограничение убытка после достижения максимального количества сделок. |
| Max Loss after Max Trades (0 for unlimted) in deposit currency. (MaxLoss) | Max Loss after Max Trades — Максимальный убыток в валюте депозита, при достижении которого позиции закрываются. |
| Use a Recovery Take Profit (UseRecoveryTakeProfit) | Use a Recovery Take Profit — Включает отдельный тейк-профит для зоны восстановления. |
| Recovery Take Profit (points). (RecoveryTakeProfit) | Recovery Take Profit (points) — Размер тейк-профита для зоны восстановления в пунктах. |
| Price for pending orders (__PendingPrice__) | Price for pending orders — Цена для размещения отложенных ордеров. |
| ATR Dynamic Zone Sizing ** (ATRHeader) | ATR Dynamic Zone Sizing — Заголовок группы настроек динамической оценки зон через ATR. |
| Use ATR? (UseATR) | Use ATR? — Включает использование индикатора ATR для динамической оценки зон и тейк-профитов. |
| ATR Period (ATRPeriod) | ATR Period — Период индикатора ATR для расчёта волатильности. |
| Fraction of ATR to use as Recovery Zone (ATRZoneFraction) | Fraction of ATR to use as Recovery Zone — Доля ATR, используемая для определения размера зоны восстановления. |
| Fraction or ATR to use for TP sizes (ATRTPFraction) | Fraction of ATR to use for TP sizes — Доля ATR, используемая для расчёта размера тейк-профита. |
| Fraction of ATR to use for recovery TP. (ATRRecoveryZone) | Fraction of ATR to use for recovery TP — Доля ATR, используемая для определения размера зоны восстановления. |
| MONEY MANAGEMENT SETTINGS ** (MoneyManagement) | MONEY MANAGEMENT SETTINGS — Заголовок группы настроек управления рисками и размера лота. |
| Account % Initial Lot Size (set to 0 if not used) (RiskPercent) | Account % Initial Lot Size — Процент риска от депозита для расчёта размера лота (0 — не используется). |
| Initial Lot Size (if % not used) (InitialLotSize) | Initial Lot Size — Начальный размер лота при отсутствии процентного риска. |
| Multiplier for Lots (LotMultiplier) | Multiplier for Lots — Множитель для увеличения размера лота при каждом последующем шаге. |
| LotAdditions | Lot Additions — Дополнительное значение, добавляемое к расчёту размера лота. |
| CUSTOM LOT SIZES ** (CustomLotSizing) | CUSTOM LOT SIZING — Заголовок группы пользовательских размеров лотов. |
| CustomLotSize1 | Custom Lot Size 1 — Пользовательский размер лота для первой сделки. |
| CustomLotSize2 | Custom Lot Size 2 — Пользовательский размер лота для второй сделки. |
| CustomLotSize3 | Custom Lot Size 3 — Пользовательский размер лота для третьей сделки. |
| CustomLotSize4 | Custom Lot Size 4 — Пользовательский размер лота для четвёртой сделки. |
| CustomLotSize5 | Custom Lot Size 5 — Пользовательский размер лота для пятой сделки. |
| CustomLotSize6 | Custom Lot Size 6 — Пользовательский размер лота для шестой сделки. |
| CustomLotSize7 | Custom Lot Size 7 — Пользовательский размер лота для седьмой сделки. |
| CustomLotSize8 | Custom Lot Size 8 — Пользовательский размер лота для восьмой сделки. |
| CustomLotSize9 | Custom Lot Size 9 — Пользовательский размер лота для девятой сделки. |
| CustomLotSize10 | Custom Lot Size 10 — Пользовательский размер лота для десятой сделки. |
| TIMER SETTINGS ** (TimerSettings) | TIMER SETTINGS — Заголовок группы настроек торгового таймера. |
| Use a Trade Timer? (UseTimer) | Use a Trade Timer? — Включает ежедневный торговый таймер. |
| Start Hour (StartHour) | Start Hour — Час начала торгового окна. |
| Start Minute (StartMinute) | Start Minute — Минута начала торгового окна. |
| End Hour (EndHour) | End Hour — Час окончания торгового окна. |
| End Minute (EndMinute) | End Minute — Минута окончания торгового окна. |
| Use local time? (UseLocalTime) | Use local time? — Использование локального времени вместо серверного для торгового таймера. |
| EA SETTINGS ** (TradeSettings) | EA SETTINGS — Заголовок группы основных настроек советника. |
| EA_Mode | EA Mode — Режим работы советника: ручной или сигналы RSI на множестве таймфреймов. |
| RSI Period (RSIPeriod) | RSI Period — Период индикатора RSI для расчёта сигналов. |
| Over-bought level (OverboughtLevel) | Over-bought level — Уровень перекупленности RSI для формирования сигнала на продажу. |
| Over-sold level (OversoldLevel) | Over-sold level — Уровень перепроданности RSI для формирования сигнала на покупку. |
| Use M1 Timeframe? (UseM1Timeframe) | Use M1 Timeframe? — Включает использование таймфрейма M1 для анализа RSI. |
| Use M5 Timeframe? (UseM5Timeframe) | Use M5 Timeframe? — Включает использование таймфрейма M5 для анализа RSI. |
| Use M15 Timeframe? (UseM15Timeframe) | Use M15 Timeframe? — Включает использование таймфрейма M15 для анализа RSI. |
| Use M30 Timeframe? (UseM30Timeframe) | Use M30 Timeframe? — Включает использование таймфрейма M30 для анализа RSI. |
| Use H1 Timeframe? (UseH1Timeframe) | Use H1 Timeframe? — Включает использование таймфрейма H1 для анализа RSI. |
| Use H4 Timeframe? (UseH4Timeframe) | Use H4 Timeframe? — Включает использование таймфрейма H4 для анализа RSI. |
| Use Daily Timeframe? (UseDailyTimeframe) | Use Daily Timeframe? — Включает использование таймфрейма D1 для анализа RSI. |
| Use Weekly Timeframe? (UseWeeklyTimeframe) | Use Weekly Timeframe? — Включает использование таймфрейма W1 для анализа RSI. |
| Use Monthly Timeframe? (UseMonthlyTimeframe) | Use Monthly Timeframe? — Включает использование таймфрейма MN1 для анализа RSI. |
| VISUALS ** (Visuals) | VISUALS — Заголовок группы визуальных настроек. |
| profitLineColor | Profit Line Color — Цвет линии уровня прибыли на графике. |
| Panel X coordinate. (Panel_X) | Panel X coordinate — Горизонтальная позиция торговой панели на графике. |
| Panel Y coordinate. (Panel_Y) | Panel Y coordinate — Вертикальная позиция торговой панели на графике. |
| Panel background colour. (Panel_Color) | Panel background colour — Цвет фона торговой панели. |
| Panel lable text color. (Panel_Lable_Color) | Panel label text color — Цвет текста меток на торговой панели. |
| OTHER SETTINGS ** (BacktestingSettings) | OTHER SETTINGS — Заголовок группы настроек бэктестирования. |
| Magic Number (MagicNumber) | Magic Number — Магический номер для идентификации ордеров советника. |
| Slippage Max (Points). (Slippage) | Slippage Max (Points) — Максимально допустимое проскальзывание в пунктах. |
| Trade on New Bar? (TradeOnBarOpen) | Trade on New Bar? — Открытие сделок только при появлении нового бара. |
| Back tester speed (speed) | Back tester speed — Скорость прохождения бэктеста. |
| Back tester simulated commission (TestCommission) | Back tester simulated commission — Симулированная комиссия для расчётов при бэктестировании. |
Поиск по коду файла
#define MODE_TICKVALUE 16
#define MODE_TICKSIZE 17
#define SELECT_BY_POS 0
#define OP_BUY 0
#define MODE_SPREAD 13
#define OP_SELL 1
#define MODE_ASK 10
#define SELECT_BY_TICKET 1
#define OP_BUYSTOP 4
#define MODE_BID 9
#define OP_SELLSTOP 5
#define OP_BUYLIMIT 2
#define OP_SELLLIMIT 3
#define MODE_DIGITS 12
#define ERR_BROKER_BUSY 137
#define ERR_COMMON_ERROR 2
#define ERR_NO_ERROR 0
#define ERR_NO_CONNECTION 6
#define ERR_NO_RESULT 1
#define ERR_SERVER_BUSY 4
#define ERR_NOT_ENOUGH_RIGHTS 7
#define ERR_MALFUNCTIONAL_TRADE 9
#define ERR_TRADE_CONTEXT_BUSY 146
#define ERR_TRADE_TIMEOUT 128
#define ERR_REQUOTE 138
#define ERR_TOO_MANY_REQUESTS 141
#define ERR_OFF_QUOTES 136
#define ERR_PRICE_CHANGED 135
#define ERR_TOO_FREQUENT_REQUESTS 8
#property description "Coded by: A Sweeney"
#property strict
enum EA_Setting {Manual, RSI_MTF};
enum CLOSE_PENDING_TYPE
{
CLOSE_BUY_LIMIT,
CLOSE_SELL_LIMIT,
CLOSE_BUY_STOP,
CLOSE_SELL_STOP,
CLOSE_ALL_PENDING
};
input string RecoverySettings; // ** ZONE RECOVERY SETTINGS **
input int __RecoveryZoneSize__ = 200; // Recovery Zone Size (points)
int RecoveryZoneSize = __RecoveryZoneSize__;
input int __TakeProfit__ = 200; // Take Profit (points)
int TakeProfit = __TakeProfit__;
input int MaxTrades = 0; // Max Trades (0 for unlimited)
input bool SetMaxLoss = false; // Max Loss after Max Trades reached?
input double MaxLoss = 0; // Max Loss after Max Trades (0 for unlimted) in deposit currency.
input bool UseRecoveryTakeProfit = true; // Use a Recovery Take Profit
input int RecoveryTakeProfit = 50; // Recovery Take Profit (points).
input double __PendingPrice__ = 0; // Price for pending orders
double PendingPrice = __PendingPrice__;
sinput string ATRHeader; // ** ATR Dynamic Zone Sizing **
input bool UseATR = false; // Use ATR?
input int ATRPeriod = 14; // ATR Period
input double ATRZoneFraction = 0.2; // Fraction of ATR to use as Recovery Zone
input double ATRTPFraction = 0.3; // Fraction or ATR to use for TP sizes
input double ATRRecoveryZone = 0.15; // Fraction of ATR to use for recovery TP.
sinput string MoneyManagement; // ** MONEY MANAGEMENT SETTINGS **
input double RiskPercent = 0; // Account % Initial Lot Size (set to 0 if not used)
input double InitialLotSize = 0.1; // Initial Lot Size (if % not used)
input double LotMultiplier = 2; // Multiplier for Lots
input double LotAdditions = 0;
sinput string CustomLotSizing; // ** CUSTOM LOT SIZES **
input double CustomLotSize1 = 0;
input double CustomLotSize2 = 0;
input double CustomLotSize3 = 0;
input double CustomLotSize4 = 0;
input double CustomLotSize5 = 0;
input double CustomLotSize6 = 0;
input double CustomLotSize7 = 0;
input double CustomLotSize8 = 0;
input double CustomLotSize9 = 0;
input double CustomLotSize10 = 0;
sinput string TimerSettings; // ** TIMER SETTINGS **
input bool UseTimer = false; // Use a Trade Timer?
input int StartHour = 0; // Start Hour
input int StartMinute = 0; // Start Minute
input int EndHour = 0; // End Hour
input int EndMinute = 0; // End Minute
input bool UseLocalTime = false; // Use local time?
sinput string TradeSettings; // ** EA SETTINGS **
input EA_Setting EA_Mode= Manual;
input int RSIPeriod = 14; // RSI Period
input double OverboughtLevel = 70; //Over-bought level
input double OversoldLevel = 30; // Over-sold level
input bool UseM1Timeframe = false; // Use M1 Timeframe?
input bool UseM5Timeframe = false; // Use M5 Timeframe?
input bool UseM15Timeframe = true; // Use M15 Timeframe?
input bool UseM30Timeframe = true; // Use M30 Timeframe?
input bool UseH1Timeframe = false; // Use H1 Timeframe?
input bool UseH4Timeframe = false; // Use H4 Timeframe?
input bool UseDailyTimeframe = false; // Use Daily Timeframe?
input bool UseWeeklyTimeframe = false; // Use Weekly Timeframe?
input bool UseMonthlyTimeframe = false; // Use Monthly Timeframe?
sinput string Visuals; // ** VISUALS **
input color profitLineColor = clrLightSeaGreen;
input int Panel_X = 40; // Panel X coordinate.
input int Panel_Y = 40; // Panel Y coordinate.
input color Panel_Color = clrBlack; // Panel background colour.
input color Panel_Lable_Color = clrWhite; // Panel lable text color.
sinput string BacktestingSettings; // ** OTHER SETTINGS **
input int MagicNumber = 141020; // Magic Number
input int Slippage = 100; // Slippage Max (Points).
input bool TradeOnBarOpen = true; // Trade on New Bar?
input int speed = 500; // Back tester speed
input double TestCommission = 7; // Back tester simulated commission
#define EA_NAME "OGT Zone Recovery v1.5"
#define SELL_BUTTON "Sell Button"
#define BUY_BUTTON "Buy Button"
#define PENDING_EDIT "Pending Edit"
#define CLOSE_ALL_BUTTON "Close All Button"
#define TP_EDIT "TP Edit"
#define ZONE_EDIT "Zone Edit"
string gTradingPanelObjects[100];
#define PROFIT_LINE "Profit Line"
datetime gLastTime;
int gInitialTicket;
double gBuyOpenPrice;
double gSellOpenPrice;
double gBuyTakeProfit;
double gSellTakeProfit;
double gLotSize;
double gInitialLotSize;
double gInitialProfitTarget;
bool gRecoveryInitiated;
int gBuyStopTicket = 0;
int gSellStopTicket = 0;
int gBuyTicket = 0;
int gSellTicket = 0;
double gCustomLotSizes[10];
double UsePip;
double UseSlippage;
double gCurrentDirection;
void OnInit()
{
// код доступен только после оплаты
}
void OnDeinit(const int reason)
{
switch(reason)
{
case 0:
{
DeleteTradePanel();
Print("EA De-Initialised, removed by EA");
break;
}
case 1:
{
DeleteTradePanel();
Print("EA De-Initialised, removed by user");
break;
}
case 2:
{
DeleteTradePanel();
Print("EA De-Initialised, EA recompiled");
break;
}
case 3:
{
DeleteTradePanel();
Print("EA De-Initialised, Symbol changed");
break;
}
case 4:
{
DeleteTradePanel();
Print("EA De-Initialised, chart closed by user.");
break;
}
case 5:
{
Print("EA De-Initialised, input parameters changed.");
break;
}
case 6:
{
Print("EA De-Initialised, account changed");
break;
}
case 7:
{
DeleteTradePanel();
Print("EA De-Initialised, A new template has been applied.");
break;
}
case 8:
{
DeleteTradePanel();
Print("EA De-Initialised, EA failed to initialize.");
break;
}
case 9:
{
DeleteTradePanel();
Print("EA De-Initialised, Terminal closed by user.");
break;
}
}
}
void __OnTick__()
{
if(CCBC::IsVisualMode() == true)
{
int Waitloop = 0;
while(Waitloop < speed)
{
Waitloop++;
}
}
bool tradeEnabled = true;
if(UseTimer == true)
{
tradeEnabled = CheckDailyTimer();
}
bool newBar = true;
int barShift = 0;
if(TradeOnBarOpen == true)
{
newBar = false;
datetime time[];
bool firstRun = false;
CCBC::CopyTime(_Symbol,PERIOD_CURRENT,0,2,time);
if(gLastTime == 0) firstRun = true;
if(time[0] > gLastTime)
{
if(firstRun == false) newBar = true;
gLastTime = time[0];
}
barShift = 1;
}
gInitialLotSize = CheckVolume(_Symbol, InitialLotSize); // check the input value for lot initial lot size and set to initial
if(RiskPercent != 0)
{
int StopLoss = TakeProfit;
if(UseATR == true)
{
double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
StopLoss = round((atr*ATRTPFraction)/_Point); // set the stop loss a fraction of atr in points
}
gInitialLotSize = GetTradeSize(_Symbol,InitialLotSize,RiskPercent,StopLoss);
}
if(newBar == true && tradeEnabled == true) // check for new bar and whether timer allows to open
{
switch(EA_Mode)
{
case RSI_MTF:
{
int direction = Is_RSI_OBOS_on_MTF(barShift + 1);
int nowfalse = Is_RSI_OBOS_on_MTF(barShift);
if(direction == 1 && nowfalse == 0)
{
Print("Buy signal generated.");
if(gCurrentDirection == 0)
{
TakeTrade(direction);
Print("Buy signal generated.");
} else {
Print("Buy signal not used as EA in trade on ", _Symbol);
}
}
else if(direction == -1 && nowfalse == 0)
{
if(gCurrentDirection == 0)
{
TakeTrade(direction);
Print("Sell signal generated.");
} else {
Print("Sell signal not used as EA in trade on ", _Symbol);
}
}
}
}
}
if(gCurrentDirection != 0)
{
int positions = 0;
double averagePrice = 0;
double currentProfit = 0;
double positionSize = 0;
double netLotSize = 0;
double totalCommision = 0;
double totalSpreadCosts = 0;
double point_value = _Point*CCBC::MarketInfo(_Symbol, MODE_TICKVALUE)/CCBC::MarketInfo(_Symbol, MODE_TICKSIZE);
for(int counter = 0; counter <= CCBC::OrdersTotal() - 1; counter++)
{
if(CCBC::OrderSelect(counter, SELECT_BY_POS))
{
if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == Symbol())
{
positions += 1;
currentProfit += CCBC::OrderProfit();
if(CCBC::OrderType() == OP_BUY)
{
positionSize += (CCBC::OrderOpenPrice()*CCBC::OrderLots());
netLotSize += CCBC::OrderLots();
totalSpreadCosts += (CCBC::OrderLots()*CCBC::MarketInfo(_Symbol, MODE_SPREAD)*point_value);
totalCommision += CCBC::OrderCommission();
}
else if(CCBC::OrderType() == OP_SELL)
{
positionSize -= (CCBC::OrderOpenPrice()*CCBC::OrderLots());
netLotSize -= CCBC::OrderLots();
totalSpreadCosts += (CCBC::OrderLots()*CCBC::MarketInfo(_Symbol, MODE_SPREAD)*point_value);
totalCommision += CCBC::OrderCommission();
}
}
}
}
double volume;
if(CustomLotSize1 != 0) volume = CustomLotSize1;
else volume = gInitialLotSize;
double profitTarget = RecoveryTakeProfit*point_value*volume;
if(UseATR == true)
{
double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
profitTarget = (ATRRecoveryZone*atr*point_value*volume)/_Point;
}
double tradeCosts = 0;
if(CCBC::IsTesting())
{
tradeCosts = totalSpreadCosts+(MathAbs(netLotSize)*TestCommission);
} else {
tradeCosts = totalSpreadCosts+totalCommision; // spread and commision
}
double tp = RecoveryTakeProfit;
if(UseRecoveryTakeProfit == false || gRecoveryInitiated == false)
{
profitTarget = TakeProfit*point_value*volume; // initial profit is equal to planned rz over tp, in $$
}
if(currentProfit >= (profitTarget +tradeCosts))
{
CloseOrdersAndReset();
Print("Orders closed, profit target of: ", CCBC::DoubleToStr(profitTarget, 2), "$ exceeded at: ", CCBC::DoubleToStr(currentProfit, 2), "$, Costs(", CCBC::DoubleToStr(tradeCosts, 2), "$)");
}
if(netLotSize != 0)
{
averagePrice = NormalizeDouble(positionSize/netLotSize, _Digits);
Comment(CCBC::StringConcatenate("Average Price: ", CCBC::DoubleToStr(averagePrice, _Digits), ", Profit Target: $", CCBC::DoubleToStr(profitTarget, 2), " + Trade Costs: $", CCBC::DoubleToStr(tradeCosts, 2), ", Running Profit: $", CCBC::DoubleToStr(currentProfit, 2)));
}
if(positions >= MaxTrades && MaxTrades != 0 && currentProfit < -MaxLoss && SetMaxLoss == true)
{
CloseOrdersAndReset();
Print("Orders closed, max trades reached and max loss of: -$", MaxLoss, " by $", currentProfit);
}
if(gCurrentDirection == 1 && netLotSize != 0)
{
tp = (profitTarget + tradeCosts - currentProfit)*_Point/(point_value*netLotSize);
double profitPrice = NormalizeDouble(Bid + tp, _Digits);
if(!CCBC::ObjectSetDouble(0, PROFIT_LINE, OBJPROP_PRICE, profitPrice)) Print("Could not set line");
} else if(gCurrentDirection == -1 && netLotSize != 0) {
tp = (profitTarget + tradeCosts - currentProfit)*_Point/(point_value*netLotSize);
double profitPrice = NormalizeDouble(Ask + tp, _Digits);
if(!CCBC::ObjectSetDouble(0, PROFIT_LINE, OBJPROP_PRICE, profitPrice)) Print("Could not set line");
}
if(gCurrentDirection == 1)
{
double price = CCBC::MarketInfo(Symbol(), MODE_ASK);
if(CCBC::OrderSelect(gSellStopTicket, SELECT_BY_TICKET))
{
if(CCBC::OrderType() == OP_SELL) // if the sell stop has opened
{
Print("Recovery Sell Stop has been opened, initiating recovery...");
gSellTicket = gSellStopTicket; // make the stop a sell ticket
gSellStopTicket = 0; // reset the sell stop ticket
gLotSize = GetTradeVolume(positions+1);
if(MaxTrades == 0 || positions < MaxTrades) // check we've not exceeded the max trades
{
gBuyStopTicket = OpenPendingOrder(Symbol(), OP_BUYSTOP, gLotSize, gBuyOpenPrice, 0, 0, CCBC::StringConcatenate("Recovery Buy Stop opened."), 0, clrTurquoise); // create an opposite buy stop
gRecoveryInitiated = true; // signal that we are in recovery mode
}
gCurrentDirection = -1;
}
} else {
string message = "Warning - EA could not find the recovery Sell Stop";
Alert(message);
Print(message);
}
}
if(gCurrentDirection == -1)
{
double price = CCBC::MarketInfo(Symbol(), MODE_BID);
if(CCBC::OrderSelect(gBuyStopTicket, SELECT_BY_TICKET))
{
if(CCBC::OrderType() == OP_BUY) // if the buy stop has opened
{
Print("Recovery Buy Stop has been opene, initiating recovery...");
gBuyTicket = gBuyStopTicket; // set the buy ticket to the stop
gBuyStopTicket = 0; // reset the buy ticket
gLotSize = GetTradeVolume(positions+1);
if(MaxTrades == 0 || positions < MaxTrades) // check we've not exceeded the max trades
{
gSellStopTicket = OpenPendingOrder(Symbol(), OP_SELLSTOP, gLotSize, gSellOpenPrice, 0, 0, CCBC::StringConcatenate("Recovery Sell Stop opened."), 0, clrPink); // create an opposite sell stop
gRecoveryInitiated = true; // signal we're in recovery mode
}
gCurrentDirection = 1;
}
} else {
string message = "Warning - EA could not find the recovery Buy Stop";
Alert(message);
Print(message);
}
}
} else {
Comment("No OGT Zone Recovery Trades Active");
}
}
void TakeTrade(int direction)
{
double tp = 0;
double rz = 0;
if(UseATR == true)
{
double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
tp = atr*ATRTPFraction;
rz = atr*ATRZoneFraction;
} else if(UseATR == false)
{
tp = TakeProfit*_Point; // tp as price units
rz = RecoveryZoneSize*_Point; // rz as price
}
if(CustomLotSize1 != 0) gLotSize = CustomLotSize1;
else gLotSize = gInitialLotSize;
double price = 0;
if(direction == 1)
{
gBuyTicket = OpenMarketOrder(Symbol(), OP_BUY, gLotSize, "Initial Buy Order", clrGreen);
if(CCBC::OrderSelect(gBuyTicket, SELECT_BY_TICKET))
{
gBuyOpenPrice = CCBC::OrderOpenPrice();
gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
gBuyTakeProfit = NormalizeDouble((gBuyOpenPrice + tp), _Digits);
gSellTakeProfit = NormalizeDouble((gBuyOpenPrice - (tp + rz)), _Digits);
gLotSize = GetTradeVolume(2);
gSellStopTicket = OpenPendingOrder(Symbol(), OP_SELLSTOP, gLotSize, gSellOpenPrice, 0, 0, "Initial Recovery Sell Stop)", 0, clrPink);
gCurrentDirection = direction;
price = gBuyOpenPrice;
}
}
else if(direction == -1)
{
gSellTicket = OpenMarketOrder(Symbol(), OP_SELL, gLotSize, "Initial Sell Order", clrRed);
if(CCBC::OrderSelect(gSellTicket, SELECT_BY_TICKET))
{
gSellOpenPrice = CCBC::OrderOpenPrice();
gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
gSellTakeProfit = NormalizeDouble((gSellOpenPrice - tp), _Digits);
gBuyTakeProfit = NormalizeDouble((gSellOpenPrice + (tp + rz)), _Digits);
gLotSize = GetTradeVolume(2);
gBuyStopTicket = OpenPendingOrder(Symbol(), OP_BUYSTOP, gLotSize, gBuyOpenPrice, 0, 0, "Initial Recovery Buy Stop)", 0, clrTurquoise);
gCurrentDirection = direction;
price = gSellOpenPrice;
}
}
CreateProfitLine(direction, price, tp);
}
void PlaceTrade(int pType)
{
double tp = 0;
double rz = 0;
if(UseATR == true)
{
double atr = CCBC::iATR(_Symbol, PERIOD_D1, ATRPeriod, 1);
tp = atr*ATRTPFraction;
rz = atr*ATRZoneFraction;
} else if(UseATR == false)
{
tp = TakeProfit*_Point; // tp as price
rz = RecoveryZoneSize*_Point; // rz as price
}
if(CustomLotSize1 != 0) gLotSize = CustomLotSize1;
else gLotSize = gInitialLotSize;
if(pType == OP_BUYLIMIT)
{
gBuyStopTicket = OpenPendingOrder(_Symbol, OP_BUYLIMIT, gLotSize, PendingPrice, 0, 0, "Buy Limit Order", 0, 0);
gBuyOpenPrice = PendingPrice;
gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
gCurrentDirection = -1;
} else if(pType == OP_BUYSTOP)
{
gBuyStopTicket = OpenPendingOrder(_Symbol, OP_BUYSTOP, gLotSize, PendingPrice, 0, 0, "Buy Stop Order", 0, 0);
gBuyOpenPrice = PendingPrice;
gSellOpenPrice = NormalizeDouble((gBuyOpenPrice - rz), _Digits);
gCurrentDirection = -1;
} else if(pType == OP_SELLLIMIT)
{
gSellOpenPrice = PendingPrice;
gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
gSellStopTicket = OpenPendingOrder(_Symbol, OP_SELLLIMIT, gLotSize, PendingPrice, 0, 0, "Sell Limit Order", 0, 0);
gCurrentDirection = 1;
} else if(pType == OP_SELLSTOP)
{
gSellOpenPrice = PendingPrice;
gBuyOpenPrice = NormalizeDouble((gSellOpenPrice + rz), _Digits);
gSellStopTicket = OpenPendingOrder(_Symbol, OP_SELLSTOP, gLotSize, PendingPrice, 0, 0, "Sell Stop Order", 0, 0);
gCurrentDirection = 1;
}
CreateProfitLine(gCurrentDirection, PendingPrice, 0);
}
int Is_RSI_OBOS_on_MTF(int shift)
{
int direction = 0;
double rsi = CCBC::iRSI(_Symbol, PERIOD_M1, RSIPeriod, PRICE_CLOSE, shift);
if((UseM1Timeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE, shift);
if(UseM5Timeframe == false || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE, shift);
if((UseM15Timeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_M30, RSIPeriod, PRICE_CLOSE, shift);
if((UseM30Timeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_H1, RSIPeriod, PRICE_CLOSE, shift);
if((UseH1Timeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_H4, RSIPeriod, PRICE_CLOSE, shift);
if((UseH4Timeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_D1, RSIPeriod, PRICE_CLOSE, shift);
if((UseDailyTimeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_W1, RSIPeriod, PRICE_CLOSE, shift);
if((UseWeeklyTimeframe == false) || (rsi < OversoldLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_MN1, RSIPeriod, PRICE_CLOSE, shift);
if((UseMonthlyTimeframe == false) || (rsi < OversoldLevel))
{
direction = 1;
return direction;
}
}
}
}
}
}
}
}
}
rsi = CCBC::iRSI(_Symbol, PERIOD_M1, RSIPeriod, PRICE_CLOSE, shift);
if((UseM1Timeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE, shift);
if(UseM5Timeframe == false || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE, shift);
if((UseM15Timeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_M30, RSIPeriod, PRICE_CLOSE, shift);
if((UseM30Timeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_H1, RSIPeriod, PRICE_CLOSE, shift);
if((UseH1Timeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_H4, RSIPeriod, PRICE_CLOSE, shift);
if((UseH4Timeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_D1, RSIPeriod, PRICE_CLOSE, shift);
if((UseDailyTimeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_W1, RSIPeriod, PRICE_CLOSE, shift);
if((UseWeeklyTimeframe == false) || (rsi > OverboughtLevel))
{
rsi = CCBC::iRSI(_Symbol, PERIOD_MN1, RSIPeriod, PRICE_CLOSE, shift);
if((UseMonthlyTimeframe == false) || (rsi > OverboughtLevel))
{
direction = -1;
return direction;
}
}
}
}
}
}
}
}
}
return direction;
}
void CloseOrdersAndReset()
{
CloseAllMarketOrders();
DeletePendingOrders(CLOSE_ALL_PENDING);
gLotSize = gInitialLotSize;
gCurrentDirection = 0;
gBuyStopTicket = 0;
gSellStopTicket = 0;
gBuyTicket = 0;
gSellTicket = 0;
gRecoveryInitiated = false;
DeleteProfitLine();
}
void CreateProfitLine(double pDirection, double pPrice, double pPoints)
{
double price = 0;
if(pDirection == 1)
{
price = NormalizeDouble(pPrice + pPoints, _Digits);
} else if(pDirection == -1) {
price = NormalizeDouble(pPrice - pPoints, _Digits);
}
CCBC::ObjectCreate(0, PROFIT_LINE, OBJ_HLINE, 0,0,price);
CCBC::ObjectSetInteger(0, PROFIT_LINE, OBJPROP_COLOR, profitLineColor);
CCBC::ObjectSetInteger(0, PROFIT_LINE, OBJPROP_STYLE, STYLE_DASH);
}
void DeleteProfitLine()
{
CCBC::ObjectDelete(0, PROFIT_LINE);
}
void CreateTradingPanel()
{
long buttonWidth = 50;
long buttonHeight = 25;
long panelX = Panel_X;
long panelY = Panel_Y;
long boxMargin = 10;
long lableX = panelX+boxMargin+5;
long lableY = panelY+boxMargin+10;
long lableHeight = 40;
long buttonX = panelX+boxMargin+20;
long buttonY = panelY+lableHeight+boxMargin;
long panelWidth = boxMargin+buttonWidth+boxMargin+buttonWidth+boxMargin +40;
long panelHeight = boxMargin+lableHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin;
double pending = NormalizeDouble(PendingPrice, _Digits);
string buttonBox = "ButtonBox";
CCBC::ObjectCreate(0, buttonBox, OBJ_RECTANGLE_LABEL, 0, 0, 0);
CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_CORNER,CORNER_LEFT_UPPER);
CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_XSIZE, panelWidth);
CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_YSIZE, panelHeight);
CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_XDISTANCE, panelX);
CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_YDISTANCE, panelY);
CCBC::ObjectSetInteger(0, buttonBox, OBJPROP_BGCOLOR, Panel_Color);
CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_BORDER_TYPE,BORDER_RAISED);
CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_COLOR,clrGray);
CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_SELECTABLE,false);
CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_HIDDEN,false);
CCBC::ObjectSetInteger(0,buttonBox,OBJPROP_ZORDER,0);
gTradingPanelObjects[0] = buttonBox;
string panelLabel = "Trading Panel Label";
CCBC::ObjectCreate(0, panelLabel, OBJ_LABEL, 0,0,0);
CCBC::ObjectSetString(0, panelLabel, OBJPROP_TEXT, EA_NAME);
CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_XDISTANCE, lableX);
CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_YDISTANCE, lableY);
CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_COLOR, Panel_Lable_Color);
CCBC::ObjectSetInteger(0, panelLabel, OBJPROP_FONTSIZE, 9);
gTradingPanelObjects[1] = panelLabel;
string sellButtonName = SELL_BUTTON;
CCBC::ObjectCreate(0, sellButtonName, OBJ_BUTTON, 0, 0, 0);
CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_XSIZE, buttonWidth);
CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_YSIZE, buttonHeight);
CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_XDISTANCE, buttonX);
CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_YDISTANCE, buttonY);
CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_COLOR, Panel_Lable_Color);
CCBC::ObjectSetInteger(0, sellButtonName, OBJPROP_BGCOLOR, clrRed);
CCBC::ObjectSetString(0, sellButtonName, OBJPROP_TEXT, "Sell");
gTradingPanelObjects[2] = SELL_BUTTON;
string buyButtonName = BUY_BUTTON;
CCBC::ObjectCreate(0, buyButtonName, OBJ_BUTTON, 0, 0, 0);
CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_XSIZE, buttonWidth);
CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_YSIZE, buttonHeight);
CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_XDISTANCE, (buttonX+buttonWidth+boxMargin));
CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_YDISTANCE, buttonY);
CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_COLOR, Panel_Lable_Color);
CCBC::ObjectSetInteger(0, buyButtonName, OBJPROP_BGCOLOR, clrGreen);
CCBC::ObjectSetString(0, buyButtonName, OBJPROP_TEXT, "Buy");
gTradingPanelObjects[3] = BUY_BUTTON;
CCBC::ObjectCreate(0, CLOSE_ALL_BUTTON, OBJ_BUTTON, 0, 0, 0);
CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_XSIZE, buttonWidth+boxMargin+buttonWidth);
CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_YSIZE, buttonHeight);
CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_XDISTANCE, (buttonX));
CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_COLOR, Panel_Lable_Color);
CCBC::ObjectSetInteger(0, CLOSE_ALL_BUTTON, OBJPROP_BGCOLOR, clrGray);
CCBC::ObjectSetString(0, CLOSE_ALL_BUTTON, OBJPROP_TEXT, "Close All Orders");
gTradingPanelObjects[4] = CLOSE_ALL_BUTTON;
string TPLabel = "TP Label";
CCBC::ObjectCreate(0, TPLabel, OBJ_LABEL, 0, 0, 0);
CCBC::ObjectSetString(0, TPLabel, OBJPROP_TEXT, "TP: ");
CCBC::ObjectSetInteger(0, TPLabel, OBJPROP_XDISTANCE, buttonX);
CCBC::ObjectSetInteger(0, TPLabel, OBJPROP_YDISTANCE, 5+buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, TPLabel, OBJPROP_COLOR, Panel_Lable_Color);
gTradingPanelObjects[5] = TPLabel;
string zoneLable = "Zone Lable";
CCBC::ObjectCreate(0, zoneLable, OBJ_LABEL, 0, 0, 0);
CCBC::ObjectSetString(0, zoneLable, OBJPROP_TEXT, "Zone: ");
CCBC::ObjectSetInteger(0, zoneLable, OBJPROP_XDISTANCE, buttonX);
CCBC::ObjectSetInteger(0, zoneLable, OBJPROP_YDISTANCE, 5+ buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, zoneLable, OBJPROP_COLOR, Panel_Lable_Color);
gTradingPanelObjects[6] = zoneLable;
CCBC::ObjectCreate(0, TP_EDIT, OBJ_EDIT, 0, 0, 0);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_XSIZE, buttonWidth);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_YSIZE, buttonHeight);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_COLOR, clrBlack);
CCBC::ObjectSetInteger(0, TP_EDIT, OBJPROP_BGCOLOR, clrWhite);
CCBC::ObjectSetString(0, TP_EDIT, OBJPROP_TEXT, IntegerToString(TakeProfit));
CCBC::ObjectSetInteger(0,TP_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
gTradingPanelObjects[7] = TP_EDIT;
CCBC::ObjectCreate(0, ZONE_EDIT, OBJ_EDIT, 0, 0, 0);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_XSIZE, buttonWidth);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_YSIZE, buttonHeight);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_COLOR, clrBlack);
CCBC::ObjectSetInteger(0, ZONE_EDIT, OBJPROP_BGCOLOR, clrWhite);
CCBC::ObjectSetString(0, ZONE_EDIT, OBJPROP_TEXT, IntegerToString(RecoveryZoneSize));
CCBC::ObjectSetInteger(0,ZONE_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
gTradingPanelObjects[8] = ZONE_EDIT;
CCBC::ObjectCreate(0, PENDING_EDIT, OBJ_EDIT, 0, 0, 0);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_CORNER, CORNER_LEFT_UPPER);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_XDISTANCE, buttonX+buttonWidth+boxMargin);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_YDISTANCE, buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_XSIZE, buttonWidth);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_YSIZE, buttonHeight);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_COLOR, clrBlack);
CCBC::ObjectSetInteger(0, PENDING_EDIT, OBJPROP_BGCOLOR, clrWhite);
CCBC::ObjectSetString(0, PENDING_EDIT, OBJPROP_TEXT, IntegerToString(pending));
CCBC::ObjectSetInteger(0,PENDING_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
gTradingPanelObjects[9] = PENDING_EDIT;
string pendingLabel = "Pending Label";
CCBC::ObjectCreate(0, pendingLabel, OBJ_LABEL, 0, 0, 0);
CCBC::ObjectSetString(0, pendingLabel, OBJPROP_TEXT, "Price: ");
CCBC::ObjectSetInteger(0, pendingLabel, OBJPROP_XDISTANCE, buttonX);
CCBC::ObjectSetInteger(0, pendingLabel, OBJPROP_YDISTANCE, 5+ buttonY+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin+buttonHeight+boxMargin);
CCBC::ObjectSetInteger(0, pendingLabel, OBJPROP_COLOR, Panel_Lable_Color);
gTradingPanelObjects[10] = pendingLabel;
}
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
if(sparam == SELL_BUTTON && gCurrentDirection == 0)
{
if(gCurrentDirection == 0 && PendingPrice == 0) TakeTrade((int)-1);
else if(PendingPrice > Bid) PlaceTrade(OP_SELLLIMIT);
else if(PendingPrice < Bid) PlaceTrade(OP_SELLSTOP);
}
else if(sparam == BUY_BUTTON && gCurrentDirection == 0)
{
if(gCurrentDirection == 0 && PendingPrice == 0) TakeTrade((int)1);
else if(PendingPrice > Ask) PlaceTrade(OP_BUYSTOP);
else if(PendingPrice < Ask) PlaceTrade(OP_BUYLIMIT);
}
else if(sparam == CLOSE_ALL_BUTTON)
{
CloseOrdersAndReset();
Print("Close all pressed.");
}
else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == TP_EDIT)
{
string takeProfitString = CCBC::ObjectGetString(0, TP_EDIT, OBJPROP_TEXT);
TakeProfit = StringToPips(takeProfitString);
}
else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == ZONE_EDIT)
{
string zoneString = CCBC::ObjectGetString(0, ZONE_EDIT, OBJPROP_TEXT);
RecoveryZoneSize = StringToPips(zoneString);
}
else if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == PENDING_EDIT)
{
string pendingString = CCBC::ObjectGetString(0, PENDING_EDIT, OBJPROP_TEXT);
PendingPrice = NormalizeDouble(StringToDouble(pendingString), _Digits);
}
}
void DeleteTradePanel()
{
for(int count = 0; count <= ArraySize(gTradingPanelObjects)-1; count++)
{
if(ArraySize(gTradingPanelObjects) > 0)
{
string objectName = gTradingPanelObjects[count];
CCBC::ObjectDelete(0, objectName);
}
}
}
double PipPoint(string Currency)
{
double CalcPoint = 0;
double CalcDigits = CCBC::MarketInfo(Currency,MODE_DIGITS);
if(CalcDigits == 2 || CalcDigits == 3) CalcPoint = 0.01;
else if(CalcDigits == 4 || CalcDigits == 5) CalcPoint = 0.0001;
else if(CalcDigits == 0) CalcPoint = 0;
else if(CalcDigits == 1) CalcPoint = 0.1;
return(CalcPoint);
}
double GetSlippage(string Currency, int SlippagePips)
{
double CalcSlippage = SlippagePips;
int CalcDigits = (int)CCBC::MarketInfo(Currency,MODE_DIGITS);
if(CalcDigits == 0 || CalcDigits == 1 || CalcDigits == 2 || CalcDigits == 4) CalcSlippage = SlippagePips;
else if(CalcDigits == 3 || CalcDigits == 5) CalcSlippage = SlippagePips;
return(CalcSlippage);
}
int GetPoints(int Pips)
{
int CalcPoint = Pips;
double CalcDigits = CCBC::MarketInfo(Symbol(),MODE_DIGITS);
if(CalcDigits == 0 || CalcDigits == 1 || CalcDigits == 2 || CalcDigits == 4) CalcPoint = Pips;
return(CalcPoint);
}
int StringToPips(string text)
{
int pips = StringToInteger(text);
if(pips <= 0)
{
Alert("Invalid pips from string: ", pips);
}
return pips;
}
void CloseAllMarketOrders()
{
int retryCount = 0;
for(int Counter = 0; Counter <= CCBC::OrdersTotal()-1; Counter++)
{
if(CCBC::OrderSelect(Counter,SELECT_BY_POS))
{
if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && (CCBC::OrderType() == OP_BUY || CCBC::OrderType() == OP_SELL))
{
int CloseTicket = CCBC::OrderTicket();
double CloseLots = CCBC::OrderLots();
while(CCBC::IsTradeContextBusy()) Sleep(10);
CCBC::RefreshRates();
double ClosePrice = CCBC::MarketInfo(_Symbol,MODE_BID);
if(CCBC::OrderType() == OP_SELL) ClosePrice = CCBC::MarketInfo(_Symbol, MODE_ASK);
bool Closed = CCBC::OrderClose(CloseTicket,CloseLots,ClosePrice,Slippage,Red);
if(Closed == false)
{
int ErrorCode = CCBC::GetLastError();
string ErrAlert = CCBC::StringConcatenate("Close All Market Orders - Error ",ErrorCode,".");
Alert(ErrAlert);
Print(ErrAlert);
} else Counter--;
}
}
}
}
double GetTradeVolume(int pTradeNo)
{
double lots = 0;
double volume = 0;
if(CustomLotSize1 == 0)
{
lots = (gLotSize*LotMultiplier)+LotAdditions; //increase the lot size
} else if(CustomLotSize1 != 0){
if(pTradeNo > 10) {
Alert("No of trades exceeds custom lot size inputs (10)");
return -1;
} else {
lots = gCustomLotSizes[pTradeNo-1];
}
}
volume = CheckVolume(_Symbol, lots);
return volume;
}
double CheckVolume(string pSymbol,double pVolume)
{
double minVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_MIN);
double maxVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_MAX);
double stepVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_STEP);
double tradeSize;
if(pVolume < minVolume)
{
Alert("Sent volume is smaller than the minimum volume for this symbol: ", _Symbol, ", min: ", minVolume, ", sent: ", pVolume);
tradeSize = minVolume;
}
else if(pVolume > maxVolume)
{
Alert("Sent volume is larger than the maximum volume for this symbol: ", _Symbol, ", max: ", maxVolume, ", sent: ", pVolume);
tradeSize = maxVolume;
}
else tradeSize = MathRound(pVolume / stepVolume) * stepVolume;
if(stepVolume >= 0.1) tradeSize = NormalizeDouble(tradeSize,1);
else tradeSize = NormalizeDouble(tradeSize,2);
return(tradeSize);
}
bool DeletePendingOrders(CLOSE_PENDING_TYPE pDeleteType)
{
bool error = false;
bool deleteOrder = false;
for(int order = 0; order <= CCBC::OrdersTotal() - 1; order++)
{
bool result = CCBC::OrderSelect(order,SELECT_BY_POS);
int orderType = CCBC::OrderType();
int orderMagicNumber = CCBC::OrderMagicNumber();
int orderTicket = CCBC::OrderTicket();
double orderVolume = CCBC::OrderLots();
if( (pDeleteType == CLOSE_ALL_PENDING && orderType != OP_BUY && orderType != OP_SELL)
|| (pDeleteType == CLOSE_BUY_LIMIT && orderType == OP_BUYLIMIT)
|| (pDeleteType == CLOSE_SELL_LIMIT && orderType == OP_SELLLIMIT)
|| (pDeleteType == CLOSE_BUY_STOP && orderType == OP_BUYSTOP)
|| (pDeleteType == CLOSE_SELL_STOP && orderType == OP_SELLSTOP) )
{
deleteOrder = true;
}
else deleteOrder = false;
if(deleteOrder == true && orderMagicNumber == MagicNumber)
{
result = CCBC::OrderDelete(orderTicket);
if(result == false)
{
Print("Delete multiple orders, failed to delete order: ", orderTicket);
error = true;
}
else order--;
}
}
return(error);
}
int OpenPendingOrder(string pSymbol,int pType,double pVolume,double pPrice,double pStop,double pProfit,string pComment,datetime pExpiration,color pArrow)
{
int retryCount = 0;
int ticket = 0;
int errorCode = 0;
int max_attempts = 5;
string orderType;
string errDesc;
while(retryCount <= max_attempts)
{
while(CCBC::IsTradeContextBusy()) Sleep(10);
ticket = CCBC::OrderSend(pSymbol, pType, pVolume, pPrice, Slippage, pStop, pProfit, pComment, MagicNumber, pExpiration, pArrow);
if(ticket == -1)
{
errorCode = CCBC::GetLastError();
bool checkError = RetryOnError(errorCode);
if(checkError == false)
{
Alert("Open ",orderType," order: Error ",errorCode,".");
Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",pPrice,", SL: ",pStop,", TP: ",pProfit,", Expiration: ",pExpiration);
break;
}
else
{
Print("Server error detected, retrying...");
Sleep(3000);
retryCount++;
}
}
else
{
Comment(orderType," order #",ticket," opened on ",_Symbol);
Print(orderType," order #",ticket," opened on ",_Symbol);
break;
}
}
if(retryCount > max_attempts)
{
Alert("Open ",orderType," order: Max retries exceeded. Error ",errorCode," - ",errDesc);
Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",pPrice,", SL: ",pStop,", TP: ",pProfit,", Expiration: ",pExpiration);
}
return(ticket);
}
bool RetryOnError(int pErrorCode)
{
switch(pErrorCode)
{
case ERR_BROKER_BUSY:
case ERR_COMMON_ERROR:
case ERR_NO_ERROR:
case ERR_NO_CONNECTION:
case ERR_NO_RESULT:
case ERR_SERVER_BUSY:
case ERR_NOT_ENOUGH_RIGHTS:
case ERR_MALFUNCTIONAL_TRADE:
case ERR_TRADE_CONTEXT_BUSY:
case ERR_TRADE_TIMEOUT:
case ERR_REQUOTE:
case ERR_TOO_MANY_REQUESTS:
case ERR_OFF_QUOTES:
case ERR_PRICE_CHANGED:
case ERR_TOO_FREQUENT_REQUESTS:
return(true);
}
return(false);
}
int OpenMarketOrder(string pSymbol, int pType, double pVolume, string pComment, color pArrow)
{
int retryCount = 0;
int ticket = 0;
int errorCode = 0;
int max_attempts = 5;
int wait_time = 3000;
double orderPrice = 0;
string orderType;
string errDesc;
while(retryCount <= max_attempts)
{
while(CCBC::IsTradeContextBusy()) Sleep(10);
if(pType == OP_BUY) orderPrice = CCBC::MarketInfo(pSymbol,MODE_ASK);
else if(pType == OP_SELL) orderPrice = CCBC::MarketInfo(pSymbol,MODE_BID);
ticket = CCBC::OrderSend(pSymbol,pType,pVolume,orderPrice,Slippage,0,0,pComment,MagicNumber,0,pArrow);
if(ticket == -1)
{
errorCode = CCBC::GetLastError();
bool checkError = RetryOnError(errorCode);
if(checkError == false)
{
Alert("Open ",orderType," order: Error ",errorCode,".");
Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",orderPrice);
break;
}
else
{
Print("Server error detected, retrying...");
Sleep(wait_time);
retryCount++;
}
}
else
{
Comment(orderType," order #",ticket," opened on ",pSymbol);
Print(orderType," order #",ticket," opened on ",pSymbol);
break;
}
}
if(retryCount > max_attempts)
{
Alert("Open ",orderType," order: Max retries exceeded. Error ",errorCode," - ",errDesc);
Print("Symbol: ",pSymbol,", Volume: ",pVolume,", Price: ",orderPrice);
}
return(ticket);
}
double GetTradeSize(string pSymbol, double pFixedVol, double pPercent, int pStopPoints)
{
double tradeSize;
if(pPercent > 0 && pStopPoints > 0)
{
if(pPercent > 10) pPercent = 10;
double margin = AccountInfoDouble(ACCOUNT_BALANCE) * (pPercent / 100);
double tickSize = SymbolInfoDouble(pSymbol,SYMBOL_TRADE_TICK_VALUE);
tradeSize = (margin / pStopPoints) / tickSize;
tradeSize = CheckVolume(pSymbol,tradeSize);
return(tradeSize);
}
else
{
tradeSize = pFixedVol;
tradeSize = CheckVolume(pSymbol,tradeSize);
return(tradeSize);
}
return NULL;
}
datetime CreateDateTime(int pHour = 0, int pMinute = 0)
{
MqlDateTime timeStruct;
TimeToStruct(TimeCurrent(),timeStruct);
timeStruct.hour = pHour;
timeStruct.min = pMinute;
datetime useTime = StructToTime(timeStruct);
return(useTime);
}
bool CheckDailyTimer()
{
datetime TimeStart = CreateDateTime(StartHour, StartMinute);
datetime TimeEnd = CreateDateTime(EndHour, EndMinute);
datetime currentTime;
if(UseLocalTime == true) currentTime = TimeLocal();
else currentTime = TimeCurrent();
if(TimeEnd <= TimeStart)
{
TimeStart -= 86400;
if(currentTime > TimeEnd)
{
TimeStart += 86400;
TimeEnd += 86400;
}
}
bool timerOn = false;
if(currentTime >= TimeStart && currentTime < TimeEnd)
{
timerOn = true;
}
return(timerOn);
}
void FindOpenOrders()
{
double largest_lots = 0;
int ticket = -1;
int open_orders = 0;
int stopTicket = 0;
for(int Counter = 0; Counter <= CCBC::OrdersTotal()-1; Counter++)
{
if(CCBC::OrderSelect(Counter,SELECT_BY_POS))
{
if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && (CCBC::OrderType() == OP_BUY || CCBC::OrderType() == OP_SELL))
{
open_orders++;
if(CCBC::OrderLots() > largest_lots)
{
ticket = CCBC::OrderTicket();
largest_lots = CCBC::OrderLots();
}
}
if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && CCBC::OrderType() == OP_BUYSTOP)
{
gBuyStopTicket = CCBC::OrderTicket();
stopTicket = gBuyStopTicket;
} else if(CCBC::OrderMagicNumber() == MagicNumber && CCBC::OrderSymbol() == _Symbol && CCBC::OrderType() == OP_SELLSTOP)
{
gSellStopTicket = CCBC::OrderTicket();
stopTicket = gSellStopTicket;
}
}
}
if(ticket > 0)
{
if(CCBC::OrderSelect(ticket, SELECT_BY_TICKET))
{
int type = CCBC::OrderType();
if(type == OP_BUY)
{
gCurrentDirection = 1;
gBuyTicket = ticket;
} else if(type == OP_SELL)
{
gCurrentDirection = -1;
gSellTicket = ticket;
}
if(open_orders > 1) gRecoveryInitiated = true;
}
Print("Check for orders complete, resuming recovery direction of trade: ", ticket, " with recovery stop: ", stopTicket, " in place. ", open_orders, " orders already opened.");
} else {
Print("Check for orders complete, none currently open.");
}
}
int FXD_SELECTED_TYPE = 0;// Indicates what is selected by OrderSelect, 1 for trade, 2 for pending order, 3 for history trade
ulong FXD_SELECTED_TICKET = 0;// The ticket number selected by OrderSelect
int FXD_INDICATOR_COUNTED_MEMORY = 0;// Used as a memory for IndicatorCounted() function. It needs to be outside of the function, because when OnCalculate needs to be reset, this memory must be reset as well.
int Bars = Bars(_Symbol, PERIOD_CURRENT);
int Digits = _Digits;
double Point = _Point;
double Ask, Bid, Close[], High[], Low[], Open[];
long Volume[];
datetime Time[];
void OnTick()
{
// код доступен только после оплаты
}
class CCBC
{
private:
/**
* _LastError is used to set custom errors that could be returned by the custom GetLastError method
* The initial value should be -1 and everything >= 0 should be valid error code
* When setting an error code in it, it should be the MQL5 value,
* because then in GetLastError it will be converted to MQL4 value
*/
static int _LastError;
public:
CCBC() {
};
/**
* Overloads for the case when numeric value is used for timeframe
*/
static int CopyTime(const string symbol_name, int timeframe, int start_pos, int count, datetime &time_array[]) {
return ::CopyTime(symbol_name, CCBC::_ConvertTimeframe_(timeframe), start_pos, count, time_array);
}
static int CopyTime(const string symbol_name, int timeframe, datetime start_time, int count, datetime &time_array[]) {
return ::CopyTime(symbol_name, CCBC::_ConvertTimeframe_(timeframe), start_time, count, time_array);
}
static int CopyTime(const string symbol_name, int timeframe, datetime start_time, datetime stop_time, datetime &time_array[]) {
return ::CopyTime(symbol_name, CCBC::_ConvertTimeframe_(timeframe), start_time, stop_time, time_array);
}
static string DoubleToStr(double value, int digits = 8) {
return ::DoubleToString(value, digits);
}
/**
* In MQL4's documentation errors are also shown as numeric values and sometimes people use these numbers, because they are shorter to write.
* This means that GetLastError shoud return such MQL4 numeric values instead of the MQL5 values.
* Supports custom error codes that can be set with CCBC -> _LastError
*/
static int GetLastError() {
int errorCode = 0;
if (CCBC::_LastError >= 0) {
errorCode = CCBC::_LastError;
CCBC::_LastError = -1;
}
else {
errorCode = ::GetLastError();
}
switch (errorCode) {
case ERR_SUCCESS : return 0; /* ERR_NO_ERROR */
case TRADE_RETCODE_INVALID : return 3; /* ERR_INVALID_TRADE_PARAMETERS */
case ERR_TRADE_SEND_FAILED : return 4; /* ERR_SERVER_BUSY */
case TRADE_RETCODE_CONNECTION : return 6; /* ERR_NO_CONNECTION */
case TRADE_RETCODE_REJECT : return 7; /* ERR_NOT_ENOUGH_RIGHTS */
case TRADE_RETCODE_ERROR : return 9; /* ERR_MALFUNCTIONAL_TRADE */
case TRADE_RETCODE_TIMEOUT : return 128; /* ERR_TRADE_TIMEOUT */
case TRADE_RETCODE_INVALID_PRICE : return 129; /* ERR_INVALID_PRICE */
case TRADE_RETCODE_INVALID_STOPS : return 130; /* ERR_INVALID_STOPS */
case TRADE_RETCODE_INVALID_VOLUME : return 131; /* ERR_INVALID_TRADE_VOLUME */
case TRADE_RETCODE_MARKET_CLOSED : return 132; /* ERR_MARKET_CLOSED */
case TRADE_RETCODE_TRADE_DISABLED : return 133; /* ERR_TRADE_DISABLED */
case TRADE_RETCODE_NO_MONEY : return 134; /* ERR_NOT_ENOUGH_MONEY */
case TRADE_RETCODE_PRICE_CHANGED : return 135; /* ERR_PRICE_CHANGED */
case TRADE_RETCODE_PRICE_OFF : return 136; /* ERR_OFF_QUOTES */
case TRADE_RETCODE_REQUOTE : return 138; /* ERR_REQUOTE */
case TRADE_RETCODE_LOCKED : return 139; /* ERR_ORDER_LOCKED */
case TRADE_RETCODE_TOO_MANY_REQUESTS : return 141; /* ERR_TOO_MANY_REQUESTS */
case TRADE_RETCODE_INVALID_EXPIRATION : return 147; /* ERR_TRADE_EXPIRATION_DENIED */
case TRADE_RETCODE_LIMIT_ORDERS : return 148; /* ERR_TRADE_TOO_MANY_ORDERS */
case 10046 : return 149; /* ERR_TRADE_HEDGE_PROHIBITED */
case TRADE_RETCODE_FIFO_CLOSE : return 150; /* ERR_TRADE_PROHIBITED_BY_FIFO */
case ERR_INVALID_POINTER_TYPE : return 4001; /* ERR_WRONG_FUNCTION_POINTER */
case ERR_SMALL_ARRAY : return 4002; /* ERR_ARRAY_INDEX_OUT_OF_RANGE */
case ERR_MATH_OVERFLOW : return 4004; /* ERR_RECURSIVE_STACK_OVERFLOW */
case ERR_STRING_OUT_OF_MEMORY : return 4006; /* ERR_NO_MEMORY_FOR_PARAM_STRING */
case ERR_NOTINITIALIZED_STRING : return 4008; /* ERR_NOT_INITIALIZED_STRING */
case ERR_STRING_TOO_BIGNUMBER : return 4011; /* ERR_TOO_LONG_STRING */
case ERR_ZEROSIZE_ARRAY : return 4016; /* ERR_NOT_INITIALIZED_ARRAY */
case ERR_INTERNAL_ERROR : return 4024; /* ERR_INTERNAL_ERROR */
case ERR_NOT_ENOUGH_MEMORY : return 4025; /* ERR_OUT_OF_MEMORY */
case ERR_INVALID_POINTER : return 4026; /* ERR_INVALID_POINTER */
case ERR_TOO_MANY_FORMATTERS : return 4027; /* ERR_FORMAT_TOO_MANY_FORMATTERS */
case ERR_TOO_MANY_PARAMETERS : return 4028; /* ERR_FORMAT_TOO_MANY_PARAMETERS */
case ERR_INVALID_ARRAY : return 4029; /* ERR_ARRAY_INVALID */
case ERR_CHART_NO_REPLY : return 4030; /* ERR_CHART_NOREPLY */
case ERR_WRONG_INTERNAL_PARAMETER : return 4052; /* ERR_STRING_FUNCTION_INTERNAL */
case ERR_SERIES_ARRAY : return 4054; /* ERR_INCORRECT_SERIESARRAY_USING */
case ERR_INCOMPATIBLE_ARRAYS : return 4056; /* ERR_INCOMPATIBLE_ARRAYS */
case ERR_GLOBALVARIABLE_EXISTS :
case ERR_GLOBALVARIABLE_NOT_MODIFIED :
case ERR_GLOBALVARIABLE_CANNOTREAD :
case ERR_GLOBALVARIABLE_CANNOTWRITE : return 4057; /* ERR_GLOBAL_VARIABLES_PROCESSING */
case ERR_GLOBALVARIABLE_NOT_FOUND : return 4058; /* ERR_GLOBAL_VARIABLE_NOT_FOUND */
case ERR_FUNCTION_NOT_ALLOWED : return 4060; /* ERR_FUNCTION_NOT_CONFIRMED */
case ERR_MAIL_SEND_FAILED : return 4061; /* ERR_SEND_MAIL_ERROR */
case ERR_RESOURCE_NOT_FOUND : return 4068; /* ERR_RESOURCE_NOT_FOUND */
case ERR_RESOURCE_UNSUPPOTED_TYPE : return 4069; /* ERR_RESOURCE_NOT_SUPPORTED */
case ERR_RESOURCE_NAME_DUPLICATED : return 4070; /* ERR_RESOURCE_DUPLICATED */
case ERR_INDICATOR_CANNOT_CREATE : return 4071; /* ERR_INDICATOR_CANNOT_INIT */
case ERR_INDICATOR_CANNOT_ADD :
case ERR_CHART_INDICATOR_CANNOT_ADD : return 4072; /* ERR_INDICATOR_CANNOT_LOAD */
case ERR_HISTORY_NOT_FOUND : return 4073; /* ERR_NO_HISTORY_DATA */
case ERR_HISTORY_LOAD_ERRORS : return 4074; /* ERR_NO_MEMORY_FOR_HISTORY */
case ERR_BUFFERS_NO_MEMORY : return 4075; /* ERR_NO_MEMORY_FOR_INDICATOR */
case ERR_FILE_ENDOFFILE : return 4099; /* ERR_END_OF_FILE */
case ERR_TRADE_POSITION_NOT_FOUND :
case ERR_TRADE_ORDER_NOT_FOUND :
case ERR_TRADE_DEAL_NOT_FOUND : return 4105; /* ERR_NO_ORDER_SELECTED */
case ERR_MARKET_UNKNOWN_SYMBOL :
case ERR_INDICATOR_UNKNOWN_SYMBOL : return 4106; /* ERR_UNKNOWN_SYMBOL */
case ERR_TRADE_DISABLED :
case TRADE_RETCODE_CLIENT_DISABLES_AT : return 4109; /* ERR_TRADE_NOT_ALLOWED */
case TRADE_RETCODE_SHORT_ONLY : return 4110; /* ERR_LONGS_NOT_ALLOWED */
case TRADE_RETCODE_LONG_ONLY : return 4111; /* ERR_SHORTS_NOT_ALLOWED */
case TRADE_RETCODE_SERVER_DISABLES_AT : return 4112; /* ERR_TRADE_EXPERT_DISABLED_BY_SERVER */
case ERR_OBJECT_WRONG_PROPERTY : return 4201; /* ERR_UNKNOWN_OBJECT_PROPERTY */
case ERR_OBJECT_NOT_FOUND : return 4202; /* ERR_OBJECT_DOES_NOT_EXIST */
case ERR_OBJECT_ERROR : return 4207; /* ERR_SOME_OBJECT_ERROR */
case ERR_CHART_WRONG_PROPERTY : return 4210; /* ERR_CHART_PROP_INVALID */
case ERR_CHART_NOT_FOUND : return 4211; /* ERR_CHART_NOT_FOUND */
case ERR_CHART_WINDOW_NOT_FOUND : return 4212; /* ERR_CHARTWINDOW_NOT_FOUND */
case ERR_CHART_INDICATOR_NOT_FOUND : return 4213; /* ERR_CHARTINDICATOR_NOT_FOUND */
case ERR_MARKET_NOT_SELECTED : return 4220; /* ERR_SYMBOL_SELECT */
case ERR_NOTIFICATION_SEND_FAILED : return 4250; /* ERR_NOTIFICATION_ERROR */
case ERR_NOTIFICATION_WRONG_PARAMETER : return 4251; /* ERR_NOTIFICATION_PARAMETER */
case ERR_NOTIFICATION_WRONG_SETTINGS : return 4252; /* ERR_NOTIFICATION_SETTINGS */
case ERR_NOTIFICATION_TOO_FREQUENT : return 4253; /* ERR_NOTIFICATION_TOO_FREQUENT */
case ERR_FTP_NOSERVER : return 4260; /* ERR_FTP_NOSERVER */
case ERR_FTP_NOLOGIN : return 4261; /* ERR_FTP_NOLOGIN */
case ERR_FTP_CONNECT_FAILED : return 4262; /* ERR_FTP_CONNECT_FAILED */
case 4524 : return 4263; /* ERR_FTP_CLOSED */
case ERR_FTP_CHANGEDIR : return 4264; /* ERR_FTP_CHANGEDIR */
case ERR_FTP_FILE_ERROR : return 4265; /* ERR_FTP_FILE_ERROR */
case ERR_FTP_SEND_FAILED : return 4266; /* ERR_FTP_ERROR */
case ERR_TOO_MANY_FILES : return 5001; /* ERR_FILE_TOO_MANY_OPENED */
case ERR_WRONG_FILENAME : return 5002; /* ERR_FILE_WRONG_FILENAME */
case ERR_TOO_LONG_FILENAME : return 5003; /* ERR_FILE_TOO_LONG_FILENAME */
case ERR_CANNOT_OPEN_FILE : return 5004; /* ERR_FILE_CANNOT_OPEN */
case ERR_FILE_CACHEBUFFER_ERROR : return 5005; /* ERR_FILE_BUFFER_ALLOCATION_ERROR */
case ERR_CANNOT_DELETE_FILE : return 5006; /* ERR_FILE_CANNOT_DELETE */
case ERR_INVALID_FILEHANDLE : return 5007; /* ERR_FILE_INVALID_HANDLE */
case ERR_WRONG_FILEHANDLE : return 5008; /* ERR_FILE_WRONG_HANDLE */
case ERR_FILE_NOTTOWRITE : return 5009; /* ERR_FILE_NOT_TOWRITE */
case ERR_FILE_NOTTOREAD : return 5010; /* ERR_FILE_NOT_TOREAD */
case ERR_FILE_NOTBIN : return 5011; /* ERR_FILE_NOT_BIN */
case ERR_FILE_NOTTXT : return 5012; /* ERR_FILE_NOT_TXT */
case ERR_FILE_NOTTXTORCSV : return 5013; /* ERR_FILE_NOT_TXTORCSV */
case ERR_FILE_NOTCSV : return 5014; /* ERR_FILE_NOT_CSV */
case ERR_FILE_READERROR : return 5015; /* ERR_FILE_READ_ERROR */
case ERR_FILE_WRITEERROR : return 5016; /* ERR_FILE_WRITE_ERROR */
case ERR_FILE_BINSTRINGSIZE : return 5017; /* ERR_FILE_BIN_STRINGSIZE */
case ERR_INCOMPATIBLE_FILE : return 5018; /* ERR_FILE_INCOMPATIBLE */
case ERR_FILE_IS_DIRECTORY : return 5019; /* ERR_FILE_IS_DIRECTORY */
case ERR_FILE_NOT_EXIST : return 5020; /* ERR_FILE_NOT_EXIST */
case ERR_FILE_CANNOT_REWRITE : return 5021; /* ERR_FILE_CANNOT_REWRITE */
case ERR_WRONG_DIRECTORYNAME : return 5022; /* ERR_FILE_WRONG_DIRECTORYNAME */
case ERR_DIRECTORY_NOT_EXIST : return 5023; /* ERR_FILE_DIRECTORY_NOT_EXIST */
case ERR_FILE_ISNOT_DIRECTORY : return 5024; /* ERR_FILE_NOT_DIRECTORY */
case ERR_CANNOT_DELETE_DIRECTORY : return 5025; /* ERR_FILE_CANNOT_DELETE_DIRECTORY */
case ERR_CANNOT_CLEAN_DIRECTORY : return 5026; /* ERR_FILE_CANNOT_CLEAN_DIRECTORY */
case ERR_ARRAY_RESIZE_ERROR : return 5027; /* ERR_FILE_ARRAYRESIZE_ERROR */
case ERR_STRING_RESIZE_ERROR : return 5028; /* ERR_FILE_STRINGRESIZE_ERROR */
case ERR_STRUCT_WITHOBJECTS_ORCLASS : return 5029; /* ERR_FILE_STRUCT_WITH_OBJECTS */
case ERR_WEBREQUEST_INVALID_ADDRESS : return 5200; /* ERR_WEBREQUEST_INVALID_ADDRESS */
case ERR_WEBREQUEST_CONNECT_FAILED : return 5201; /* ERR_WEBREQUEST_CONNECT_FAILED */
case ERR_WEBREQUEST_TIMEOUT : return 5202; /* ERR_WEBREQUEST_TIMEOUT */
case ERR_WEBREQUEST_REQUEST_FAILED : return 5203; /* ERR_WEBREQUEST_REQUEST_FAILED */
case ERR_USER_ERROR_FIRST : return 65536; /* ERR_USER_ERROR_FIRST */
default : return 2; /* ERR_COMMON_ERROR */
}
}
static bool IsTesting() {
return (bool)::MQLInfoInteger(MQL_TESTER);
}
/**
* Can't find such functionality in MQL5, but I think TERMINAL_CONNECTED should be here
*/
static bool IsTradeContextBusy() {
if (!::TerminalInfoInteger(TERMINAL_CONNECTED)) return true;
return false;
}
static bool IsVisualMode() {
return (bool)::MQLInfoInteger(MQL_VISUAL_MODE);
}
static double MarketInfo(string symbol, int type) {
if (symbol == NULL) symbol = ::Symbol();
switch(type) {
case 1 /* MODE_LOW */ : return ::SymbolInfoDouble(symbol, SYMBOL_LASTLOW);
case 2 /* MODE_HIGH */ : return ::SymbolInfoDouble(symbol, SYMBOL_LASTHIGH);
case 5 /* MODE_TIME */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TIME);
case 9 /* MODE_BID */ : return ::SymbolInfoDouble(symbol, SYMBOL_BID);
case 10 /* MODE_ASK */ : return ::SymbolInfoDouble(symbol, SYMBOL_ASK);
case 11 /* MODE_POINT */ : return ::SymbolInfoDouble(symbol, SYMBOL_POINT);
case 12 /* MODE_DIGITS */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_DIGITS);
case 13 /* MODE_SPREAD */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_SPREAD);
case 14 /* MODE_STOPLEVEL */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
case 15 /* MODE_LOTSIZE */ : return ::SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
case 16 /* MODE_TICKVALUE */ : return ::SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
case 17 /* MODE_TICKSIZE */ : return ::SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
case 18 /* MODE_SWAPLONG */ : return ::SymbolInfoDouble(symbol, SYMBOL_SWAP_LONG);
case 19 /* MODE_SWAPSHORT */ : return ::SymbolInfoDouble(symbol, SYMBOL_SWAP_SHORT);
case 20 /* MODE_STARTING */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_START_TIME);
case 21 /* MODE_EXPIRATION */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_EXPIRATION_TIME);
case 22 /* MODE_TRADEALLOWED */ : return (::SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_DISABLED);
case 23 /* MODE_MINLOT */ : return ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
case 24 /* MODE_LOTSTEP */ : return ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
case 25 /* MODE_MAXLOT */ : return ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
case 26 /* MODE_SWAPTYPE */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_SWAP_MODE);
case 27 /* MODE_PROFITCALCMODE */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
case 28 /* MODE_MARGINCALCMODE */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
case 29 /* MODE_MARGININIT */ : return (double)::SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL);
case 30 /* MODE_MARGINMAINTENANCE */ : return (double)::SymbolInfoDouble(symbol, SYMBOL_MARGIN_MAINTENANCE);
case 31 /* MODE_MARGINHEDGED */ : return (double)::SymbolInfoDouble(symbol, SYMBOL_MARGIN_HEDGED);
case 32 /* MODE_MARGINREQUIRED */ : {
double margin = 0.0;
if (::OrderCalcMargin(ORDER_TYPE_BUY, symbol, 1, ::SymbolInfoDouble(symbol, SYMBOL_ASK), margin))
return margin;
else
return 0.0;
}
case 33 /* MODE_FREEZELEVEL */ : return (double)::SymbolInfoInteger(symbol, SYMBOL_TRADE_FREEZE_LEVEL);
case 34 /* MODE_CLOSEBY_ALLOWED */ : return 0.0;
}
return 0.0;
}
static bool ObjectCreate(
long chart_id, string object_name, ENUM_OBJECT object_type, int sub_window,
datetime time1, double price1,
datetime time2 = 0, double price2 = 0,
datetime time3 = 0, double price3 = 0,
datetime time4 = 0, double price4 = 0,
datetime time5 = 0, double price5 = 0,
datetime time6 = 0, double price6 = 0,
datetime time7 = 0, double price7 = 0,
datetime time8 = 0, double price8 = 0,
datetime time9 = 0, double price9 = 0,
datetime time10 = 0, double price10 = 0,
datetime time11 = 0, double price11 = 0,
datetime time12 = 0, double price12 = 0,
datetime time13 = 0, double price13 = 0,
datetime time14 = 0, double price14 = 0,
datetime time15 = 0, double price15 = 0,
datetime time16 = 0, double price16 = 0,
datetime time17 = 0, double price17 = 0,
datetime time18 = 0, double price18 = 0,
datetime time19 = 0, double price19 = 0,
datetime time20 = 0, double price20 = 0,
datetime time21 = 0, double price21 = 0,
datetime time22 = 0, double price22 = 0,
datetime time23 = 0, double price23 = 0,
datetime time24 = 0, double price24 = 0,
datetime time25 = 0, double price25 = 0,
datetime time26 = 0, double price26 = 0,
datetime time27 = 0, double price27 = 0,
datetime time28 = 0, double price28 = 0,
datetime time29 = 0, double price29 = 0
) {
return (bool)::ObjectCreate(
chart_id, object_name, object_type, sub_window,
time1, price1,
time2, price2,
time3, price3,
time4, price4,
time5, price5,
time6, price6,
time7, price7,
time8, price8,
time9, price9,
time10, price10,
time11, price11,
time12, price12,
time13, price13,
time14, price14,
time15, price15,
time16, price16,
time17, price17,
time18, price18,
time19, price19,
time20, price20,
time21, price21,
time22, price22,
time23, price23,
time24, price24,
time25, price25,
time26, price26,
time27, price27,
time28, price28,
time29, price29
);
}
static bool ObjectCreate(
string object_name, ENUM_OBJECT object_type, int sub_window,
datetime time1, double price1,
datetime time2 = 0, double price2 = 0,
datetime time3 = 0, double price3 = 0
) {
return (bool)::ObjectCreate(0, object_name, object_type, sub_window, time1, price1, time2, price2, time3, price3);
}
static bool ObjectDelete(long chart_id, string object_name) {
return (bool)::ObjectDelete(chart_id, object_name);
}
static bool ObjectDelete(string object_name) {
return (bool)::ObjectDelete(0, object_name);
}
/**
* In MQL5 the names of the constants in ENUM_OBJECT_PROPERTY_* are pretty much the same as in MQL4, so when constants are used the functions below will serve
*/
static string ObjectGetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, int prop_modifier = 0) {
return ::ObjectGetString(chart_id, object_name, prop_id, prop_modifier);
}
static bool ObjectGetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, int prop_modifier, string &string_var) {
return ::ObjectGetString(chart_id, object_name, prop_id, prop_modifier, string_var);
}
/**
* These overloads are used just in case when integer value is passed to prop_id.
* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
*/
static string ObjectGetString(long chart_id, const string object_name, int prop_id, int prop_modifier = 0) {
ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
if (propID == -1) return "";
return ::ObjectGetString(chart_id, object_name, propID, prop_modifier);
}
static bool ObjectGetString(long chart_id, const string object_name, int prop_id, int prop_modifier, string &string_var) {
ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
if (propID == -1) {
string_var = "";
return true;
}
return ::ObjectGetString(chart_id, object_name, propID, prop_modifier, string_var);
}
/**
* These overloads are used just in case when integer value is passed to prop_id.
* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
*/
static bool ObjectSetDouble(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_DOUBLE prop_id, double prop_value) {
return ::ObjectSetDouble(chart_id, object_name, prop_id, prop_value);
}
static bool ObjectSetDouble(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_DOUBLE prop_id, int prop_modifier, double prop_value) {
return ::ObjectSetDouble(chart_id, object_name, prop_id, prop_modifier, prop_value);
}
static bool ObjectSetDouble(long chart_id, const string object_name, int prop_id, double prop_value) {
ENUM_OBJECT_PROPERTY_DOUBLE propID = CCBC::_ConvertEnumObjectPropertyDouble_(prop_id);
if (propID == -1) return false;
return ::ObjectSetDouble(chart_id, object_name, propID, prop_value);
}
static bool ObjectSetDouble(long chart_id, const string object_name, int prop_id, int prop_modifier, double prop_value) {
ENUM_OBJECT_PROPERTY_DOUBLE propID = CCBC::_ConvertEnumObjectPropertyDouble_(prop_id);
if (propID == -1) return false;
return ::ObjectSetDouble(chart_id, object_name, propID, prop_modifier, prop_value);
}
/**
* These overloads are used just in case when integer value is passed to prop_id.
* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
*/
static bool ObjectSetInteger(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_INTEGER prop_id, long prop_value) {
return ::ObjectSetInteger(chart_id, object_name, prop_id, prop_value);
}
static bool ObjectSetInteger(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_INTEGER prop_id, int prop_modifier, long prop_value) {
return ::ObjectSetInteger(chart_id, object_name, prop_id, prop_modifier, prop_value);
}
static bool ObjectSetInteger(long chart_id, const string object_name, int prop_id, long prop_value) {
ENUM_OBJECT_PROPERTY_INTEGER propID = CCBC::_ConvertEnumObjectPropertyInteger_(prop_id);
if (propID == -1) return false;
return ::ObjectSetInteger(chart_id, object_name, propID, prop_value);
}
static bool ObjectSetInteger(long chart_id, const string object_name, int prop_id, int prop_modifier, long prop_value) {
ENUM_OBJECT_PROPERTY_INTEGER propID = CCBC::_ConvertEnumObjectPropertyInteger_(prop_id);
if (propID == -1) return false;
return ::ObjectSetInteger(chart_id, object_name, propID, prop_modifier, prop_value);
}
/**
* These overloads are used just in case when integer value is passed to prop_id.
* It's presumed that this integer value is what represents the enumeration constants in MQL4, which representation is different in MQL5.
*/
static bool ObjectSetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, string prop_value) {
return ::ObjectSetString(chart_id, object_name, prop_id, prop_value);
}
static bool ObjectSetString(long chart_id, const string object_name, ENUM_OBJECT_PROPERTY_STRING prop_id, int prop_modifier, string prop_value) {
return ::ObjectSetString(chart_id, object_name, prop_id, prop_modifier, prop_value);
}
static bool ObjectSetString(long chart_id, const string object_name, int prop_id, string prop_value) {
ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
if (propID == -1) return true;
return ::ObjectSetString(chart_id, object_name, propID, prop_value);
}
static bool ObjectSetString(long chart_id, const string object_name, int prop_id, int prop_modifier, string prop_value) {
ENUM_OBJECT_PROPERTY_STRING propID = CCBC::_ConvertEnumObjectPropertyString_(prop_id);
if (propID == -1) return true;
return ::ObjectSetString(chart_id, object_name, propID, prop_modifier, prop_value);
}
static bool OrderClose(long ticket, double lots, double price, int slippage, color arrow_color = clrNONE) {
int positionsTotal = ::PositionsTotal();
bool found = false;
long positionID = ticket;
for (int index = positionsTotal-1; index >= 0; index--) {
ticket = (long)::PositionGetTicket(index);
if (::PositionGetInteger(POSITION_IDENTIFIER) == positionID) {
found = true;
break;
}
}
if (!found) {
if (::HistoryDealSelect(ticket)) {
long posID = ::HistoryDealGetInteger(ticket, DEAL_POSITION_ID);
for (int index = positionsTotal-1; index >= 0; index--) {
ticket = (long)::PositionGetTicket(index);
if (::PositionGetInteger(POSITION_IDENTIFIER) == posID) {
found = true;
break;
}
}
}
}
if (!found) return false;
double lots0 = ::NormalizeDouble(PositionGetDouble(POSITION_VOLUME), 5);
string symbol = ::PositionGetString(POSITION_SYMBOL);
double lotstep = ::SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
while (true) {
lots = ::MathFloor(lots/lotstep)*lotstep;
MqlTradeRequest request;
MqlTradeResult result;
::ZeroMemory(request);
::ZeroMemory(result);
request.action = TRADE_ACTION_DEAL;
request.price = price;
request.type = (::PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY ;
request.position = ::PositionGetInteger(POSITION_TICKET);
request.symbol = symbol;
request.volume = lots;
request.magic = ::PositionGetInteger(POSITION_MAGIC);
request.deviation = (ulong)slippage;
request.comment = "from #" + ::IntegerToString(ticket);
if (CCBC_TRADES::IsFillingTypeAllowed(symbol, SYMBOL_FILLING_FOK))
request.type_filling = ORDER_FILLING_FOK;
else if (CCBC_TRADES::IsFillingTypeAllowed(symbol, SYMBOL_FILLING_IOC))
request.type_filling = ORDER_FILLING_IOC;
else if (CCBC_TRADES::IsFillingTypeAllowed(symbol, ORDER_FILLING_RETURN)) // just in case
request.type_filling = ORDER_FILLING_RETURN;
int success = ::OrderSend(request, result);
if (!success || (result.retcode!=TRADE_RETCODE_DONE && result.retcode!=TRADE_RETCODE_PLACED && result.retcode!=TRADE_RETCODE_DONE_PARTIAL)) {
string errmsgpfx = "Closing trade error";
int erraction = CCBC_TRADES::CheckForTradingError(result.retcode, errmsgpfx);
switch (erraction) {
case 0: break; // no error
case 1: continue; // overcomable error
case 2: break; // fatal error
}
return false;
}
if (result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE_PARTIAL) {
if (lots0 == ::NormalizeDouble(result.volume, 5)) {
while (true) {
if (!::PositionSelectByTicket(ticket)) {
break;
}
::Sleep(10);
}
}
else if (lots0 > ::NormalizeDouble(result.volume, 5)) {
while (true) {
if (::PositionSelectByTicket(ticket) && (lots0 != ::NormalizeDouble(PositionGetDouble(POSITION_VOLUME), 5))) {
break;
}
::Sleep(10);
}
}
}
break;
}
::ResetLastError();
return true;
}
static double OrderCommission() {
if (CCBC_TRADES::LoadedType() == 1) {
::HistorySelectByPosition(CCBC::OrderTicket());
int total = ::HistoryDealsTotal();
for (int index = 0; index < total; index++) {
ulong ticket = ::HistoryDealGetTicket(index);
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);
if (entry == DEAL_ENTRY_IN) {
return ::HistoryDealGetDouble(ticket, DEAL_COMMISSION);
}
}
}
if (CCBC_TRADES::LoadedType() == 2) return 0;
if (CCBC_TRADES::LoadedType() == 3) {
::HistorySelectByPosition(CCBC::OrderTicket());
int total = ::HistoryDealsTotal();
for (int index = total -1; index >= 0; index--) {
ulong ticket = ::HistoryDealGetTicket(index);
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);
if (entry == DEAL_ENTRY_OUT) {
return ::HistoryDealGetDouble(ticket, DEAL_COMMISSION);
}
}
}
if (CCBC_TRADES::LoadedType() == 4) return 0;
return 0.0;
}
static bool OrderDelete(long ticket, color arrow_color = clrNONE) {
if (!::OrderSelect(ticket)) return false;
while (true) {
MqlTradeRequest request;
MqlTradeResult result;
MqlTradeCheckResult check_result;
::ZeroMemory(request);
::ZeroMemory(result);
::ZeroMemory(check_result);
request.action = TRADE_ACTION_REMOVE;
request.order = ticket;
if (!::OrderCheck(request,check_result)) {
::Print("OrderCheck() failed: "+(string)check_result.comment+" ("+(string)check_result.retcode+")");
return false;
}
int success = ::OrderSend(request, result);
if (!success || (result.retcode!=TRADE_RETCODE_DONE && result.retcode!=TRADE_RETCODE_PLACED && result.retcode!=TRADE_RETCODE_DONE_PARTIAL)) {
string errmsgpfx = "Closing order error";
int erraction = CCBC_TRADES::CheckForTradingError(result.retcode, errmsgpfx);
switch (erraction) {
case 0: break; // no error
case 1: continue; // overcomable error
case 2: break; // fatal error
}
CCBC::_LastError_(result.retcode);
return false;
}
if (result.retcode==TRADE_RETCODE_DONE || result.retcode==TRADE_RETCODE_PLACED || result.retcode==TRADE_RETCODE_DONE_PARTIAL) {
while (true) {
if (!::OrderSelect(ticket)) {
break;
}
::Sleep(10);
}
}
break;
}
::ResetLastError();
return true;
}
static double OrderLots() {
if (CCBC_TRADES::LoadedType() == 1) return ::PositionGetDouble(POSITION_VOLUME);
if (CCBC_TRADES::LoadedType() == 2) return ::OrderGetDouble(ORDER_VOLUME_CURRENT);
if (CCBC_TRADES::LoadedType() == 3) {
::HistorySelectByPosition(CCBC::OrderTicket());
int total = ::HistoryDealsTotal();
for (int index = total -1; index >= 0; index--) {
ulong ticket = ::HistoryDealGetTicket(index);
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);
if (entry == DEAL_ENTRY_OUT) {
return ::HistoryDealGetDouble(ticket, DEAL_VOLUME);
}
}
}
if (CCBC_TRADES::LoadedType() == 4) return ::HistoryOrderGetDouble(CCBC::OrderTicket(), ORDER_VOLUME_CURRENT);
return 0.0;
}
static long OrderMagicNumber() {
if (CCBC_TRADES::LoadedType() == 1) return (long)::PositionGetInteger(POSITION_MAGIC);
if (CCBC_TRADES::LoadedType() == 2) return (long)::OrderGetInteger(ORDER_MAGIC);
if (CCBC_TRADES::LoadedType() == 3) {
::HistorySelectByPosition(CCBC::OrderTicket());
int total = ::HistoryDealsTotal();
for (int index = total -1; index >= 0; index--) {
ulong ticket = ::HistoryDealGetTicket(index);
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);
if (entry == DEAL_ENTRY_OUT) {
return (long)::HistoryDealGetInteger(ticket, DEAL_MAGIC);
}
}
}
if (CCBC_TRADES::LoadedType() == 4) return (long)::HistoryOrderGetInteger(CCBC::OrderTicket(), ORDER_MAGIC);
return 0;
}
static double OrderOpenPrice() {
if (CCBC_TRADES::LoadedType() == 1) return ::PositionGetDouble(POSITION_PRICE_OPEN);
if (CCBC_TRADES::LoadedType() == 2) return ::OrderGetDouble(ORDER_PRICE_OPEN);
if (CCBC_TRADES::LoadedType() == 3) {
::HistorySelectByPosition(CCBC::OrderTicket());
int total = ::HistoryDealsTotal();
for (int index = 0; index < total; index++) {
ulong ticket = ::HistoryDealGetTicket(index);
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);
if (entry == DEAL_ENTRY_IN) {
return ::HistoryDealGetDouble(ticket, DEAL_PRICE);
}
}
}
if (CCBC_TRADES::LoadedType() == 4) return ::HistoryOrderGetDouble(CCBC::OrderTicket(), ORDER_PRICE_OPEN);
return 0.0;
}
static double OrderProfit() {
if (CCBC_TRADES::LoadedType() == 1) return ::PositionGetDouble(POSITION_PROFIT);
if (CCBC_TRADES::LoadedType() == 3) {
::HistorySelectByPosition(CCBC::OrderTicket());
int total = ::HistoryDealsTotal();
for (int index = total -1; index >= 0; index--) {
ulong ticket = ::HistoryDealGetTicket(index);
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)::HistoryDealGetInteger(ticket, DEAL_ENTRY);
if (entry == DEAL_ENTRY_OUT) {
return ::HistoryDealGetDouble(ticket, DEAL_PROFIT);
}
}
}
return 0.0;
}
static bool OrderSelect(long index, int select, int pool = 0) {
if (pool < 0 || pool > 1) pool = 0;
if (select != 0) select = 1;
bool selected = false;
int loadedTypeTrade = 1;
int loadedTypeOrder = 2;
CCBC::OrderTicket(0);
CCBC_TRADES::LoadedType(0);
if (select == 0) {
int totalTrades = 0;
int totalOrders = 0;
if (pool == 1) {
::HistorySelect(0, ::TimeCurrent() + 1);
totalTrades = ::HistoryDealsTotal();
totalOrders = ::HistoryOrdersTotal();
loadedTypeTrade = 3;
loadedTypeOrder = 4;
}
else {
totalTrades = ::PositionsTotal();
totalOrders = ::OrdersTotal();
loadedTypeTrade = 1;
loadedTypeOrder = 2;
}
if (totalTrades == 0 && totalOrders == 0) {
CCBC::_LastError_(ERR_INVALID_PARAMETER);
}
else {
int total = ::MathMax(totalTrades, totalOrders);
int tradeIndex = 0;
int orderIndex = 0;
int iterationIndex = 0;
while (true) {
ulong tradeTicket = 0;
ulong orderTicket = 0;
if (tradeIndex < totalTrades) {
Показано первые 50% кода (символов: 128444)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.