Small account (up to 1000 USD) indicators and algo, ea ?

Created at 16 Dec 2019, 19:33
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
TG

tgjobscv

Joined 05.12.2018

Small account (up to 1000 USD) indicators and algo, ea ?
16 Dec 2019, 19:33


Small account (up to 1000 USD) indicators and algo, ea ? 

 

BrainTrend

Errors 117.

What wrong ?

 

//#reference: ..\Indicators\BrainTrend1_Indicator.algo
//#reference: ..\Indicators\FractaldimesionEhlers_Indicator.algo
//#reference: ..\Indicators\BrainTrend1Sig_Indicator.algo
//#reference: ..\Indicators\BrainTrend2Sig_Indicator.algo
//#reference: ..\Indicators\iTrend_Indicator.algo
//#reference: ..\Indicators\BrainTrend1StopLine_Indicator.algo
//#reference: ..\Indicators\BrainTrend2StopLine_Indicator.algo
// ------------------------------------------------------------                   
// Paste this code into your cAlgo editor. 
// -----------------------------------------------------------
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using cAlgo.API.Requests;
// ---------------------------------------------------------------------------                   
// Converted from MQ4 to cAlgo with http://2calgo.com
// ---------------------------------------------------------------------------

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.FullAccess)]
    public class BrainExpert_v2_Robot : Robot
    {
        Mq4Double Mq4Init()
        {
            if (Digits == 4 || Digits == 2)
                pointvalue = Point;
            else if (Digits == 5 || Digits == 3)
                pointvalue = 10.0 * Point;
            CurrBar = iTime(Symbol.Code, TimeFrameMq4, 0);
            PrevBar = iTime(Symbol.Code, TimeFrameMq4, 1);
            return 0;
            return 0;
        }
        Mq4Double ScanTradesFunc()
        {
            Mq4Double cnt = 0;
            Mq4Double numords = 0;
            Mq4Double total = 0;
            total = OrdersTotal();
            numords = 0;

            for (cnt = 0; cnt < total; cnt++)
            {
                OrderSelect(cnt, SELECT_BY_POS);
                if (OrderSymbol() == Symbol.Code && OrderType() <= OP_SELLSTOP && OrderMagicNumber() == Magic)
                    numords++;
            }
            return numords;
            return 0;
        }
        Mq4Double ConfirmSignalFunc(Mq4Double mode, Mq4Double num)
        {
            Mq4Double fde2 = 0;
            Mq4Double fde1 = 0;
            Mq4Double lo = 0;
            Mq4Double hi = 0;
            Mq4Double loBT1 = 0;
            Mq4Double hiBT1 = 0;
            Mq4Double i = 0;
            Mq4Double result = 0;
            result = 0;


            for (i = num; i >= 1; i--)
            {
                hiBT1 = iCustom<BrainTrend1_Indicator>(Symbol.Code, 0, "BrainTrend1", NumBars, 1, i);
                loBT1 = iCustom<BrainTrend1_Indicator>(Symbol.Code, 0, "BrainTrend1", NumBars, 0, i);
                hi = High[i];
                lo = Low[i];
                fde1 = iCustom<FractaldimesionEhlers_Indicator>(NULL, 0, "Fractal dimesion Ehlers", FDSize, FDPrice, FDTreshold, 2, i);
                fde2 = iCustom<FractaldimesionEhlers_Indicator>(NULL, 0, "Fractal dimesion Ehlers", FDSize, FDPrice, FDTreshold, 2, i + 1);
                if (mode == 1 && result >= 0 && fde1 < fde2 && (hiBT1 != lo && loBT1 != hi))
                {
                    result += 1;
                }

                if (mode == 2 && result <= 0 && fde1 < fde2 && (hiBT1 != hi && loBT1 != lo))
                {
                    result -= 1;
                }

            }

            return result;
            return 0;
        }
        Mq4Double TradeSignalFunc()
        {
            Mq4Double iTrend = 0;
            Mq4Double iTrend2 = 0;
            Mq4Double iTrend1 = 0;
            Mq4Double Power_Period = 0;
            Mq4Double Bands_Deviation = 0;
            Mq4Double Bands_Period = 0;
            Mq4Double Price_Type_0_3 = 0;
            Mq4Double Power_Price_0_6 = 0;
            Mq4Double Bands_Mode_0_2 = 0;
            Mq4Double Stoch = 0;
            Mq4Double StoSig = 0;
            Mq4Double StoMain = 0;
            Mq4Double pSAR = 0;
            Mq4Double SAR = 0;
            Mq4Double sellBT2 = 0;
            Mq4Double sellBT1 = 0;
            Mq4Double buyBT2 = 0;
            Mq4Double buyBT1 = 0;

            buyBT1 = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend1Sig", NumBars, 0, 0, 1, 1);
            buyBT2 = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend2Sig", NumBars, 0, 1);

            sellBT1 = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend1Sig", NumBars, 0, 0, 0, 1);
            sellBT2 = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend2Sig", NumBars, 1, 1);

            if (Use_pSAR > 0)
            {
                SAR = iSAR(NULL, TimeFrameMq4, pSAR_Step, pSAR_Maximum, 1);
                if (SAR < Close[1])
                    pSAR = 1;
                else if (SAR > Close[1])
                    pSAR = -1;
            }

            if (Use_Stoch > 0)
            {
                StoMain = iStochastic(NULL, TimeFrameMq4, Kperiod, Dperiod, slowing, MODE_SMA, 0, MODE_MAIN, 1);
                StoSig = iStochastic(NULL, TimeFrameMq4, Kperiod, Dperiod, slowing, MODE_SMA, 0, MODE_SIGNAL, 1);
                if (StoMain > StoSig && StoMain < DnLevel && StoSig < DnLevel)
                    Stoch = 1;
                else if (StoMain < StoSig && StoMain > UpLevel && StoSig > UpLevel)
                    Stoch = -1;
            }

            if (Use_iTrend > 0)
            {
                Bands_Mode_0_2 = 0;
                Power_Price_0_6 = 0;
                Price_Type_0_3 = 0;
                Bands_Period = 20;
                Bands_Deviation = 2;
                Power_Period = 13;

                iTrend1 = iCustom<iTrend_Indicator>(Symbol.Code, TimeFrameMq4, "iTrend", Bands_Mode_0_2, Power_Price_0_6, Price_Type_0_3, Bands_Period, Bands_Deviation, Power_Period, NumBars,
                0, 1);
                iTrend2 = iCustom<iTrend_Indicator>(Symbol.Code, TimeFrameMq4, "iTrend", Bands_Mode_0_2, Power_Price_0_6, Price_Type_0_3, Bands_Period, Bands_Deviation, Power_Period, NumBars,
                1, 1);

                if (iTrend1 > 0 && iTrend2 < 0)
                    iTrend = 1;
                else if (iTrend2 > 0 && iTrend1 < 0)
                    iTrend = -1;
            }
            if (TimeHour(CurTime()) >= SessionStart && TimeHour(CurTime()) <= SessionEnd)
            {
                if (buyBT1 > 0 && sellBT1 <= 0 && buyBT2 > 0 && sellBT2 <= 0 && ConfirmSignalFunc(1, ConfirmBars) == ConfirmBars && (pSAR == 1 || Use_pSAR == 0) && (Stoch == 1 || Use_Stoch == 0) && (iTrend == 1 || Use_iTrend == 0))
                    return 1;

                if (buyBT1 <= 0 && sellBT1 > 0 && buyBT2 <= 0 && sellBT2 > 0 && ConfirmSignalFunc(2, ConfirmBars) == -ConfirmBars && (pSAR == -1 || Use_pSAR == 0) && (Stoch == -1 || Use_Stoch == 0) && (iTrend == -1 || Use_iTrend == 0))
                    return -1;
            }
            return 0;
        }
        Mq4Double MoneyManagementFunc(Mq4Double flag, Mq4Double Lots, Mq4Double risk, Mq4Double maxloss)
        {
            Lotsi = Lots;

            if (flag)
                Lotsi = Lots * NormalizeDouble(Lots * AccountFreeMargin() * risk / maxloss, 1);

            if (Lotsi < 1)
                Lotsi = 0.01;

            return Lotsi;
            return 0;
        }
        void TrailStopFunc()
        {
            Mq4Double SellStop = 0;
            Mq4Double k = 0;
            Mq4Double BuyStop = 0;
            Mq4Double mode = 0;
            Mq4Double cnt = 0;
            Mq4Double Gain = 0;
            Mq4Double result = false;
            Mq4Double error = 0;

            result = false;
            Gain = 0;

            for (cnt = 0; cnt < OrdersTotal(); cnt++)
            {
                OrderSelect(cnt, SELECT_BY_POS);
                mode = OrderType();
                if (OrderSymbol() == Symbol.Code && OrderMagicNumber() == Magic)
                {
                    if (mode == OP_BUY)
                    {
                        if (TrailStopMode == 1)
                            BuyStop = NormalizeDouble(iCustom<BrainTrend1StopLine_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend1StopLine", NumBars, 1, 1), Digits);
                        if (TrailStopMode == 2)
                            BuyStop = NormalizeDouble(iCustom<BrainTrend2StopLine_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend2StopLine", NumBars, 0, 0, 1), Digits);


                        if (BreakEven > 0 && BEvent == 0)
                        {
                            Gain = (MarketInfo(Symbol.Code, MODE_BID) - OrderOpenPrice()) / pointvalue;
                            if (Gain >= BreakEven && OrderStopLoss() <= OrderOpenPrice() + 1 * pointvalue)
                            {
                                BuyStop = NormalizeDouble(OrderOpenPrice() + 1 * pointvalue, Digits);
                                BEvent = 1;
                            }
                        }

                        if (BuyStop > NormalizeDouble(OrderStopLoss(), Digits))
                        {
                            for (k = 0; k < TriesNum; k++)
                            {
                                result = OrderModify(OrderTicket(), OrderOpenPrice(), BuyStop, OrderTakeProfit(), 0, Lime);
                                error = GetLastError();
                                if (error == 0)
                                    break;
                                else
                                {
                                    Sleep(5000);
                                    RefreshRates();
                                    continue;
                                }
                            }
                        }
                    }
                    if (mode == OP_SELL)
                    {
                        if (TrailStopMode == 1)
                            SellStop = NormalizeDouble(iCustom<BrainTrend1StopLine_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend1StopLine", NumBars, 0, 1), Digits);
                        if (TrailStopMode == 2)
                            SellStop = NormalizeDouble(iCustom<BrainTrend2StopLine_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend2StopLine", NumBars, 0, 1, 1), Digits);

                        if (BreakEven > 0 && BEvent == 0)
                        {
                            Gain = (OrderOpenPrice() - MarketInfo(Symbol.Code, MODE_ASK)) / pointvalue;
                            if (Gain >= BreakEven && OrderStopLoss() >= OrderOpenPrice() - 1 * pointvalue)
                            {
                                SellStop = NormalizeDouble(OrderOpenPrice() - 1 * pointvalue, Digits);
                                BEvent = -1;
                            }
                        }

                        if (SellStop < NormalizeDouble(OrderStopLoss(), Digits) && SellStop > 0)
                        {
                            for (k = 0; k < TriesNum; k++)
                            {
                                result = OrderModify(OrderTicket(), OrderOpenPrice(), SellStop, OrderTakeProfit(), 0, Orange);
                                error = GetLastError();
                                if (error == 0)
                                    break;
                                else
                                {
                                    Sleep(5000);
                                    RefreshRates();
                                    continue;
                                }
                            }
                        }
                    }
                }
            }
            return;
        }
        void SellOrdOpenFunc()
        {
            Mq4Double ticket = 0;
            Mq4Double SellProfit = 0;
            Mq4Double SellStop = 0;
            Mq4Double Mode = 0;
            Mq4Double StopPrice = 0;
            Mq4Double SellPrice = 0;
            SellPrice = Bid;
            StopPrice = Bid;
            Mode = OP_SELL;

            if (StopLossMode == 1)
                SellStop = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend1Sig", NumBars, 0, 0, 0, 1);
            else if (StopLossMode == 2)
                SellStop = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend2Sig", NumBars, 1, 1);
            else
                SellStop = 0;

            if (TakeProfit > 0)
                SellProfit = SellPrice - TakeProfit * pointvalue;
            else
                SellProfit = 0;

            ticket = OrderSend(Symbol.Code, Mode, MoneyManagementFunc(MM, Lots, MMRisk, MaxLoss), NormalizeDouble(SellPrice, Digits), Slippage, NormalizeDouble(SellStop, Digits), NormalizeDouble(SellProfit, Digits), Expert_Name + " SELL", Magic, 0,
            Red);

            if (ticket > 0)
            {
                if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
                {
                    OrderBar = iBars(OrderSymbol(), TimeFrameMq4);
                    Mq4Print("SELL order opened : ", OrderOpenPrice());
                    BEvent = 0;
                    if (SignalMail)
                        SendMail("[Signal Alert]", "[" + Symbol.Code + "] " + DoubleToStr(Bid, Digits) + " Open Sell");
                }
            }
            else if (GetLastError() > 0)
                Mq4Print("SELL: OrderSend failed with error #", GetLastError());

            return;
            return;
        }
        void BuyOrdOpenFunc()
        {
            Mq4Double ticket = 0;
            Mq4Double BuyProfit = 0;
            Mq4Double BuyStop = 0;
            Mq4Double Mode = 0;
            Mq4Double StopPrice = 0;
            Mq4Double BuyPrice = 0;
            BuyPrice = Ask;
            StopPrice = Ask;
            Mode = OP_BUY;

            if (StopLossMode == 1)
                BuyStop = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend1Sig", NumBars, 0, 0, 1, 1);
            else if (StopLossMode == 2)
                BuyStop = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code, TimeFrameMq4, "BrainTrend2Sig", NumBars, 0, 1);
            else
                BuyStop = 0;

            if (TakeProfit > 0)
                BuyProfit = BuyPrice + TakeProfit * pointvalue;
            else
                BuyProfit = 0;

            ticket = OrderSend(Symbol.Code, Mode, MoneyManagementFunc(MM, Lots, MMRisk, MaxLoss), NormalizeDouble(BuyPrice, Digits), Slippage, NormalizeDouble(BuyStop, Digits), NormalizeDouble(BuyProfit, Digits), Expert_Name + " BUY", Magic, 0,
            Blue);

            if (ticket > 0)
            {
                if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
                {
                    OrderBar = iBars(OrderSymbol(), TimeFrameMq4);
                    Mq4Print("BUY order opened : ", OrderOpenPrice());
                    BEvent = 0;
                    if (SignalMail)
                        SendMail("[Signal Alert]", "[" + Symbol.Code + "] " + DoubleToStr(Ask, Digits) + " Open Buy");
                }
            }
            else if (GetLastError() > 0)
                Mq4Print("BUY : OrderSend failed with error #", GetLastError());

            return;
            return;
        }
        void CloseOrderFunc(Mq4Double mode)
        {
            Mq4Double i = 0;
            Mq4Double total = 0;
            Mq4Double result = false;
            result = false;
            total = OrdersTotal();

            for (i = 0; i <= OrdersTotal(); i++)
            {
                OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
                if (OrderMagicNumber() == Magic && OrderSymbol() == Symbol.Code)
                {
                    if ((mode == 0 || mode == 1) && OrderType() == OP_BUY)
                        result = CloseAtMarketFunc(OrderTicket(), OrderLots(), Aqua);
                    if ((mode == 0 || mode == 2) && OrderType() == OP_SELL)
                        result = CloseAtMarketFunc(OrderTicket(), OrderLots(), Pink);
                }
            }
            return;
        }
        Mq4Double CloseAtMarketFunc(Mq4Double ticket, Mq4Double lot, Mq4Double clr)
        {
            Mq4Double tries = 0;
            Mq4Double ntr = 0;
            Mq4Double result = false;
            result = false;


            tries = 0;
            while (!result && tries < TriesNum)
            {
                ntr = 0;

                RefreshRates();
                result = OrderClose(ticket, lot, OrderClosePrice(), Slippage, clr);
                tries++;
            }
            if (!result)
                Mq4Print("Error closing order : ", ErrorDescription(GetLastError()));
            return result;
            return true;
        }
        Mq4Double deinitFunc()
        {
            return 0;
            return 0;
        }
        Mq4Double Mq4Start()
        {
            if (iBars(Symbol.Code, TimeFrameMq4) < 100 || IsTradeAllowed() == false)
                return 0;

            if (AccountFreeMargin() < 1000 * MoneyManagementFunc(MM, Lots, MMRisk, MaxLoss))
            {
                Mq4Print("We have no money. Free Margin = ", AccountFreeMargin());
                return 0;
            }
            CurrBar = iTime(Symbol.Code, TimeFrameMq4, 0);


            if (CurrBar != PrevBar)
            {
                if (ScanTradesFunc() > 0)
                {
                    if (TradeSignalFunc() > 0)
                        CloseOrderFunc(2);
                    if (TradeSignalFunc() < 0)
                        CloseOrderFunc(1);
                }

                if (ScanTradesFunc() == 0)
                {
                    if (TradeSignalFunc() > 0)
                        BuyOrdOpenFunc();
                    if (TradeSignalFunc() < 0)
                        SellOrdOpenFunc();
                }
            }
            else if (ScanTradesFunc() > 0)
            {
                if (BreakEven > 0 || TrailStopMode > 0)
                    TrailStopFunc();
            }
            PrevBar = CurrBar;

            return 0;
            return 0;
        }

//{
        [Parameter("Email from", DefaultValue = "your_email@gmail.com")]
        public string EmailAddressFrom { get; set; }

        [Parameter("Email to", DefaultValue = "your_email@gmail.com")]
        public string EmailAddressTo { get; set; }
//}
        [Parameter("Expert_Name", DefaultValue = "BrainExpert_v2")]
        public string Expert_Name_parameter { get; set; }
        bool _Expert_NameGot;
        Mq4String Expert_Name_backfield;
        Mq4String Expert_Name
        {
            get
            {
                if (!_Expert_NameGot)
                    Expert_Name_backfield = Expert_Name_parameter;
                return Expert_Name_backfield;
            }
            set { Expert_Name_backfield = value; }
        }

        [Parameter("Magic", DefaultValue = 52000)]
        public int Magic_parameter { get; set; }
        bool _MagicGot;
        Mq4Double Magic_backfield;
        Mq4Double Magic
        {
            get
            {
                if (!_MagicGot)
                    Magic_backfield = Magic_parameter;
                return Magic_backfield;
            }
            set { Magic_backfield = value; }
        }

        [Parameter("Slippage", DefaultValue = 3)]
        public int Slippage_parameter { get; set; }
        bool _SlippageGot;
        Mq4Double Slippage_backfield;
        Mq4Double Slippage
        {
            get
            {
                if (!_SlippageGot)
                    Slippage_backfield = Slippage_parameter;
                return Slippage_backfield;
            }
            set { Slippage_backfield = value; }
        }

        [Parameter("Main_data", DefaultValue = " TradeMq4 Volume & TradeMq4 Method")]
        public string Main_data_parameter { get; set; }
        bool _Main_dataGot;
        Mq4String Main_data_backfield;
        Mq4String Main_data
        {
            get
            {
                if (!_Main_dataGot)
                    Main_data_backfield = Main_data_parameter;
                return Main_data_backfield;
            }
            set { Main_data_backfield = value; }
        }

        [Parameter("Lots", DefaultValue = 0.01)]
        public double Lots_parameter { get; set; }
        bool _LotsGot;
        Mq4Double Lots_backfield;
        Mq4Double Lots
        {
            get
            {
                if (!_LotsGot)
                    Lots_backfield = Lots_parameter;
                return Lots_backfield;
            }
            set { Lots_backfield = value; }
        }

        [Parameter("TakeProfit", DefaultValue = 0)]
        public double TakeProfit_parameter { get; set; }
        bool _TakeProfitGot;
        Mq4Double TakeProfit_backfield;
        Mq4Double TakeProfit
        {
            get
            {
                if (!_TakeProfitGot)
                    TakeProfit_backfield = TakeProfit_parameter;
                return TakeProfit_backfield;
            }
            set { TakeProfit_backfield = value; }
        }

        [Parameter("StopLossMode", DefaultValue = 2)]
        public int StopLossMode_parameter { get; set; }
        bool _StopLossModeGot;
        Mq4Double StopLossMode_backfield;
        Mq4Double StopLossMode
        {
            get
            {
                if (!_StopLossModeGot)
                    StopLossMode_backfield = StopLossMode_parameter;
                return StopLossMode_backfield;
            }
            set { StopLossMode_backfield = value; }
        }

        [Parameter("TrailStopMode", DefaultValue = 2)]
        public int TrailStopMode_parameter { get; set; }
        bool _TrailStopModeGot;
        Mq4Double TrailStopMode_backfield;
        Mq4Double TrailStopMode
        {
            get
            {
                if (!_TrailStopModeGot)
                    TrailStopMode_backfield = TrailStopMode_parameter;
                return TrailStopMode_backfield;
            }
            set { TrailStopMode_backfield = value; }
        }

        [Parameter("BreakEven", DefaultValue = 0)]
        public double BreakEven_parameter { get; set; }
        bool _BreakEvenGot;
        Mq4Double BreakEven_backfield;
        Mq4Double BreakEven
        {
            get
            {
                if (!_BreakEvenGot)
                    BreakEven_backfield = BreakEven_parameter;
                return BreakEven_backfield;
            }
            set { BreakEven_backfield = value; }
        }

        [Parameter("SessionStart", DefaultValue = 0)]
        public int SessionStart_parameter { get; set; }
        bool _SessionStartGot;
        Mq4Double SessionStart_backfield;
        Mq4Double SessionStart
        {
            get
            {
                if (!_SessionStartGot)
                    SessionStart_backfield = SessionStart_parameter;
                return SessionStart_backfield;
            }
            set { SessionStart_backfield = value; }
        }

        [Parameter("SessionEnd", DefaultValue = 24)]
        public int SessionEnd_parameter { get; set; }
        bool _SessionEndGot;
        Mq4Double SessionEnd_backfield;
        Mq4Double SessionEnd
        {
            get
            {
                if (!_SessionEndGot)
                    SessionEnd_backfield = SessionEnd_parameter;
                return SessionEnd_backfield;
            }
            set { SessionEnd_backfield = value; }
        }

        [Parameter("SignalMail", DefaultValue = false)]
        public bool SignalMail_parameter { get; set; }
        bool _SignalMailGot;
        Mq4Double SignalMail_backfield;
        Mq4Double SignalMail
        {
            get
            {
                if (!_SignalMailGot)
                    SignalMail_backfield = SignalMail_parameter;
                return SignalMail_backfield;
            }
            set { SignalMail_backfield = value; }
        }

        [Parameter("Inputs", DefaultValue = " BrainTrend parameters ")]
        public string Inputs_parameter { get; set; }
        bool _InputsGot;
        Mq4String Inputs_backfield;
        Mq4String Inputs
        {
            get
            {
                if (!_InputsGot)
                    Inputs_backfield = Inputs_parameter;
                return Inputs_backfield;
            }
            set { Inputs_backfield = value; }
        }

        [Parameter("TimeFrameMq4", DefaultValue = 60)]
        public int TimeFrameMq4_parameter { get; set; }
        bool _TimeFrameMq4Got;
        Mq4Double TimeFrameMq4_backfield;
        Mq4Double TimeFrameMq4
        {
            get
            {
                if (!_TimeFrameMq4Got)
                    TimeFrameMq4_backfield = TimeFrameMq4_parameter;
                return TimeFrameMq4_backfield;
            }
            set { TimeFrameMq4_backfield = value; }
        }

        [Parameter("NumBars", DefaultValue = 500)]
        public int NumBars_parameter { get; set; }
        bool _NumBarsGot;
        Mq4Double NumBars_backfield;
        Mq4Double NumBars
        {
            get
            {
                if (!_NumBarsGot)
                    NumBars_backfield = NumBars_parameter;
                return NumBars_backfield;
            }
            set { NumBars_backfield = value; }
        }

        [Parameter("ConfirmBars", DefaultValue = 3)]
        public int ConfirmBars_parameter { get; set; }
        bool _ConfirmBarsGot;
        Mq4Double ConfirmBars_backfield;
        Mq4Double ConfirmBars
        {
            get
            {
                if (!_ConfirmBarsGot)
                    ConfirmBars_backfield = ConfirmBars_parameter;
                return ConfirmBars_backfield;
            }
            set { ConfirmBars_backfield = value; }
        }

        [Parameter("Use_pSAR", DefaultValue = 0)]
        public double Use_pSAR_parameter { get; set; }
        bool _Use_pSARGot;
        Mq4Double Use_pSAR_backfield;
        Mq4Double Use_pSAR
        {
            get
            {
                if (!_Use_pSARGot)
                    Use_pSAR_backfield = Use_pSAR_parameter;
                return Use_pSAR_backfield;
            }
            set { Use_pSAR_backfield = value; }
        }

        [Parameter("pSAR_Step", DefaultValue = 0.02)]
        public double pSAR_Step_parameter { get; set; }
        bool _pSAR_StepGot;
        Mq4Double pSAR_Step_backfield;
        Mq4Double pSAR_Step
        {
            get
            {
                if (!_pSAR_StepGot)
                    pSAR_Step_backfield = pSAR_Step_parameter;
                return pSAR_Step_backfield;
            }
            set { pSAR_Step_backfield = value; }
        }

        [Parameter("pSAR_Maximum", DefaultValue = 0.2)]
        public double pSAR_Maximum_parameter { get; set; }
        bool _pSAR_MaximumGot;
        Mq4Double pSAR_Maximum_backfield;
        Mq4Double pSAR_Maximum
        {
            get
            {
                if (!_pSAR_MaximumGot)
                    pSAR_Maximum_backfield = pSAR_Maximum_parameter;
                return pSAR_Maximum_backfield;
            }
            set { pSAR_Maximum_backfield = value; }
        }

        [Parameter("Use_Stoch", DefaultValue = 0)]
        public double Use_Stoch_parameter { get; set; }
        bool _Use_StochGot;
        Mq4Double Use_Stoch_backfield;
        Mq4Double Use_Stoch
        {
            get
            {
                if (!_Use_StochGot)
                    Use_Stoch_backfield = Use_Stoch_parameter;
                return Use_Stoch_backfield;
            }
            set { Use_Stoch_backfield = value; }
        }

        [Parameter("Kperiod", DefaultValue = 14)]
        public int Kperiod_parameter { get; set; }
        bool _KperiodGot;
        Mq4Double Kperiod_backfield;
        Mq4Double Kperiod
        {
            get
            {
                if (!_KperiodGot)
                    Kperiod_backfield = Kperiod_parameter;
                return Kperiod_backfield;
            }
            set { Kperiod_backfield = value; }
        }

        [Parameter("Dperiod", DefaultValue = 5)]
        public int Dperiod_parameter { get; set; }
        bool _DperiodGot;
        Mq4Double Dperiod_backfield;
        Mq4Double Dperiod
        {
            get
            {
                if (!_DperiodGot)
                    Dperiod_backfield = Dperiod_parameter;
                return Dperiod_backfield;
            }
            set { Dperiod_backfield = value; }
        }

        [Parameter("slowing", DefaultValue = 5)]
        public int slowing_parameter { get; set; }
        bool _slowingGot;
        Mq4Double slowing_backfield;
        Mq4Double slowing
        {
            get
            {
                if (!_slowingGot)
                    slowing_backfield = slowing_parameter;
                return slowing_backfield;
            }
            set { slowing_backfield = value; }
        }

        [Parameter("UpLevel", DefaultValue = 75)]
        public double UpLevel_parameter { get; set; }
        bool _UpLevelGot;
        Mq4Double UpLevel_backfield;
        Mq4Double UpLevel
        {
            get
            {
                if (!_UpLevelGot)
                    UpLevel_backfield = UpLevel_parameter;
                return UpLevel_backfield;
            }
            set { UpLevel_backfield = value; }
        }

        [Parameter("DnLevel", DefaultValue = 25)]
        public double DnLevel_parameter { get; set; }
        bool _DnLevelGot;
        Mq4Double DnLevel_backfield;
        Mq4Double DnLevel
        {
            get
            {
                if (!_DnLevelGot)
                    DnLevel_backfield = DnLevel_parameter;
                return DnLevel_backfield;
            }
            set { DnLevel_backfield = value; }
        }

        [Parameter("Use_iTrend", DefaultValue = 0)]
        public double Use_iTrend_parameter { get; set; }
        bool _Use_iTrendGot;
        Mq4Double Use_iTrend_backfield;
        Mq4Double Use_iTrend
        {
            get
            {
                if (!_Use_iTrendGot)
                    Use_iTrend_backfield = Use_iTrend_parameter;
                return Use_iTrend_backfield;
            }
            set { Use_iTrend_backfield = value; }
        }

        [Parameter("FDSize", DefaultValue = 30)]
        public int FDSize_parameter { get; set; }
        bool _FDSizeGot;
        Mq4Double FDSize_backfield;
        Mq4Double FDSize
        {
            get
            {
                if (!_FDSizeGot)
                    FDSize_backfield = FDSize_parameter;
                return FDSize_backfield;
            }
            set { FDSize_backfield = value; }
        }

        [Parameter("FDPrice", DefaultValue = PRICE_MEDIAN)]
        public int FDPrice_parameter { get; set; }
        bool _FDPriceGot;
        Mq4Double FDPrice_backfield;
        Mq4Double FDPrice
        {
            get
            {
                if (!_FDPriceGot)
                    FDPrice_backfield = FDPrice_parameter;
                return FDPrice_backfield;
            }
            set { FDPrice_backfield = value; }
        }

        [Parameter("FDTreshold", DefaultValue = 1.5)]
        public double FDTreshold_parameter { get; set; }
        bool _FDTresholdGot;
        Mq4Double FDTreshold_backfield;
        Mq4Double FDTreshold
        {
            get
            {
                if (!_FDTresholdGot)
                    FDTreshold_backfield = FDTreshold_parameter;
                return FDTreshold_backfield;
            }
            set { FDTreshold_backfield = value; }
        }

        [Parameter("MM_inputs", DefaultValue = " MoneyManagement by L.Williams ")]
        public string MM_inputs_parameter { get; set; }
        bool _MM_inputsGot;
        Mq4String MM_inputs_backfield;
        Mq4String MM_inputs
        {
            get
            {
                if (!_MM_inputsGot)
                    MM_inputs_backfield = MM_inputs_parameter;
                return MM_inputs_backfield;
            }
            set { MM_inputs_backfield = value; }
        }

        [Parameter("MM", DefaultValue = false)]
        public bool MM_parameter { get; set; }
        bool _MMGot;
        Mq4Double MM_backfield;
        Mq4Double MM
        {
            get
            {
                if (!_MMGot)
                    MM_backfield = MM_parameter;
                return MM_backfield;
            }
            set { MM_backfield = value; }
        }

        [Parameter("MMRisk", DefaultValue = 0.15)]
        public double MMRisk_parameter { get; set; }
        bool _MMRiskGot;
        Mq4Double MMRisk_backfield;
        Mq4Double MMRisk
        {
            get
            {
                if (!_MMRiskGot)
                    MMRisk_backfield = MMRisk_parameter;
                return MMRisk_backfield;
            }
            set { MMRisk_backfield = value; }
        }

        [Parameter("MaxLoss", DefaultValue = 1000)]
        public double MaxLoss_parameter { get; set; }
        bool _MaxLossGot;
        Mq4Double MaxLoss_backfield;
        Mq4Double MaxLoss
        {
            get
            {
                if (!_MaxLossGot)
                    MaxLoss_backfield = MaxLoss_parameter;
                return MaxLoss_backfield;
            }
            set { MaxLoss_backfield = value; }
        }





        Mq4Double pointvalue = 1;
        Mq4Double PrevBar;
        Mq4Double CurrBar;
        Mq4Double TriesNum = 5;
        Mq4Double BEvent = 0;
        Mq4Double Lotsi;
        Mq4Double OrderBar = 0;

        int indicator_buffers = 0;


        Mq4Double indicator_width1 = 1;
        Mq4Double indicator_width2 = 1;
        Mq4Double indicator_width3 = 1;
        Mq4Double indicator_width4 = 1;
        Mq4Double indicator_width5 = 1;
        Mq4Double indicator_width6 = 1;
        Mq4Double indicator_width7 = 1;
        Mq4Double indicator_width8 = 1;






        List<Mq4OutputDataSeries> AllBuffers = new List<Mq4OutputDataSeries>();
        public List<DataSeries> AllOutputDataSeries = new List<DataSeries>();

        protected override void OnStart()
        {


            CommonInitialize();


            try
            {
                Mq4Init();
            } catch (Exception e)
            {

            }
        }

        protected override void OnTick()
        {
            var index = MarketSeries.Close.Count - 1;


            try
            {
                Mq4Start();
            } catch (Exception e)
            {

            }
        }

        private bool IsLastBar
        {
            get { return true; }
        }
        private bool IsTradeAllowed()
        {
            return true;
        }

        void Sleep(Mq4Double milliseconds)
        {
            if (!IsBacktesting)
                Thread.Sleep(milliseconds);
        }
        int _currentIndex;
        CachedStandardIndicators _cachedStandardIndicators;
        Mq4ChartObjects _mq4ChartObjects;
        Mq4ArrayToDataSeriesConverterFactory _mq4ArrayToDataSeriesConverterFactory;
        Mq4MarketDataSeries Open;
        Mq4MarketDataSeries High;
        Mq4MarketDataSeries Low;
        Mq4MarketDataSeries Close;
        Mq4MarketDataSeries Median;
        Mq4MarketDataSeries Volume;
        Mq4TimeSeries Time;

        private void CommonInitialize()
        {
            Open = new Mq4MarketDataSeries(MarketSeries.Open);
            High = new Mq4MarketDataSeries(MarketSeries.High);
            Low = new Mq4MarketDataSeries(MarketSeries.Low);
            Close = new Mq4MarketDataSeries(MarketSeries.Close);
            Volume = new Mq4MarketDataSeries(MarketSeries.TickVolume);
            Median = new Mq4MarketDataSeries(MarketSeries.Median);
            Time = new Mq4TimeSeries(MarketSeries.OpenTime);

            _cachedStandardIndicators = new CachedStandardIndicators(Indicators);
            _mq4ChartObjects = new Mq4ChartObjects(ChartObjects, MarketSeries.OpenTime);
            _mq4ArrayToDataSeriesConverterFactory = new Mq4ArrayToDataSeriesConverterFactory(() => CreateDataSeries());
        }
        private int Bars
        {
            get { return MarketSeries.Close.Count; }
        }
        private int Digits
        {
            get
            {
                if (Symbol == null)
                    return 0;
                return Symbol.Digits;
            }
        }

        Mq4Double Point
        {
            get
            {
                if (Symbol == null)
                    return 1E-05;

                return Symbol.TickSize;
            }
        }
        private int Period()
        {
            if (TimeFrame == TimeFrame.Minute)
                return 1;
            if (TimeFrame == TimeFrame.Minute2)
                return 2;
            if (TimeFrame == TimeFrame.Minute3)
                return 3;
            if (TimeFrame == TimeFrame.Minute4)
                return 4;
            if (TimeFrame == TimeFrame.Minute5)
                return 5;
            if (TimeFrame == TimeFrame.Minute10)
                return 10;
            if (TimeFrame == TimeFrame.Minute15)
                return 15;
            if (TimeFrame == TimeFrame.Minute30)
                return 30;
            if (TimeFrame == TimeFrame.Hour)
                return 60;
            if (TimeFrame == TimeFrame.Hour4)
                return 240;
            if (TimeFrame == TimeFrame.Hour12)
                return 720;
            if (TimeFrame == TimeFrame.Daily)
                return 1440;
            if (TimeFrame == TimeFrame.Weekly)
                return 10080;

            return 43200;
        }

        public TimeFrame PeriodToTimeFrame(int period)
        {
            switch (period)
            {
                case 0:
                    return TimeFrame;
                case 1:
                    return TimeFrame.Minute;
                case 2:
                    return TimeFrame.Minute2;
                case 3:
                    return TimeFrame.Minute3;
                case 4:
                    return TimeFrame.Minute4;
                case 5:
                    return TimeFrame.Minute5;
                case 10:
                    return TimeFrame.Minute10;
                case 15:
                    return TimeFrame.Minute15;
                case 30:
                    return TimeFrame.Minute30;
                case 60:
                    return TimeFrame.Hour;
                case 240:
                    return TimeFrame.Hour4;
                case 720:
                    return TimeFrame.Hour12;
                case 1440:
                    return TimeFrame.Daily;
                case 10080:
                    return TimeFrame.Weekly;
                case 43200:
                    return TimeFrame.Monthly;
                default:
                    throw new NotSupportedException(string.Format("TimeFrame {0} minutes isn't supported by cAlgo", period));
            }
        }



















        Mq4String DoubleToStr(double value, int digits)
        {
            return value.ToString("F" + digits);
        }

        Mq4Double NormalizeDouble(double value, int digits)
        {
            return Math.Round(value, digits);
        }





        int ToMq4ErrorCode(ErrorCode errorCode)
        {
            switch (errorCode)
            {
                case ErrorCode.BadVolume:
                    return ERR_INVALID_TRADE_VOLUME;
                case ErrorCode.NoMoney:
                    return ERR_NOT_ENOUGH_MONEY;
                case ErrorCode.MarketClosed:
                    return ERR_MARKET_CLOSED;
                case ErrorCode.Disconnected:
                    return ERR_NO_CONNECTION;
                case ErrorCode.Timeout:
                    return ERR_TRADE_TIMEOUT;
                default:
                    return ERR_COMMON_ERROR;
            }
        }



        Mq4Double RefreshRates()
        {
            RefreshData();
            return true;
        }













        int Hour()
        {
            return Server.Time.Hour;
        }




        int TimeCurrent()
        {
            return Mq4TimeSeries.ToInteger(Server.Time);
        }

        int CurTime()
        {
            return TimeCurrent();
        }




        int TimeHour(int time)
        {
            return Mq4TimeSeries.ToDateTime(time).Hour;
        }








        const string NotSupportedMaShift = "Converter supports only ma_shift = 0";










        int iTime(Mq4String symbol, int timeframe, int shift)
        {
            var timeSeries = GetSeries(symbol, timeframe).OpenTime;
            if (shift >= 0 && shift < timeSeries.Count)
                return Mq4TimeSeries.ToInteger(timeSeries.Last(shift));
            return 0;
        }


        int iBars(Mq4String symbol, int timeframe)
        {
            return GetSeries(symbol, timeframe).Close.Count;
        }

        Mq4Double MarketInfo(Mq4String symbol, int type)
        {
            var symbolObject = GetSymbol(symbol);
            switch (type)
            {
                case MODE_LOW:
                    return GetSeries(symbol, PERIOD_D1).Low.LastValue;
                case MODE_HIGH:
                    return GetSeries(symbol, PERIOD_D1).High.LastValue;
                case MODE_DIGITS:
                    return symbolObject.Digits;
                case MODE_TIME:
                    return TimeCurrent();
                case MODE_ASK:
                    return symbolObject.Ask;
                case MODE_BID:
                    return symbolObject.Bid;
                case MODE_SPREAD:
                    return symbolObject.Spread / symbolObject.TickSize;
                case MODE_PROFITCALCMODE:
                    return 0;
                case MODE_FREEZELEVEL:
                    return 0;
                case MODE_TRADEALLOWED:
                    return 1;
                case MODE_POINT:
                    return symbolObject.TickSize;
                case MODE_TICKSIZE:
                    return symbolObject.TickSize;
                case MODE_SWAPTYPE:
                    return 0;
                case MODE_MARGINCALCMODE:
                    return 0;
                case MODE_STOPLEVEL:
                    return symbolObject.TickSize;
                case MODE_MINLOT:
                    return symbolObject.ToLotsVolume(symbolObject.VolumeMin);
                case MODE_MAXLOT:
                    return symbolObject.ToLotsVolume(symbolObject.VolumeMax);
                case MODE_LOTSTEP:
                    return symbolObject.ToLotsVolume(symbolObject.VolumeStep);
                case MODE_TICKVALUE:
                    return symbolObject.TickValue;
                case MODE_LOTSIZE:
                    return symbolObject.ToNotNormalizedUnitsVolume(1);
                case MODE_MARGINREQUIRED:
                    return symbolObject.ToNotNormalizedUnitsVolume(1) / Account.Leverage * symbolObject.Ask * symbolObject.TickValue / symbolObject.TickSize;
            }
            return 0;
        }

        Mq4Double Bid
        {
            get
            {
                if (Symbol == null || double.IsNaN(Symbol.Bid))
                    return 0;
                return Symbol.Bid;
            }
        }

        Mq4Double Ask
        {
            get
            {
                if (Symbol == null || double.IsNaN(Symbol.Ask))
                    return 0;
                return Symbol.Ask;
            }
        }



        void SendMail(Mq4String subject, string text)
        {
            Notifications.SendEmail(EmailAddressFrom, EmailAddressTo, subject, text);
            _lastError = ERR_NO_MQLERROR;
        }

        void Mq4Print(params object[] parameters)
        {
            Print(string.Join(string.Empty, parameters));
        }



















//{
        //AccessRights = AccessRights.FullAccess

        void Alert(params object[] objects)
        {
            if (IsBacktesting)
                return;

            var text = string.Join("", objects.Select(o => o.ToString()));
            _alertWindowWrapper.Value.ShowAlert(text);
            PlayAlertSoundIfNeeded();
        }

        Lazy<AlertWindowWrapper> _alertWindowWrapper = new Lazy<AlertWindowWrapper>(() => { return new AlertWindowWrapper(); });

        private const string _alertSound = "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";
        void PlayAlertSoundIfNeeded()
        {
            if (!IsLastBar || IsTesting() || (DateTime.Now - _lastPlayedTime) < TimeSpan.FromSeconds(1))
                return;

            _lastPlayedTime = DateTime.Now;
            _mediaPlayer = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.Media.MediaPlayer");

            var soundFilePath = Path.Combine(FolderPaths._2calgoAppDataFolder, "alert_sound.mp3");
            if (!File.Exists(soundFilePath))
            {
                var binaryData = Convert.FromBase64String(_alertSound);
                File.WriteAllBytes(soundFilePath, binaryData);
            }
            var uri = new Uri(soundFilePath);

            ReflectionHelper.InvokeMethod(_mediaPlayer, "Open", uri);
            ReflectionHelper.InvokeMethod(_mediaPlayer, "Play");
        }

        private DateTime _lastPlayedTime;
        private object _mediaPlayer;

        public class AlertWindowWrapper : MarshalByRefObject
        {
            private static Thread _windowThread;
            private static readonly AutoResetEvent LoadedEvent = new AutoResetEvent(false);
            private static readonly object SyncObject = new object();

            private static object _window;
            private static AlertWindowModel _alertWindowModel;

            public void ShowAlert(string message)
            {
                lock (SyncObject)
                {
                    if (_window == null)
                        CreateWindow();

                    _alertWindowModel.Message = message;
                    var items = new List<AlertItem>(_alertWindowModel.Items);
                    items.Insert(0, new AlertItem(DateTime.Now, message));
                    _alertWindowModel.Items = items;
                }
            }

            private void CreateWindow()
            {
                _windowThread = new Thread(() =>
                {
                    try
                    {
                        _window = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Window");
                        SubscribeToEvent(_window, "Loaded", "Window_Loaded");
                        SubscribeToEvent(_window, "Closing", "Window_Closing");
                        ReflectionHelper.SetProperty(_window, "ShowInTaskbar", true);
                        ReflectionHelper.SetProperty(_window, "ShowActivated", true);
                        ReflectionHelper.SetProperty(_window, "Width", 525);
                        ReflectionHelper.SetProperty(_window, "Height", 400);
                        ReflectionHelper.SetProperty(_window, "WindowStartupLocation", ReflectionHelper.GetStaticValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.WindowStartupLocation", "CenterScreen"));
                        ReflectionHelper.SetProperty(_window, "WindowStyle", ReflectionHelper.GetStaticValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.WindowStyle", "ToolWindow"));
                        ReflectionHelper.SetProperty(_window, "Title", "Alert");
                        var rootGrid = WpfReflectionHelper.CreateGrid();
                        WpfReflectionHelper.SetMargin(rootGrid, 5);
                        WpfReflectionHelper.AddAutoRowDefinition(rootGrid);
                        WpfReflectionHelper.AddStarRowDefinition(rootGrid);

                        var messageGrid = WpfReflectionHelper.CreateGrid();
                        WpfReflectionHelper.AddAutoColumnDefinition(messageGrid);
                        WpfReflectionHelper.AddStarColumnDefinition(messageGrid);

                        var image = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.Image");
                        WpfReflectionHelper.SetMargin(image, 20);
                        var bitmapImage = Base64ToImage("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");
                        ReflectionHelper.SetProperty(image, "Source", bitmapImage);
                        WpfReflectionHelper.AddChild(messageGrid, image);

                        var messageTextBlock = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.TextBlock");

                        WpfReflectionHelper.SetGridColumn(messageTextBlock, 1);
                        ReflectionHelper.SetProperty(messageTextBlock, "HorizontalAlignment", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.HorizontalAlignment", "Left"));
                        ReflectionHelper.SetProperty(messageTextBlock, "TextWrapping", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.TextWrapping", "Wrap"));
                        ReflectionHelper.SetProperty(messageTextBlock, "VerticalAlignment", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.VerticalAlignment", "Center"));
                        ReflectionHelper.SetProperty(messageTextBlock, "FontSize", 18);
                        WpfReflectionHelper.SetBinding(messageTextBlock, "Message", "System.Windows.Controls.TextBlock", "TextProperty");
                        WpfReflectionHelper.AddChild(messageGrid, messageTextBlock);

                        var allAlertsGrid = WpfReflectionHelper.CreateGrid();
                        WpfReflectionHelper.SetGridRow(allAlertsGrid, 1);
                        WpfReflectionHelper.AddStarRowDefinition(allAlertsGrid);
                        WpfReflectionHelper.AddAutoRowDefinition(allAlertsGrid);
                        var dataGrid = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.DataGrid");
                        WpfReflectionHelper.SetBinding(dataGrid, "Items", "System.Windows.Controls.ItemsControl", "ItemsSourceProperty");
                        WpfReflectionHelper.AddChild(allAlertsGrid, dataGrid);
                        var closeButton = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.Button");
                        SubscribeToEvent(closeButton, "Click", "ButtonOnClick");
                        WpfReflectionHelper.SetGridRow(closeButton, 1);
                        ReflectionHelper.SetProperty(closeButton, "Width", 100);
                        WpfReflectionHelper.SetMargin(closeButton, 0, 5, 0, 0);
                        ReflectionHelper.SetProperty(closeButton, "Content", "Close");
                        WpfReflectionHelper.AddChild(allAlertsGrid, closeButton);

                        WpfReflectionHelper.AddChild(rootGrid, messageGrid);
                        WpfReflectionHelper.AddChild(rootGrid, allAlertsGrid);

                        ReflectionHelper.SetProperty(_window, "Content", rootGrid);
                        _alertWindowModel = new AlertWindowModel();
                        ReflectionHelper.SetProperty(_window, "DataContext", _alertWindowModel);

                        ReflectionHelper.InvokeMethod(_window, "ShowDialog");
                    } catch (Exception exception)
                    {
                    }
                }) 
                {
                    IsBackground = false,
                    Name = "Alert Window thread"
                };

                _windowThread.TrySetApartmentState(ApartmentState.STA);
                _windowThread.Start();
                LoadedEvent.WaitOne();
            }

            private static object Base64ToImage(string stringValue)
            {

                var binaryData = Convert.FromBase64String(stringValue);

                var bitmapImage = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.Media.Imaging.BitmapImage");

                ReflectionHelper.InvokeMethod(bitmapImage, "BeginInit");
                ReflectionHelper.SetProperty(bitmapImage, "StreamSource", new MemoryStream(binaryData));
                ReflectionHelper.InvokeMethod(bitmapImage, "EndInit");

                return bitmapImage;
            }

            public void ButtonOnClick(object sender, object routedEventArgs)
            {
                ReflectionHelper.InvokeMethod(_window, "Close");
            }

            public void Window_Loaded(object s, object e)
            {
                LoadedEvent.Set();
            }

            public void Window_Closing(object sender, CancelEventArgs e)
            {
                _window = null;
                _alertWindowModel = null;
            }

            private void SubscribeToEvent(object @object, string eventName, string handlerName)
            {
                var eventInfo = @object.GetType().GetEvent(eventName);
                var methodInfo = GetType().GetMethod(handlerName);
                var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
                eventInfo.AddEventHandler(@object, handler);
            }
        }

        public class AlertWindowModel : INotifyPropertyChanged
        {
            private string _message;
            private IEnumerable<AlertItem> _items = new List<AlertItem>();

            public string Message
            {
                get { return _message; }
                set
                {
                    if (_message == value)
                        return;

                    _message = value;
                    OnPropertyChanged("Message");
                }
            }

            public IEnumerable<AlertItem> Items
            {
                get { return _items; }
                set
                {
                    if (_items == value)
                        return;

                    _items = value;
                    OnPropertyChanged("Items");
                }
            }


            public event PropertyChangedEventHandler PropertyChanged;

            protected virtual void OnPropertyChanged(string propertyName)
            {
                var handler = PropertyChanged;
                if (handler != null)
                    handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public class AlertItem
        {
            public DateTime Time { get; private set; }
            public string Message { get; private set; }

            public AlertItem(DateTime time, string message)
            {
                Time = time;
                Message = message;
            }
        }

        public static class WpfReflectionHelper
        {
            public static Assembly PresentationFrameworkAssembly = Assembly.Load("PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            public static Assembly PresentationCoreAssembly = Assembly.Load("PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

            public static void SetMargin(object rootGrid, params object[] parameters)
            {
                var thickness = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Thickness", parameters);
                ReflectionHelper.SetProperty(rootGrid, "Margin", thickness);
            }

            public static object CreateGrid()
            {
                return ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.Grid");
            }

            public static void AddChild(object grid, object child)
            {
                var rootGridChildren = ReflectionHelper.GetPropertyValue(grid, "Children");
                ReflectionHelper.InvokeMethod(rootGridChildren, "Add", child);
            }

            private static readonly object AutoGridLegth = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.GridLength", "Auto");

            public static void AddAutoRowDefinition(object grid)
            {
                var rowDefinition = CreateRowDefinition();
                ReflectionHelper.SetProperty(rowDefinition, "Height", AutoGridLegth);
                AddRowDefinition(grid, rowDefinition);
            }

            public static void AddStarRowDefinition(object grid)
            {
                var rowDefinition = CreateRowDefinition();
                var starUnitType = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.GridUnitType", "Star");
                var gridLength = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.GridLength", new[] 
                {
                    1,
                    starUnitType
                });
                ReflectionHelper.SetProperty(rowDefinition, "Height", gridLength);
                AddRowDefinition(grid, rowDefinition);
            }

            private static object CreateRowDefinition()
            {
                var rowDefinition = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.RowDefinition");
                return rowDefinition;
            }

            public static void AddRowDefinition(object grid, object rowDefinition)
            {
                var rowDefinitions = ReflectionHelper.GetPropertyValue(grid, "RowDefinitions");
                ReflectionHelper.InvokeMethod(rowDefinitions, "Add", rowDefinition);
            }

            public static void AddAutoColumnDefinition(object grid)
            {
                var ColumnDefinition = CreateColumnDefinition();
                ReflectionHelper.SetProperty(ColumnDefinition, "Width", AutoGridLegth);
                AddColumnDefinition(grid, ColumnDefinition);
            }

            public static void AddStarColumnDefinition(object grid)
            {
                var ColumnDefinition = CreateColumnDefinition();
                var starUnitType = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.GridUnitType", "Star");
                var gridLength = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.GridLength", new[] 
                {
                    1,
                    starUnitType
                });
                ReflectionHelper.SetProperty(ColumnDefinition, "Width", gridLength);
                AddColumnDefinition(grid, ColumnDefinition);
            }

            private static object CreateColumnDefinition()
            {
                var ColumnDefinition = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.ColumnDefinition");
                return ColumnDefinition;
            }

            public static void AddColumnDefinition(object grid, object ColumnDefinition)
            {
                var ColumnDefinitions = ReflectionHelper.GetPropertyValue(grid, "ColumnDefinitions");
                ReflectionHelper.InvokeMethod(ColumnDefinitions, "Add", ColumnDefinition);
            }

            public static void SetGridColumn(object element, int column)
            {
                var columnProperty = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.Controls.Grid", "ColumnProperty");
                ReflectionHelper.InvokeMethod(element, "SetValue", columnProperty, column);
            }

            public static void SetGridRow(object element, int row)
            {
                var columnProperty = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.Controls.Grid", "RowProperty");
                ReflectionHelper.InvokeMethod(element, "SetValue", columnProperty, row);
            }

            public static void SetBinding(object element, string path, string propertyTypeName, string propertyName)
            {
                var property = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, propertyTypeName, propertyName);
                ReflectionHelper.InvokeMethod(element, "SetBinding", property, path);
            }
        }

        public static class ReflectionHelper
        {
            public static object GetEnumValue(Assembly assembly, string typeName, string value)
            {
                var type = assembly.GetType(typeName);
                return Enum.Parse(type, value);
            }

            public static void InvokeMethod(object instance, string methodName, params object[] parameters)
            {
                instance.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod, null, instance, parameters);
            }

            public static object InvokeStaticMethod(Assembly assembly, string typeName, string methodName, params object[] parameters)
            {
                return assembly.GetType(typeName).InvokeMember(methodName, BindingFlags.InvokeMethod, null, null, parameters);
            }

            public static object GetStaticValue(Assembly assembly, string typeName, string propertyName)
            {
                var type = assembly.GetType(typeName);
                var propertyInfo = type.GetProperty(propertyName);
                if (propertyInfo != null)
                    return propertyInfo.GetValue(null, null);

                var fieldInfo = type.GetField(propertyName);
                return fieldInfo.GetValue(null);
            }

            public static void SetProperty(object instance, string propertyName, Assembly assembly, string typeName, params object[] parameters)
            {
                var propertyInfo = instance.GetType().GetProperty(propertyName);
                var propertyValue = CreateInstance(assembly, typeName, parameters);
                propertyInfo.SetValue(instance, propertyValue, null);
            }

            public static void SetProperty(object instance, string propertyName, object value)
            {
                var propertyInfo = instance.GetType().GetProperty(propertyName);
                propertyInfo.SetValue(instance, value, null);
            }

            public static object GetPropertyValue(object instance, string propertyName)
            {
                var propertyInfo = instance.GetType().GetProperty(propertyName);
                return propertyInfo.GetValue(instance, null);
            }

            public static object CreateInstance(Assembly assembly, string typeName)
            {
                return CreateInstance(assembly, typeName, new object[0]);
            }

            public static object CreateInstance(Assembly assembly, string typeName, object[] parameters)
            {
                var pointType = assembly.GetType(typeName);
                var propertyValue = Activator.CreateInstance(pointType, parameters);
                return propertyValue;
            }
        }
        //}

        private int _lastError;
        Mq4Double GetLastError()
        {
            return _lastError;
        }

        Mq4Double IsTesting()
        {
            return IsBacktesting;
        }











        Mq4String ErrorDescription(int code)
        {
            string error_string;
            switch (code)
            {
                case 0:
                case 1:
                    return "no error";
                case 2:
                    return "common error";
                case 4203:
                    return "unknown object type";
                case 4204:
                    return "no object name";
                case 4205:
                    return "object coordinates error";
                default:
                    return "unknown error";
            }
            return error_string;
        }

        const string GlobalVariablesPath = "Software\\2calgo\\Global Variables\\";






        Symbol GetSymbol(string symbolCode)
        {
            if (symbolCode == "0" || string.IsNullOrEmpty(symbolCode))
            {
                return Symbol;
            }
            return MarketData.GetSymbol(symbolCode);
        }

        MarketSeries GetSeries(string symbol, int period)
        {
            var timeFrame = PeriodToTimeFrame(period);
            var symbolObject = GetSymbol(symbol);

            if (symbolObject == Symbol && timeFrame == TimeFrame)
                return MarketSeries;

            return MarketData.GetSeries(symbolObject.Code, timeFrame);
        }

        private DataSeries ToAppliedPrice(string symbol, int timeframe, int constant)
        {
            var series = GetSeries(symbol, timeframe);
            switch (constant)
            {
                case PRICE_OPEN:
                    return series.Open;
                case PRICE_HIGH:
                    return series.High;
                case PRICE_LOW:
                    return series.Low;
                case PRICE_CLOSE:
                    return series.Close;
                case PRICE_MEDIAN:
                    return series.Median;
                case PRICE_TYPICAL:
                    return series.Typical;
                case PRICE_WEIGHTED:
                    return series.WeightedClose;
            }
            throw new NotImplementedException("Converter doesn't support working with this type of AppliedPrice");
        }
        const string xArrow = "✖";

        public static string GetArrowByCode(int code)
        {
            switch (code)
            {
                case 0:
                    return string.Empty;
                case 32:
                    return " ";
                case 33:
                    return "✏";
                case 34:
                    return "✂";
                case 35:
                    return "✁";
                case 40:
                    return "☎";
                case 41:
                    return "✆";
                case 42:
                    return "✉";
                case 54:
                    return "⌛";
                case 55:
                    return "⌨";
                case 62:
                    return "✇";
                case 63:
                    return "✍";
                case 65:
                    return "✌";
                case 69:
                    return "☜";
                case 70:
                    return "☞";
                case 71:
                    return "☝";
                case 72:
                    return "☟";
                case 74:
                    return "☺";
                case 76:
                    return "☹";
                case 78:
                    return "☠";
                case 79:
                    return "⚐";
                case 81:
                    return "✈";
                case 82:
                    return "☼";
                case 84:
                    return "❄";
                case 86:
                    return "✞";
                case 88:
                    return "✠";
                case 89:
                    return "✡";
                case 90:
                    return "☪";
                case 91:
                    return "☯";
                case 92:
                    return "ॐ";
                case 93:
                    return "☸";
                case 94:
                    return "♈";
                case 95:
                    return "♉";
                case 96:
                    return "♊";
                case 97:
                    return "♋";
                case 98:
                    return "♌";
                case 99:
                    return "♍";
                case 100:
                    return "♎";
                case 101:
                    return "♏";
                case 102:
                    return "♐";
                case 103:
                    return "♑";
                case 104:
                    return "♒";
                case 105:
                    return "♓";
                case 106:
                    return "&";
                case 107:
                    return "&";
                case 108:
                    return "●";
                case 109:
                    return "❍";
                case 110:
                    return "■";
                case 111:
                case 112:
                    return "□";
                case 113:
                    return "❑";
                case 114:
                    return "❒";
                case 115:
                case 116:
                    return "⧫";
                case 117:
                case 119:
                    return "◆";
                case 118:
                    return "❖";
                case 120:
                    return "⌧";
                case 121:
                    return "⍓";
                case 122:
                    return "⌘";
                case 123:
                    return "❀";
                case 124:
                    return "✿";
                case 125:
                    return "❝";
                case 126:
                    return "❞";
                case 127:
                    return "▯";
                case 128:
                    return "⓪";
                case 129:
                    return "①";
                case 130:
                    return "②";
                case 131:
                    return "③";
                case 132:
                    return "④";
                case 133:
                    return "⑤";
                case 134:
                    return "⑥";
                case 135:
                    return "⑦";
                case 136:
                    return "⑧";
                case 137:
                    return "⑨";
                case 138:
                    return "⑩";
                case 139:
                    return "⓿";
                case 140:
                    return "❶";
                case 141:
                    return "❷";
                case 142:
                    return "❸";
                case 143:
                    return "❹";
                case 144:
                    return "❺";
                case 145:
                    return "❻";
                case 146:
                    return "❼";
                case 147:
                    return "❽";
                case 148:
                    return "❾";
                case 149:
                    return "❿";
                case 158:
                    return "·";
                case 159:
                    return "•";
                case 160:
                case 166:
                    return "▪";
                case 161:
                    return "○";
                case 162:
                case 164:
                    return "⭕";
                case 165:
                    return "◎";
                case 167:
                    return "✖";
                case 168:
                    return "◻";
                case 170:
                    return "✦";
                case 171:
                    return "★";
                case 172:
                    return "✶";
                case 173:
                    return "✴";
                case 174:
                    return "✹";
                case 175:
                    return "✵";
                case 177:
                    return "⌖";
                case 178:
                    return "⟡";
                case 179:
                    return "⌑";
                case 181:
                    return "✪";
                case 182:
                    return "✰";
                case 195:
                case 197:
                case 215:
                case 219:
                case 223:
                case 231:
                    return "◀";
                case 196:
                case 198:
                case 224:
                    return "▶";
                case 213:
                    return "⌫";
                case 214:
                    return "⌦";
                case 216:
                    return "➢";
                case 220:
                    return "➲";
                case 232:
                    return "➔";
                case 233:
                case 199:
                case 200:
                case 217:
                case 221:
                case 225:
                    return "◭";
                case 234:
                case 201:
                case 202:
                case 218:
                case 222:
                case 226:
                    return "⧨";
                case 239:
                    return "⇦";
                case 240:
                    return "⇨";
                case 241:
                    return "◭";
                case 242:
                    return "⧨";
                case 243:
                    return "⬄";
                case 244:
                    return "⇳";
                case 245:
                case 227:
                case 235:
                    return "↖";
                case 246:
                case 228:
                case 236:
                    return "↗";
                case 247:
                case 229:
                case 237:
                    return "↙";
                case 248:
                case 230:
                case 238:
                    return "↘";
                case 249:
                    return "▭";
                case 250:
                    return "▫";
                case 251:
                    return "✗";
                case 252:
                    return "✓";
                case 253:
                    return "☒";
                case 254:
                    return "☑";
                default:
                    return xArrow;
            }
        }
        class Mq4OutputDataSeries : IMq4DoubleArray
        {
            public IndicatorDataSeries OutputDataSeries { get; private set; }
            private readonly IndicatorDataSeries _originalValues;
            private int _currentIndex;
            private int _shift;
            private double _emptyValue = EMPTY_VALUE;
            private readonly ChartObjects _chartObjects;
            private readonly int _style;
            private readonly int _bufferIndex;
            private readonly BrainExpert_v2_Robot _indicator;

            public Mq4OutputDataSeries(BrainExpert_v2_Robot indicator, IndicatorDataSeries outputDataSeries, ChartObjects chartObjects, int style, int bufferIndex, Func<IndicatorDataSeries> dataSeriesFactory, int lineWidth, Colors? color = null)
            {
                OutputDataSeries = outputDataSeries;
                _chartObjects = chartObjects;
                _style = style;
                _bufferIndex = bufferIndex;
                _indicator = indicator;
                Color = color;
                _originalValues = dataSeriesFactory();
                LineWidth = lineWidth;
            }

            public int LineWidth { get; private set; }
            public Colors? Color { get; private set; }

            public int Length
            {
                get { return OutputDataSeries.Count; }
            }

            public void Resize(int newSize)
            {
            }

            public void SetCurrentIndex(int index)
            {
                _currentIndex = index;
            }

            public void SetShift(int shift)
            {
                _shift = shift;
            }

            public void SetEmptyValue(double emptyValue)
            {
                _emptyValue = emptyValue;
            }

            public Mq4Double this[int index]
            {
                get
                {
                    var indexToGetFrom = _currentIndex - index + _shift;
                    if (indexToGetFrom < 0 || indexToGetFrom > _currentIndex)
                        return 0;
                    if (indexToGetFrom >= _originalValues.Count)
                        return _emptyValue;

                    return _originalValues[indexToGetFrom];
                }
                set
                {
                    var indexToSet = _currentIndex - index + _shift;
                    if (indexToSet < 0)
                        return;

                    _originalValues[indexToSet] = value;

                    var valueToSet = value;
                    if (valueToSet == _emptyValue)
                        valueToSet = double.NaN;

                    if (indexToSet < 0)
                        return;

                    OutputDataSeries[indexToSet] = valueToSet;

                    switch (_style)
                    {
                        case DRAW_ARROW:
                            var arrowName = GetArrowName(indexToSet);
                            if (double.IsNaN(valueToSet))
                                _chartObjects.RemoveObject(arrowName);
                            else
                            {
                                var color = Color.HasValue ? Color.Value : Colors.Red;
                                _chartObjects.DrawText(arrowName, _indicator.ArrowByIndex[_bufferIndex], indexToSet, valueToSet, VerticalAlignment.Center, HorizontalAlignment.Center, color);
                            }
                            break;
                        case DRAW_HISTOGRAM:
                            if (false)
                            {
                                var anotherLine = _indicator.AllBuffers.FirstOrDefault(b => b.LineWidth == LineWidth && b != this);
                                if (anotherLine != null)
                                {
                                    var name = GetNameOfHistogramLineOnChartWindow(indexToSet);
                                    Colors color;
                                    if (this[index] > anotherLine[index])
                                        color = Color ?? Colors.Green;
                                    else
                                        color = anotherLine.Color ?? Colors.Green;
                                    var lineWidth = LineWidth;
                                    if (lineWidth != 1 && lineWidth < 5)
                                        lineWidth = 5;

                                    _chartObjects.DrawLine(name, indexToSet, this[index], indexToSet, anotherLine[index], color, lineWidth);
                                }
                            }
                            break;
                    }
                }
            }

            private string GetNameOfHistogramLineOnChartWindow(int index)
            {
                return string.Format("Histogram on chart window {0} {1}", LineWidth, index);
            }

            private string GetArrowName(int index)
            {
                return string.Format("Arrow {0} {1}", GetHashCode(), index);
            }
        }
















        public Dictionary<int, string> ArrowByIndex = new Dictionary<int, string> 
        {
            {
                0,
                xArrow
            },
            {
                1,
                xArrow
            },
            {
                2,
                xArrow
            },
            {
                3,
                xArrow
            },
            {
                4,
                xArrow
            },
            {
                5,
                xArrow
            },
            {
                6,
                xArrow
            },
            {
                7,
                xArrow
            }
        };
        void SetIndexArrow(int index, int code)
        {
            ArrowByIndex[index] = GetArrowByCode(code);
        }

        private int _indicatorCounted;
        int FILE_READ = 1;
        int FILE_WRITE = 2;
//int FILE_BIN = 8;
        int FILE_CSV = 8;

        int SEEK_END = 2;

        class FileInfo
        {
            public int Mode { get; set; }
            public int Handle { get; set; }
            public char Separator { get; set; }
            public string FileName { get; set; }
            public List<string> PendingParts { get; set; }
            public StreamWriter StreamWriter { get; set; }
            public StreamReader StreamReader { get; set; }
        }

        private Dictionary<int, FileInfo> _openedFiles = new Dictionary<int, FileInfo>();
        private int _handleCounter = 1000;







        class FolderPaths
        {
            public static string _2calgoAppDataFolder
            {
                get
                {
                    var result = Path.Combine(SystemAppData, "2calgo");
                    if (!Directory.Exists(result))
                        Directory.CreateDirectory(result);
                    return result;
                }
            }

            public static string _2calgoDesktopFolder
            {
                get
                {
                    var result = Path.Combine(Desktop, "2calgo");
                    if (!Directory.Exists(result))
                        Directory.CreateDirectory(result);
                    return result;
                }
            }

            static string SystemAppData
            {
                get { return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); }
            }

            static string Desktop
            {
                get { return Environment.GetFolderPath(Environment.SpecialFolder.Desktop); }
            }
        }
        const int MODE_TRADES = 0;
        const int MODE_HISTORY = 1;
        const int SELECT_BY_POS = 0;
        const int SELECT_BY_TICKET = 1;

        T GetPropertyValue<T>(Func<Position, T> getFromPosition, Func<PendingOrder, T> getFromPendingOrder, Func<HistoricalTrade, T> getFromHistory)
        {
            if (_currentOrder == null)
                return default(T);

            return GetPropertyValue<T>(_currentOrder, getFromPosition, getFromPendingOrder, getFromHistory);
        }

        T GetPropertyValue<T>(object obj, Func<Position, T> getFromPosition, Func<PendingOrder, T> getFromPendingOrder, Func<HistoricalTrade, T> getFromHistory)
        {
            if (obj is Position)
                return getFromPosition((Position)obj);
            if (obj is PendingOrder)
                return getFromPendingOrder((PendingOrder)obj);

            return getFromHistory((HistoricalTrade)obj);
        }

        private Mq4Double GetTicket(object trade)
        {
            return new Mq4Double(GetPropertyValue<int>(trade, _ => _.Id, _ => _.Id, _ => _.ClosingDealId));
        }
        Mq4Double OrderTicket()
        {
            if (_currentOrder == null)
                return 0;

            return GetTicket(_currentOrder);
        }
        private int GetMagicNumber(string label)
        {
            int magicNumber;
            if (int.TryParse(label, out magicNumber))
                return magicNumber;

            return 0;
        }

        private int GetMagicNumber(object order)
        {
            var label = GetPropertyValue<string>(order, _ => _.Label, _ => _.Label, _ => _.Label);
            return GetMagicNumber(label);
        }
        Mq4Double OrderMagicNumber()
        {
            if (_currentOrder == null)
                return 0;

            return GetMagicNumber(_currentOrder);
        }


        Mq4Double OrdersTotal()
        {
            return Positions.Count + PendingOrders.Count;
        }


        object _currentOrder;
        bool OrderSelect(int index, int @select, int pool = MODE_TRADES)
        {
            _currentOrder = null;

            if (pool == MODE_TRADES)
            {
                var allOrders = Positions.OfType<object>().Concat(PendingOrders.OfType<object>()).ToArray();

                switch (@select)
                {
                    case SELECT_BY_POS:
                        if (index < 0 || index >= allOrders.Length)
                            return false;

                        _currentOrder = allOrders[index];
                        return true;
                    case SELECT_BY_TICKET:
                        _currentOrder = GetOrderByTicket(index);
                        return _currentOrder != null;
                }
            }
            if (pool == MODE_HISTORY)
            {
                switch (@select)
                {
                    case SELECT_BY_POS:
                        if (index < 0 || index >= History.Count)
                            return false;

                        _currentOrder = History[index];
                        return true;
                    case SELECT_BY_TICKET:
                        _currentOrder = History.FindLast(index.ToString());
                        return _currentOrder != null;
                }
            }

            return false;
        }
        double GetLots(object order)
        {
            var volume = GetPropertyValue<long>(order, _ => _.Volume, _ => _.Volume, _ => _.Volume);
            var symbolCode = GetPropertyValue<string>(order, _ => _.SymbolCode, _ => _.SymbolCode, _ => _.SymbolCode);
            var symbolObject = MarketData.GetSymbol(symbolCode);

            return symbolObject.ToLotsVolume(volume);
        }

        object GetOrderByTicket(int ticket)
        {
            var allOrders = Positions.OfType<object>().Concat(PendingOrders.OfType<object>()).ToArray();

            return allOrders.FirstOrDefault(_ => GetTicket(_) == ticket);
        }
        Mq4Double OrderLots()
        {
            if (_currentOrder == null)
                return 0;

            return GetLots(_currentOrder);
        }

        Mq4Double OrderType()
        {
            if (_currentOrder == null)
                return 0;

            var position = _currentOrder as Position;
            if (position != null)
            {
                return position.TradeType == TradeType.Buy ? OP_BUY : OP_SELL;
            }
            var pendingOrder = _currentOrder as PendingOrder;
            if (pendingOrder != null)
            {
                if (pendingOrder.OrderType == PendingOrderType.Limit)
                    return pendingOrder.TradeType == TradeType.Buy ? OP_BUYLIMIT : OP_SELLLIMIT;
                return pendingOrder.TradeType == TradeType.Buy ? OP_BUYSTOP : OP_SELLSTOP;
            }

            var historicalTrade = (HistoricalTrade)_currentOrder;

            return historicalTrade.TradeType == TradeType.Buy ? OP_BUY : OP_SELL;
        }

        Mq4String OrderSymbol()
        {
            return GetPropertyValue<string>(_ => _.SymbolCode, _ => _.SymbolCode, _ => _.SymbolCode);
        }
        double GetOpenPrice(object order)
        {
            return GetPropertyValue<double>(order, _ => _.EntryPrice, _ => _.TargetPrice, _ => _.EntryPrice);
        }
        Mq4Double OrderOpenPrice()
        {
            if (_currentOrder == null)
                return 0;

            return GetOpenPrice(_currentOrder);
        }

        Mq4Double OrderClosePrice()
        {
            var historicalTrade = _currentOrder as HistoricalTrade;
            if (historicalTrade != null)
                return historicalTrade.ClosingPrice;

            return 0;
        }

        private double GetStopLoss(object order)
        {
            var nullableValue = GetPropertyValue<double?>(order, _ => _.StopLoss, _ => _.StopLoss, _ => 0);
            return nullableValue ?? 0;
        }

        private double GetTakeProfit(object order)
        {
            var nullableValue = GetPropertyValue<double?>(order, _ => _.TakeProfit, _ => _.TakeProfit, _ => 0);
            return nullableValue ?? 0;
        }
        Mq4Double OrderStopLoss()
        {
            if (_currentOrder == null)
                return 0;
            return GetStopLoss(_currentOrder);
        }

        Mq4Double OrderTakeProfit()
        {
            if (_currentOrder == null)
                return 0;
            return GetTakeProfit(_currentOrder);
        }








        Mq4Double AccountFreeMargin()
        {
            return Account.FreeMargin;
        }














        class ParametersKey
        {
            private readonly object[] _parameters;

            public ParametersKey(params object[] parameters)
            {
                _parameters = parameters;
            }

            public override bool Equals(object obj)
            {
                var other = (ParametersKey)obj;
                for (var i = 0; i < _parameters.Length; i++)
                {
                    if (!_parameters[i].Equals(other._parameters[i]))
                        return false;
                }
                return true;
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    var hashCode = 0;
                    foreach (var parameter in _parameters)
                    {
                        hashCode = (hashCode * 397) ^ parameter.GetHashCode();
                    }
                    return hashCode;
                }
            }
        }

        class Cache<TValue>
        {
            private Dictionary<ParametersKey, TValue> _dictionary = new Dictionary<ParametersKey, TValue>();

            public bool TryGetValue(out TValue value, params object[] parameters)
            {
                var key = new ParametersKey(parameters);
                return _dictionary.TryGetValue(key, out value);
            }

            public void Add(TValue value, params object[] parameters)
            {
                var key = new ParametersKey(parameters);
                _dictionary.Add(key, value);
            }
        }


        private static MovingAverageType ToMaType(int constant)
        {
            switch (constant)
            {
                case MODE_SMA:
                    return MovingAverageType.Simple;
                case MODE_EMA:
                    return MovingAverageType.Exponential;
                case MODE_LWMA:
                    return MovingAverageType.Weighted;
                default:
                    throw new ArgumentOutOfRangeException("Not supported moving average type");
            }
        }










//{
        #region iSAR
        private Mq4Double iSAR(Mq4String symbol, Mq4Double timeframe, Mq4Double step, Mq4Double maximum, Mq4Double shift)
        {
            var series = GetSeries(symbol, timeframe);
            var indicator = Indicators.ParabolicSAR(series, step, maximum);

            return indicator.Result[series.Close.Count - 1 - shift];
        }
        #endregion
        //}


//{

        Mq4Double iStochastic(Mq4String symbol, Mq4Double timeframe, Mq4Double kperiod, Mq4Double dperiod, Mq4Double slowing, Mq4Double method, Mq4Double price_field, Mq4Double mode, Mq4Double shift)
        {
            var maType = ToMaType(method);
            var stochasticMode = method == 0 ? StochasticMode.LowHigh : StochasticMode.CloseClose;
            var marketSeries = GetSeries(symbol, timeframe);
            var index = marketSeries.Close.Count - 1 - shift;

            var stochasticValues = CalculateStochastic(marketSeries, kperiod, dperiod, slowing, maType, stochasticMode, index);

            switch (mode)
            {
                case MODE_MAIN:
                    return stochasticValues.K;
                case MODE_SIGNAL:
                    return stochasticValues.D;
            }

            return 0;
        }

        private struct StochasticParameters
        {
            public int KPeriods;
            public int DPeriods;
            public int KSlowing;
            public MovingAverageType MAType;
            public StochasticMode StochasticMode;
            public MarketSeries MarketSeries;

            public bool Equals(StochasticParameters other)
            {
                return KPeriods == other.KPeriods && DPeriods == other.DPeriods && KSlowing == other.KSlowing && MAType == other.MAType && StochasticMode == other.StochasticMode && Equals(MarketSeries, other.MarketSeries);
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                    return false;
                return obj is StochasticParameters && Equals((StochasticParameters)obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    var hashCode = KPeriods;
                    hashCode = (hashCode * 397) ^ DPeriods;
                    hashCode = (hashCode * 397) ^ KSlowing;
                    hashCode = (hashCode * 397) ^ (int)MAType;
                    hashCode = (hashCode * 397) ^ (int)StochasticMode;
                    hashCode = (hashCode * 397) ^ (MarketSeries != null ? MarketSeries.GetHashCode() : 0);
                    return hashCode;
                }
            }
        }

        private class StochasticValues_
        {
            public Mq4Double K { get; private set; }
            public Mq4Double D { get; private set; }

            public StochasticValues_(double k, double d)
            {
                K = k;
                D = d;
            }
        }

        private enum StochasticMode
        {
            LowHigh,
            CloseClose
        }

        private class StochasticIndicator_
        {
            private readonly StochasticParameters _parameters;
            private IndicatorDataSeries _fastK;
            private MovingAverage _slowK;
            private MovingAverage _averageOnSlowK;

            public StochasticIndicator_(StochasticParameters stochasticParameters, IIndicatorsAccessor indicatorAccessor, Func<IndicatorDataSeries> dataSeriesFactory)
            {
                _parameters = stochasticParameters;
                _fastK = dataSeriesFactory();
                _slowK = indicatorAccessor.MovingAverage(_fastK, _parameters.KSlowing, _parameters.MAType);
                _averageOnSlowK = indicatorAccessor.MovingAverage(_slowK.Result, _parameters.DPeriods, _parameters.MAType);
            }

            public StochasticValues_ Calculate(int index)
            {
                for (var i = index - _parameters.KSlowing * _parameters.DPeriods; i <= index; i++)
                    _fastK[i] = GetFastKValue(i);

                for (var i = Math.Max(0, index - _parameters.DPeriods); i <= index; i++)
                    _slowK.Calculate(i + 1);
                var k = _slowK.Result[index];

                for (var i = Math.Max(0, index - _parameters.DPeriods); i <= index; i++)
                    _averageOnSlowK.Calculate(i + 1);
                var d = _averageOnSlowK.Result[index];

                return new StochasticValues_(k, d);
            }

            private double GetFastKValue(int index)
            {
                DataSeries low = _parameters.MarketSeries.Low;
                DataSeries high = _parameters.MarketSeries.High;

                if (_parameters.StochasticMode == StochasticMode.CloseClose)
                {
                    low = _parameters.MarketSeries.Close;
                    high = _parameters.MarketSeries.Close;
                }
                double minFromPeriod = GetMinFromPeriod(low, index, _parameters.KPeriods);
                double maxFromPeriod = GetMaxFromPeriod(high, index, _parameters.KPeriods);
                return (_parameters.MarketSeries.Close[index] - minFromPeriod) / (maxFromPeriod - minFromPeriod) * 100.0;
            }

            private static double GetMinFromPeriod(DataSeries dataSeries, int endIndex, int periods)
            {
                double num = dataSeries[endIndex];
                for (int index = endIndex; index > endIndex - periods; --index)
                {
                    if (dataSeries[index] < num)
                        num = dataSeries[index];
                }
                return num;
            }

            private static double GetMaxFromPeriod(DataSeries dataSeries, int endIndex, int periods)
            {
                double num = dataSeries[endIndex];
                for (int index = endIndex; index > endIndex - periods; --index)
                {
                    if (dataSeries[index] > num)
                        num = dataSeries[index];
                }
                return num;
            }
        }

        private Dictionary<StochasticParameters, StochasticIndicator_> _stochasticIndicators = new Dictionary<StochasticParameters, StochasticIndicator_>();

        private StochasticValues_ CalculateStochastic(MarketSeries marketSeries, int kPeriod, int dPeriod, int slowing, MovingAverageType maType, StochasticMode stochasticMode, int index)
        {
            var parameters = new StochasticParameters 
            {
                KPeriods = kPeriod,
                DPeriods = dPeriod,
                KSlowing = slowing,
                MAType = maType,
                StochasticMode = stochasticMode,
                MarketSeries = marketSeries
            };

            StochasticIndicator_ indicator;
            if (!_stochasticIndicators.TryGetValue(parameters, out indicator))
            {
                indicator = new StochasticIndicator_(parameters, Indicators, () => CreateDataSeries());
                _stochasticIndicators[parameters] = indicator;
            }

            return indicator.Calculate(index);
        }
//}






//{
        internal class CustomIndicatorParameters
        {
            public MarketSeries MarketSeries { get; set; }
            public object[] Parameters { get; set; }

            protected bool Equals(CustomIndicatorParameters other)
            {
                if (Parameters.Length != other.Parameters.Length)
                    return false;
                for (var i = 0; i < Parameters.Length; i++)
                {
                    if (!Equals(Parameters[i], other.Parameters[i]))
                        return false;
                }

                return Equals(MarketSeries, other.MarketSeries);
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                    return false;
                if (ReferenceEquals(this, obj))
                    return true;
                if (obj.GetType() != this.GetType())
                    return false;
                return Equals((CustomIndicatorParameters)obj);
            }

            public override int GetHashCode()
            {
                return (MarketSeries != null ? MarketSeries.GetHashCode() : 0);
            }
        }

        private List<DataSeries> GetAllOutputDataSeries(object indicatorInstance)
        {
            var fieldInfo = indicatorInstance.GetType().GetField("AllOutputDataSeries");
            return (List<DataSeries>)fieldInfo.GetValue(indicatorInstance);
        }

        private object CastParameter(object parameter)
        {
            if (parameter is Mq4Double)
            {
                var mq4Double = (Mq4Double)parameter;
                if (Math.Abs(mq4Double - (int)mq4Double) < Symbol.TickSize)
                    return (int)mq4Double;
                return (double)mq4Double;
            }
            if (parameter is string || parameter is Mq4String)
            {
                return (string)parameter;
            }
            return parameter;
        }

        private object[] CastParameters<T>(object[] parameters)
        {
            return parameters.Select(CastParameter).ToArray();
        }

        private static object[] AddEmailParametersIfNeeded<T>(object[] parameters)
        {
            var needed = typeof(T).GetProperties().Where(info => info.GetCustomAttributes(typeof(ParameterAttribute), false).Any()).Any(p => p.Name == "EmailAddressFrom");

            var result = new List<object>();
            result.AddRange(parameters);
            if (needed)
            {
                result.Insert(0, string.Empty);
                result.Insert(0, string.Empty);
            }
            return result.ToArray();
        }

        private readonly Dictionary<CustomIndicatorParameters, List<DataSeries>> _customIndicatorsCache = new Dictionary<CustomIndicatorParameters, List<DataSeries>>();

        Mq4Double iCustom<T>(Mq4String symbol, Mq4Double timeframe, Mq4String name, params object[] parameters) where T : Indicator
        {
            var marketSeries = GetSeries(symbol, timeframe);
            var indicatorParameters = CastParameters<T>(parameters.Take(parameters.Length - 2).ToArray());
            indicatorParameters = AddEmailParametersIfNeeded<T>(indicatorParameters);

            var customIndicatorParameters = new CustomIndicatorParameters 
            {
                MarketSeries = marketSeries,
                Parameters = indicatorParameters
            };
            List<DataSeries> outputSeries;
            if (!_customIndicatorsCache.TryGetValue(customIndicatorParameters, out outputSeries))
            {
                var customIndicator = Indicators.GetIndicator<T>(marketSeries, indicatorParameters);
                outputSeries = GetAllOutputDataSeries(customIndicator);
                _customIndicatorsCache[customIndicatorParameters] = outputSeries;
            }

            var mode = (int)CastParameter(parameters[parameters.Length - 2]);
            var shift = (int)CastParameter(parameters[parameters.Length - 1]);
            return outputSeries[mode].Last(shift);
        }
//}








        class CachedStandardIndicators
        {
            private readonly IIndicatorsAccessor _indicatorsAccessor;

            public CachedStandardIndicators(IIndicatorsAccessor indicatorsAccessor)
            {
                _indicatorsAccessor = indicatorsAccessor;
            }

        }
        const bool True = true;
        const bool False = false;
        const bool TRUE = true;
        const bool FALSE = false;
        Mq4Null NULL;
        const int EMPTY = -1;
        const double EMPTY_VALUE = 2147483647;
        public const int WHOLE_ARRAY = 0;

        const int MODE_SMA = 0;
        //Simple moving average
        const int MODE_EMA = 1;
        //Exponential moving average,
        const int MODE_SMMA = 2;
        //Smoothed moving average,
        const int MODE_LWMA = 3;
        //Linear weighted moving average. 
        const int PRICE_CLOSE = 0;
        //Close price. 
        const int PRICE_OPEN = 1;
        //Open price. 
        const int PRICE_HIGH = 2;
        //High price. 
        const int PRICE_LOW = 3;
        //Low price. 
        const int PRICE_MEDIAN = 4;
        //Median price, (high+low)/2. 
        const int PRICE_TYPICAL = 5;
        //Typical price, (high+low+close)/3. 
        const int PRICE_WEIGHTED = 6;
        //Weighted close price, (high+low+close+close)/4. 
        const int DRAW_LINE = 0;
        const int DRAW_SECTION = 1;
        const int DRAW_HISTOGRAM = 2;
        const int DRAW_ARROW = 3;
        const int DRAW_ZIGZAG = 4;
        const int DRAW_NONE = 12;

        const int STYLE_SOLID = 0;
        const int STYLE_DASH = 1;
        const int STYLE_DOT = 2;
        const int STYLE_DASHDOT = 3;
        const int STYLE_DASHDOTDOT = 4;

        const int MODE_OPEN = 0;
        const int MODE_LOW = 1;
        const int MODE_HIGH = 2;
        const int MODE_CLOSE = 3;
        const int MODE_VOLUME = 4;
        const int MODE_TIME = 5;
        const int MODE_BID = 9;
        const int MODE_ASK = 10;
        const int MODE_POINT = 11;
        const int MODE_DIGITS = 12;
        const int MODE_SPREAD = 13;
        const int MODE_TRADEALLOWED = 22;
        const int MODE_PROFITCALCMODE = 27;
        const int MODE_MARGINCALCMODE = 28;
        const int MODE_SWAPTYPE = 26;
        const int MODE_TICKSIZE = 17;
        const int MODE_FREEZELEVEL = 33;
        const int MODE_STOPLEVEL = 14;
        const int MODE_LOTSIZE = 15;
        const int MODE_TICKVALUE = 16;
        /*const int MODE_SWAPLONG = 18;
const int MODE_SWAPSHORT = 19;
const int MODE_STARTING = 20;
const int MODE_EXPIRATION = 21;    
*/
        const int MODE_MINLOT = 23;
        const int MODE_LOTSTEP = 24;
        const int MODE_MAXLOT = 25;
        /*const int MODE_MARGININIT = 29;
const int MODE_MARGINMAINTENANCE = 30;
const int MODE_MARGINHEDGED = 31;*/
        const int MODE_MARGINREQUIRED = 32;

        const int OBJ_VLINE = 0;
        const int OBJ_HLINE = 1;
        const int OBJ_TREND = 2;
        const int OBJ_FIBO = 10;

        /*const int OBJ_TRENDBYANGLE = 3;
    const int OBJ_REGRESSION = 4;
    const int OBJ_CHANNEL = 5;
    const int OBJ_STDDEVCHANNEL = 6;
    const int OBJ_GANNLINE = 7;
    const int OBJ_GANNFAN = 8;
    const int OBJ_GANNGRID = 9;
    const int OBJ_FIBOTIMES = 11;
    const int OBJ_FIBOFAN = 12;
    const int OBJ_FIBOARC = 13;
    const int OBJ_EXPANSION = 14;
    const int OBJ_FIBOCHANNEL = 15;*/
        const int OBJ_RECTANGLE = 16;
        /*const int OBJ_TRIANGLE = 17;
    const int OBJ_ELLIPSE = 18;
    const int OBJ_PITCHFORK = 19;
    const int OBJ_CYCLES = 20;*/
        const int OBJ_TEXT = 21;
        const int OBJ_ARROW = 22;
        const int OBJ_LABEL = 23;

        const int OBJPROP_TIME1 = 0;
        const int OBJPROP_PRICE1 = 1;
        const int OBJPROP_TIME2 = 2;
        const int OBJPROP_PRICE2 = 3;
        const int OBJPROP_TIME3 = 4;
        const int OBJPROP_PRICE3 = 5;
        const int OBJPROP_COLOR = 6;
        const int OBJPROP_STYLE = 7;
        const int OBJPROP_WIDTH = 8;
        const int OBJPROP_BACK = 9;
        const int OBJPROP_RAY = 10;
        const int OBJPROP_ELLIPSE = 11;
        //const int OBJPROP_SCALE = 12;
        const int OBJPROP_ANGLE = 13;
        //angle for text rotation
        const int OBJPROP_ARROWCODE = 14;
        const int OBJPROP_TIMEFRAMES = 15;
        //const int OBJPROP_DEVIATION = 16;
        const int OBJPROP_FONTSIZE = 100;
        const int OBJPROP_CORNER = 101;
        const int OBJPROP_XDISTANCE = 102;
        const int OBJPROP_YDISTANCE = 103;
        const int OBJPROP_FIBOLEVELS = 200;
        const int OBJPROP_LEVELCOLOR = 201;
        const int OBJPROP_LEVELSTYLE = 202;
        const int OBJPROP_LEVELWIDTH = 203;
        const int OBJPROP_FIRSTLEVEL = 210;

        const int PERIOD_M1 = 1;
        const int PERIOD_M5 = 5;
        const int PERIOD_M15 = 15;
        const int PERIOD_M30 = 30;
        const int PERIOD_H1 = 60;
        const int PERIOD_H4 = 240;
        const int PERIOD_D1 = 1440;
        const int PERIOD_W1 = 10080;
        const int PERIOD_MN1 = 43200;

        const int TIME_DATE = 1;
        const int TIME_MINUTES = 2;
        const int TIME_SECONDS = 4;

        const int MODE_MAIN = 0;
        const int MODE_BASE = 0;
        const int MODE_PLUSDI = 1;
        const int MODE_MINUSDI = 2;
        const int MODE_SIGNAL = 1;

        const int MODE_UPPER = 1;
        const int MODE_LOWER = 2;

        const int MODE_GATORLIPS = 3;
        const int MODE_GATORJAW = 1;
        const int MODE_GATORTEETH = 2;

        const int CLR_NONE = 32768;

        const int White = 16777215;
        const int Snow = 16448255;
        const int MintCream = 16449525;
        const int LavenderBlush = 16118015;
        const int AliceBlue = 16775408;
        const int Honeydew = 15794160;
        const int Ivory = 15794175;
        const int Seashell = 15660543;
        const int WhiteSmoke = 16119285;
        const int OldLace = 15136253;
        const int MistyRose = 14804223;
        const int Lavender = 16443110;
        const int Linen = 15134970;
        const int LightCyan = 16777184;
        const int LightYellow = 14745599;
        const int Cornsilk = 14481663;
        const int PapayaWhip = 14020607;
        const int AntiqueWhite = 14150650;
        const int Beige = 14480885;
        const int LemonChiffon = 13499135;
        const int BlanchedAlmond = 13495295;
        const int LightGoldenrod = 13826810;
        const int Bisque = 12903679;
        const int Pink = 13353215;
        const int PeachPuff = 12180223;
        const int Gainsboro = 14474460;
        const int LightPink = 12695295;
        const int Moccasin = 11920639;
        const int NavajoWhite = 11394815;
        const int Wheat = 11788021;
        const int LightGray = 13882323;
        const int PaleTurquoise = 15658671;
        const int PaleGoldenrod = 11200750;
        const int PowderBlue = 15130800;
        const int Thistle = 14204888;
        const int PaleGreen = 10025880;
        const int LightBlue = 15128749;
        const int LightSteelBlue = 14599344;
        const int LightSkyBlue = 16436871;
        const int Silver = 12632256;
        const int Aquamarine = 13959039;
        const int LightGreen = 9498256;
        const int Khaki = 9234160;
        const int Plum = 14524637;
        const int LightSalmon = 8036607;
        const int SkyBlue = 15453831;
        const int LightCoral = 8421616;
        const int Violet = 15631086;
        const int Salmon = 7504122;
        const int HotPink = 11823615;
        const int BurlyWood = 8894686;
        const int DarkSalmon = 8034025;
        const int Tan = 9221330;
        const int MediumSlateBlue = 15624315;
        const int SandyBrown = 6333684;
        const int DarkGray = 11119017;
        const int CornflowerBlue = 15570276;
        const int Coral = 5275647;
        const int PaleVioletRed = 9662683;
        const int MediumPurple = 14381203;
        const int Orchid = 14053594;
        const int RosyBrown = 9408444;
        const int Tomato = 4678655;
        const int DarkSeaGreen = 9419919;
        const int Cyan = 16776960;
        const int MediumAquamarine = 11193702;
        const int GreenYellow = 3145645;
        const int MediumOrchid = 13850042;
        const int IndianRed = 6053069;
        const int DarkKhaki = 7059389;
        const int SlateBlue = 13458026;
        const int RoyalBlue = 14772545;
        const int Turquoise = 13688896;
        const int DodgerBlue = 16748574;
        const int MediumTurquoise = 13422920;
        const int DeepPink = 9639167;
        const int LightSlateGray = 10061943;
        const int BlueViolet = 14822282;
        const int Peru = 4163021;
        const int SlateGray = 9470064;
        const int Gray = 8421504;
        const int Red = 255;
        const int Magenta = 16711935;
        const int Blue = 16711680;
        const int DeepSkyBlue = 16760576;
        const int Aqua = 16776960;
        const int SpringGreen = 8388352;
        const int Lime = 65280;
        const int Chartreuse = 65407;
        const int Yellow = 65535;
        const int Gold = 55295;
        const int Orange = 42495;
        const int DarkOrange = 36095;
        const int OrangeRed = 17919;
        const int LimeGreen = 3329330;
        const int YellowGreen = 3329434;
        const int DarkOrchid = 13382297;
        const int CadetBlue = 10526303;
        const int LawnGreen = 64636;
        const int MediumSpringGreen = 10156544;
        const int Goldenrod = 2139610;
        const int SteelBlue = 11829830;
        const int Crimson = 3937500;
        const int Chocolate = 1993170;
        const int MediumSeaGreen = 7451452;
        const int MediumVioletRed = 8721863;
        const int FireBrick = 2237106;
        const int DarkViolet = 13828244;
        const int LightSeaGreen = 11186720;
        const int DimGray = 6908265;
        const int DarkTurquoise = 13749760;
        const int Brown = 2763429;
        const int MediumBlue = 13434880;
        const int Sienna = 2970272;
        const int DarkSlateBlue = 9125192;
        const int DarkGoldenrod = 755384;
        const int SeaGreen = 5737262;
        const int OliveDrab = 2330219;
        const int ForestGreen = 2263842;
        const int SaddleBrown = 1262987;
        const int DarkOliveGreen = 3107669;
        const int DarkBlue = 9109504;
        const int MidnightBlue = 7346457;
        const int Indigo = 8519755;
        const int Maroon = 128;
        const int Purple = 8388736;
        const int Navy = 8388608;
        const int Teal = 8421376;
        const int Green = 32768;
        const int Olive = 32896;
        const int DarkSlateGray = 5197615;
        const int DarkGreen = 25600;
        const int Fuchsia = 16711935;
        const int Black = 0;

        const int SYMBOL_LEFTPRICE = 5;
        const int SYMBOL_RIGHTPRICE = 6;

        const int SYMBOL_ARROWUP = 241;
        const int SYMBOL_ARROWDOWN = 242;
        const int SYMBOL_STOPSIGN = 251;
        /*
const int SYMBOL_THUMBSUP = 67;
const int SYMBOL_THUMBSDOWN = 68;	
const int SYMBOL_CHECKSIGN = 25;
*/

        public const int MODE_ASCEND = 1;
        public const int MODE_DESCEND = 2;

        const int MODE_TENKANSEN = 1;
        const int MODE_KIJUNSEN = 2;
        const int MODE_SENKOUSPANA = 3;
        const int MODE_SENKOUSPANB = 4;
        const int MODE_CHINKOUSPAN = 5;
        const int OP_BUY = 0;
        const int OP_SELL = 1;
        const int OP_BUYLIMIT = 2;
        const int OP_SELLLIMIT = 3;
        const int OP_BUYSTOP = 4;
        const int OP_SELLSTOP = 5;
        const int OBJ_PERIOD_M1 = 0x1;
        const int OBJ_PERIOD_M5 = 0x2;
        const int OBJ_PERIOD_M15 = 0x4;
        const int OBJ_PERIOD_M30 = 0x8;
        const int OBJ_PERIOD_H1 = 0x10;
        const int OBJ_PERIOD_H4 = 0x20;
        const int OBJ_PERIOD_D1 = 0x40;
        const int OBJ_PERIOD_W1 = 0x80;
        const int OBJ_PERIOD_MN1 = 0x100;
        const int OBJ_ALL_PERIODS = 0x1ff;

        const int REASON_REMOVE = 1;
        const int REASON_RECOMPILE = 2;
        const int REASON_CHARTCHANGE = 3;
        const int REASON_CHARTCLOSE = 4;
        const int REASON_PARAMETERS = 5;
        const int REASON_ACCOUNT = 6;
        const int ERR_NO_ERROR = 0;
        const int ERR_NO_RESULT = 1;
        const int ERR_COMMON_ERROR = 2;
        const int ERR_INVALID_TRADE_PARAMETERS = 3;
        const int ERR_SERVER_BUSY = 4;
        const int ERR_OLD_VERSION = 5;
        const int ERR_NO_CONNECTION = 6;
        const int ERR_NOT_ENOUGH_RIGHTS = 7;
        const int ERR_TOO_FREQUENT_REQUESTS = 8;
        const int ERR_MALFUNCTIONAL_TRADE = 9;
        const int ERR_ACCOUNT_DISABLED = 64;
        const int ERR_INVALID_ACCOUNT = 65;
        const int ERR_TRADE_TIMEOUT = 128;
        const int ERR_INVALID_PRICE = 129;
        const int ERR_INVALID_STOPS = 130;
        const int ERR_INVALID_TRADE_VOLUME = 131;
        const int ERR_MARKET_CLOSED = 132;
        const int ERR_TRADE_DISABLED = 133;
        const int ERR_NOT_ENOUGH_MONEY = 134;
        const int ERR_PRICE_CHANGED = 135;
        const int ERR_OFF_QUOTES = 136;
        const int ERR_BROKER_BUSY = 137;
        const int ERR_REQUOTE = 138;
        const int ERR_ORDER_LOCKED = 139;
        const int ERR_LONG_POSITIONS_ONLY_ALLOWED = 140;
        const int ERR_TOO_MANY_REQUESTS = 141;
        const int ERR_TRADE_MODIFY_DENIED = 145;
        const int ERR_TRADE_CONTEXT_BUSY = 146;
        const int ERR_TRADE_EXPIRATION_DENIED = 147;
        const int ERR_TRADE_TOO_MANY_ORDERS = 148;
        const int ERR_TRADE_HEDGE_PROHIBITED = 149;
        const int ERR_TRADE_PROHIBITED_BY_FIFO = 150;
        const int ERR_NO_MQLERROR = 4000;
        const int ERR_WRONG_FUNCTION_POINTER = 4001;
        const int ERR_ARRAY_INDEX_OUT_OF_RANGE = 4002;
        const int ERR_NO_MEMORY_FOR_CALL_STACK = 4003;
        const int ERR_RECURSIVE_STACK_OVERFLOW = 4004;
        const int ERR_NOT_ENOUGH_STACK_FOR_PARAM = 4005;
        const int ERR_NO_MEMORY_FOR_PARAM_STRING = 4006;
        const int ERR_NO_MEMORY_FOR_TEMP_STRING = 4007;
        const int ERR_NOT_INITIALIZED_STRING = 4008;
        const int ERR_NOT_INITIALIZED_ARRAYSTRING = 4009;
        const int ERR_NO_MEMORY_FOR_ARRAYSTRING = 4010;
        const int ERR_TOO_LONG_STRING = 4011;
        const int ERR_REMAINDER_FROM_ZERO_DIVIDE = 4012;
        const int ERR_ZERO_DIVIDE = 4013;
        const int ERR_UNKNOWN_COMMAND = 4014;
        const int ERR_WRONG_JUMP = 4015;
        const int ERR_NOT_INITIALIZED_ARRAY = 4016;
        const int ERR_DLL_CALLS_NOT_ALLOWED = 4017;
        const int ERR_CANNOT_LOAD_LIBRARY = 4018;
        const int ERR_CANNOT_CALL_FUNCTION = 4019;
        const int ERR_EXTERNAL_CALLS_NOT_ALLOWED = 4020;
        const int ERR_NO_MEMORY_FOR_RETURNED_STR = 4021;
        const int ERR_SYSTEM_BUSY = 4022;
        const int ERR_INVALID_FUNCTION_PARAMSCNT = 4050;
        const int ERR_INVALID_FUNCTION_PARAMVALUE = 4051;
        const int ERR_STRING_FUNCTION_INTERNAL = 4052;
        const int ERR_SOME_ARRAY_ERROR = 4053;
        const int ERR_INCORRECT_SERIESARRAY_USING = 4054;
        const int ERR_CUSTOM_INDICATOR_ERROR = 4055;
        const int ERR_INCOMPATIBLE_ARRAYS = 4056;
        const int ERR_GLOBAL_VARIABLES_PROCESSING = 4057;
        const int ERR_GLOBAL_VARIABLE_NOT_FOUND = 4058;
        const int ERR_FUNC_NOT_ALLOWED_IN_TESTING = 4059;
        const int ERR_FUNCTION_NOT_CONFIRMED = 4060;
        const int ERR_SEND_MAIL_ERROR = 4061;
        const int ERR_STRING_PARAMETER_EXPECTED = 4062;
        const int ERR_INTEGER_PARAMETER_EXPECTED = 4063;
        const int ERR_DOUBLE_PARAMETER_EXPECTED = 4064;
        const int ERR_ARRAY_AS_PARAMETER_EXPECTED = 4065;
        const int ERR_HISTORY_WILL_UPDATED = 4066;
        const int ERR_TRADE_ERROR = 4067;
        const int ERR_END_OF_FILE = 4099;
        const int ERR_SOME_FILE_ERROR = 4100;
        const int ERR_WRONG_FILE_NAME = 4101;
        const int ERR_TOO_MANY_OPENED_FILES = 4102;
        const int ERR_CANNOT_OPEN_FILE = 4103;
        const int ERR_INCOMPATIBLE_FILEACCESS = 4104;
        const int ERR_NO_ORDER_SELECTED = 4105;
        const int ERR_UNKNOWN_SYMBOL = 4106;
        const int ERR_INVALID_PRICE_PARAM = 4107;
        const int ERR_INVALID_TICKET = 4108;
        const int ERR_TRADE_NOT_ALLOWED = 4109;
        const int ERR_LONGS_NOT_ALLOWED = 4110;
        const int ERR_SHORTS_NOT_ALLOWED = 4111;
        const int ERR_OBJECT_ALREADY_EXISTS = 4200;
        const int ERR_UNKNOWN_OBJECT_PROPERTY = 4201;
        const int ERR_OBJECT_DOES_NOT_EXIST = 4202;
        const int ERR_UNKNOWN_OBJECT_TYPE = 4203;
        const int ERR_NO_OBJECT_NAME = 4204;
        const int ERR_OBJECT_COORDINATES_ERROR = 4205;
        const int ERR_NO_SPECIFIED_SUBWINDOW = 4206;
        const int ERR_SOME_OBJECT_ERROR = 4207;
        class Mq4ChartObjects
        {
            private readonly ChartObjects _algoChartObjects;
            private readonly TimeSeries _timeSeries;

            private readonly Dictionary<string, Mq4Object> _mq4ObjectByName = new Dictionary<string, Mq4Object>();
            private readonly List<string> _mq4ObjectNameByIndex = new List<string>();

            public Mq4ChartObjects(ChartObjects chartObjects, TimeSeries timeSeries)
            {
                _algoChartObjects = chartObjects;
                _timeSeries = timeSeries;
            }

            public void Set(string name, int index, Mq4Double value)
            {
                if (!_mq4ObjectByName.ContainsKey(name))
                    return;
                _mq4ObjectByName[name].Set(index, value);
                _mq4ObjectByName[name].Draw();
            }
            public void SetText(string name, string text, int font_size, string font, int color)
            {
                if (!_mq4ObjectByName.ContainsKey(name))
                    return;

                Set(name, OBJPROP_COLOR, color);
            }







            private T GetObject<T>(string name) where T : Mq4Object
            {
                Mq4Object mq4Object;
                if (!_mq4ObjectByName.TryGetValue(name, out mq4Object))
                    return null;
                return mq4Object as T;
            }

        }

        abstract class Mq4Object : IDisposable
        {
            private readonly ChartObjects _chartObjects;

            protected Mq4Object(string name, int type, ChartObjects chartObjects)
            {
                Name = name;
                Type = type;
                _chartObjects = chartObjects;
            }

            public int Type { get; private set; }

            public string Name { get; private set; }

            protected DateTime Time1
            {
                get
                {
                    int seconds = Get(OBJPROP_TIME1);
                    return Mq4TimeSeries.ToDateTime(seconds);
                }
            }

            protected double Price1
            {
                get { return Get(OBJPROP_PRICE1); }
            }

            protected DateTime Time2
            {
                get
                {
                    int seconds = Get(OBJPROP_TIME2);
                    return Mq4TimeSeries.ToDateTime(seconds);
                }
            }

            protected double Price2
            {
                get { return Get(OBJPROP_PRICE2); }
            }

            protected Colors Color
            {
                get
                {
                    int intColor = Get(OBJPROP_COLOR);
                    if (intColor != CLR_NONE)
                        return Mq4Colors.GetColorByInteger(intColor);

                    return Colors.Yellow;
                }
            }

            protected int Width
            {
                get { return Get(OBJPROP_WIDTH); }
            }

            protected int Style
            {
                get { return Get(OBJPROP_STYLE); }
            }

            public abstract void Draw();

            private readonly Dictionary<int, Mq4Double> _properties = new Dictionary<int, Mq4Double> 
            {
                {
                    OBJPROP_WIDTH,
                    new Mq4Double(1)
                },
                {
                    OBJPROP_COLOR,
                    new Mq4Double(CLR_NONE)
                },
                {
                    OBJPROP_RAY,
                    new Mq4Double(1)
                },

                {
                    OBJPROP_LEVELCOLOR,
                    new Mq4Double(CLR_NONE)
                },
                {
                    OBJPROP_LEVELSTYLE,
                    new Mq4Double(0)
                },
                {
                    OBJPROP_LEVELWIDTH,
                    new Mq4Double(1)
                },
                {
                    OBJPROP_FIBOLEVELS,
                    new Mq4Double(9)
                },
                {
                    OBJPROP_FIRSTLEVEL + 0,
                    new Mq4Double(0)
                },
                {
                    OBJPROP_FIRSTLEVEL + 1,
                    new Mq4Double(0.236)
                },
                {
                    OBJPROP_FIRSTLEVEL + 2,
                    new Mq4Double(0.382)
                },
                {
                    OBJPROP_FIRSTLEVEL + 3,
                    new Mq4Double(0.5)
                },
                {
                    OBJPROP_FIRSTLEVEL + 4,
                    new Mq4Double(0.618)
                },
                {
                    OBJPROP_FIRSTLEVEL + 5,
                    new Mq4Double(1)
                },
                {
                    OBJPROP_FIRSTLEVEL + 6,
                    new Mq4Double(1.618)
                },
                {
                    OBJPROP_FIRSTLEVEL + 7,
                    new Mq4Double(2.618)
                },
                {
                    OBJPROP_FIRSTLEVEL + 8,
                    new Mq4Double(4.236)
                }
            };

            public virtual void Set(int index, Mq4Double value)
            {
                _properties[index] = value;
            }

            public Mq4Double Get(int index)
            {
                return _properties.ContainsKey(index) ? _properties[index] : new Mq4Double(0);
            }

            private readonly List<string> _addedAlgoChartObjects = new List<string>();

            protected void DrawText(string objectName, string text, int index, double yValue, VerticalAlignment verticalAlignment = VerticalAlignment.Center, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center, Colors? color = null)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawText(objectName, text, index, yValue, verticalAlignment, horizontalAlignment, color);
            }

            protected void DrawText(string objectName, string text, StaticPosition position, Colors? color = null)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawText(objectName, text, position, color);
            }

            protected void DrawLine(string objectName, int index1, double y1, int index2, double y2, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawLine(objectName, index1, y1, index2, y2, color, thickness, style);
            }

            protected void DrawLine(string objectName, DateTime date1, double y1, DateTime date2, double y2, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawLine(objectName, date1, y1, date2, y2, color, thickness, style);
            }

            protected void DrawVerticalLine(string objectName, DateTime date, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawVerticalLine(objectName, date, color, thickness, style);
            }

            protected void DrawVerticalLine(string objectName, int index, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawVerticalLine(objectName, index, color, thickness, style);
            }

            protected void DrawHorizontalLine(string objectName, double y, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawHorizontalLine(objectName, y, color, thickness, style);
            }

            public void Dispose()
            {
                foreach (var name in _addedAlgoChartObjects)
                {
                    _chartObjects.RemoveObject(name);
                }
            }
        }





        class Mq4Arrow : Mq4Object
        {
            private readonly TimeSeries _timeSeries;
            private int _index;

            public Mq4Arrow(string name, int type, ChartObjects chartObjects, TimeSeries timeSeries) : base(name, type, chartObjects)
            {
                _timeSeries = timeSeries;
            }

            public override void Set(int index, Mq4Double value)
            {
                base.Set(index, value);
                switch (index)
                {
                    case OBJPROP_TIME1:
                        _index = _timeSeries.GetIndexByTime(Time1);
                        break;
                }
            }

            private int ArrowCode
            {
                get { return Get(OBJPROP_ARROWCODE); }
            }

            public override void Draw()
            {
                string arrowString;
                HorizontalAlignment horizontalAlignment;
                switch (ArrowCode)
                {
                    case SYMBOL_RIGHTPRICE:
                        horizontalAlignment = HorizontalAlignment.Right;
                        arrowString = Price1.ToString();
                        break;
                    case SYMBOL_LEFTPRICE:
                        horizontalAlignment = HorizontalAlignment.Left;
                        arrowString = Price1.ToString();
                        break;
                    default:
                        arrowString = BrainExpert_v2_Robot.GetArrowByCode(ArrowCode);
                        horizontalAlignment = HorizontalAlignment.Center;
                        break;
                }
                DrawText(Name, arrowString, _index, Price1, VerticalAlignment.Center, horizontalAlignment, Color);
            }
        }















        Mq4Double OrderSend(Mq4String symbol, int cmd, Mq4Double volume, Mq4Double price, Mq4Double slippagePoints, Mq4Double stoploss, Mq4Double takeprofit, Mq4String comment = null, Mq4Double? magic = null, int expiration = 0,
        int arrow_color = CLR_NONE)
        {
            _lastError = ERR_NO_ERROR;
            if (magic == null)
                magic = 0;
            var label = magic.Value.ToString();

            var symbolObject = GetSymbol(symbol);
            var volumeInUnits = symbolObject.ToUnitsVolume(volume);

            switch (cmd)
            {
                case OP_BUY:
                case OP_SELL:
                    {
                        var tradeType = cmd == OP_BUY ? TradeType.Buy : TradeType.Sell;
                        var slippageInPrice = symbolObject.TickSize * slippagePoints;
                        var slippageInPips = (int)Math.Round((double)slippageInPrice / symbolObject.PipSize);
                        double? stopLossPips = null;
                        if (stoploss != 0)
                            stopLossPips = tradeType == TradeType.Buy ? (symbolObject.Ask - stoploss) / symbolObject.PipSize : (stoploss - symbolObject.Bid) / symbolObject.PipSize;
                        double? takeProfitPips = null;
                        if (takeprofit != 0)
                            takeProfitPips = tradeType == TradeType.Buy ? (takeprofit - symbolObject.Ask) / symbolObject.PipSize : (symbolObject.Bid - takeprofit) / symbolObject.PipSize;

                        var marketOrderResult = ExecuteMarketOrder(tradeType, symbolObject, volumeInUnits, label, stopLossPips, takeProfitPips, slippageInPips, comment);

                        if (marketOrderResult.IsSuccessful)
                            return GetTicket(marketOrderResult.Position);
                        else
                        {
                            _lastError = ToMq4ErrorCode(marketOrderResult.Error.Value);
                            return -1;
                        }
                    }
                case OP_BUYLIMIT:
                case OP_SELLLIMIT:
                case OP_BUYSTOP:
                case OP_SELLSTOP:
                    {
                        var tradeType = cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? TradeType.Buy : TradeType.Sell;

                        double? stopLossPips = null;
                        if (stoploss != 0)
                            stopLossPips = tradeType == TradeType.Buy ? (price - stoploss) / symbolObject.PipSize : (stoploss - price) / symbolObject.PipSize;
                        double? takeProfitPips = null;
                        if (takeprofit != 0)
                            takeProfitPips = tradeType == TradeType.Buy ? (takeprofit - price) / symbolObject.PipSize : (price - takeprofit) / symbolObject.PipSize;

                        TradeResult placeOrderResult;
                        if (cmd == OP_BUYLIMIT || cmd == OP_SELLLIMIT)
                            placeOrderResult = PlaceLimitOrder(tradeType, symbolObject, volumeInUnits, price, label, stopLossPips, takeProfitPips, expiration.ToNullableDateTime(), comment);
                        else
                            placeOrderResult = PlaceStopOrder(tradeType, symbolObject, volumeInUnits, price, label, stopLossPips, takeProfitPips, expiration.ToNullableDateTime(), comment);

                        if (placeOrderResult.IsSuccessful)
                            return GetTicket(placeOrderResult.PendingOrder);
                        else
                        {
                            _lastError = ToMq4ErrorCode(placeOrderResult.Error.Value);
                            return -1;
                        }
                    }
                default:
                    throw new Exception("Not supported by converter");
            }

            return 0;
        }
        Mq4Double OrderClose(int ticket, double lots, double price, int slippagePoints, int Color = CLR_NONE)
        {
            _lastError = ERR_NO_ERROR;

            var position = GetOrderByTicket(ticket) as Position;
            if (position == null)
            {
                _lastError = ERR_INVALID_TICKET;
                return false;
            }
            var symbolObject = MarketData.GetSymbol(position.SymbolCode);

            var volumeInUnits = symbolObject.ToUnitsVolume(lots);
            ClosePosition(position, volumeInUnits);

            if (!LastResult.IsSuccessful)
                _lastError = ToMq4ErrorCode(LastResult.Error.Value);

            return LastResult.IsSuccessful;
        }

        Mq4Double OrderModify(int ticket, double price, double stoploss, double takeprofit, int expiration, int arrow_color = CLR_NONE)
        {
            _lastError = ERR_NO_ERROR;

            var order = GetOrderByTicket(ticket);
            if (GetTakeProfit(order) == takeprofit && GetStopLoss(order) == stoploss && GetOpenPrice(order) == price)
            {
                _lastError = ERR_NO_RESULT;
                return false;
            }

            var position = order as Position;
            if (position != null)
            {
                ModifyPosition(position, stoploss.ToNullableDouble(), takeprofit.ToNullableDouble());
                if (!LastResult.IsSuccessful)
                    _lastError = ToMq4ErrorCode(LastResult.Error.Value);

                return LastResult.IsSuccessful;
            }

            var pendingOrder = (PendingOrder)order;
            var expirationTime = expiration.ToNullableDateTime();
            ModifyPendingOrder(pendingOrder, price, stoploss.ToNullableDouble(), takeprofit.ToNullableDouble(), expirationTime);

            if (!LastResult.IsSuccessful)
                _lastError = ToMq4ErrorCode(LastResult.Error.Value);

            return LastResult.IsSuccessful;
        }


    }

    //Custom Indicators Place Holder

    class Mq4DoubleComparer : IComparer<Mq4Double>
    {
        public int Compare(Mq4Double x, Mq4Double y)
        {
            return x.CompareTo(y);
        }
    }
    class Mq4String
    {
        private readonly string _value;

        public Mq4String(string value)
        {
            _value = value;
        }

        public static implicit operator Mq4String(string value)
        {
            return new Mq4String(value);
        }

        public static implicit operator Mq4String(int value)
        {
            return new Mq4String(value.ToString());
        }

        public static implicit operator Mq4String(Mq4Null mq4Null)
        {
            return new Mq4String(null);
        }

        public static implicit operator string(Mq4String mq4String)
        {
            if ((object)mq4String == null)
                return null;

            return mq4String._value;
        }

        public static implicit operator Mq4String(Mq4Double mq4Double)
        {
            return new Mq4String(mq4Double.ToString());
        }

        public static bool operator <(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) == -1;
        }

        public static bool operator >(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) == 1;
        }

        public static bool operator <(Mq4String x, string y)
        {
            return string.Compare(x._value, y) == -1;
        }

        public static bool operator >(Mq4String x, string y)
        {
            return string.Compare(x._value, y) == 1;
        }
        public static bool operator <=(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) <= 0;
        }

        public static bool operator >=(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) >= 0;
        }

        public static bool operator <=(Mq4String x, string y)
        {
            return string.Compare(x._value, y) <= 0;
        }

        public static bool operator >=(Mq4String x, string y)
        {
            return string.Compare(x._value, y) >= 0;
        }

        public static bool operator ==(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) == 0;
        }

        public static bool operator !=(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) != 0;
        }

        public static bool operator ==(Mq4String x, string y)
        {
            return string.Compare(x._value, y) == 0;
        }

        public static bool operator !=(Mq4String x, string y)
        {
            return string.Compare(x._value, y) != 0;
        }

        public override string ToString()
        {
            if ((object)this == null)
                return string.Empty;

            return _value.ToString();
        }

        public static readonly Mq4String Empty = new Mq4String(string.Empty);

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != this.GetType())
                return false;
            return Equals((Mq4String)obj);
        }

        protected bool Equals(Mq4String other)
        {
            return this == other;
        }

        public override int GetHashCode()
        {
            return (_value != null ? _value.GetHashCode() : 0);
        }
    }
    struct Mq4Char
    {
        char _char;

        public Mq4Char(byte code)
        {
            _char = Encoding.Unicode.GetString(new byte[] 
            {
                code,
                0
            })[0];
        }

        public Mq4Char(char @char)
        {
            _char = @char;
        }

        public static implicit operator char(Mq4Char mq4Char)
        {
            return mq4Char._char;
        }

        public static implicit operator Mq4Char(int code)
        {
            return new Mq4Char((byte)code);
        }

        public static implicit operator Mq4Char(string str)
        {
            if (string.IsNullOrEmpty(str) || str.Length == 0)
                return new Mq4Char(' ');
            return new Mq4Char(str[0]);
        }
    }
    struct Mq4Null
    {
        public static implicit operator string(Mq4Null mq4Null)
        {
            return (string)null;
        }

        public static implicit operator int(Mq4Null mq4Null)
        {
            return 0;
        }

        public static implicit operator double(Mq4Null mq4Null)
        {
            return 0;
        }
    }
    static class Comparers
    {
        public static IComparer<T> GetComparer<T>()
        {
            if (typeof(T) == typeof(Mq4Double))
                return (IComparer<T>)new Mq4DoubleComparer();

            return Comparer<T>.Default;
        }
    }
    static class DataSeriesExtensions
    {
        public static int InvertIndex(this DataSeries dataSeries, int index)
        {
            return dataSeries.Count - 1 - index;
        }

        public static Mq4Double Last(this DataSeries dataSeries, int shift, DataSeries sourceDataSeries)
        {
            return dataSeries[sourceDataSeries.Count - 1 - shift];
        }
    }
    static class TimeSeriesExtensions
    {
        public static DateTime Last(this TimeSeries timeSeries, int index)
        {
            return timeSeries[timeSeries.InvertIndex(index)];
        }

        public static int InvertIndex(this TimeSeries timeSeries, int index)
        {
            return timeSeries.Count - 1 - index;
        }

        public static int GetIndexByTime(this TimeSeries timeSeries, DateTime time)
        {
            var index = timeSeries.Count - 1;
            for (var i = timeSeries.Count - 1; i >= 0; i--)
            {
                if (timeSeries[i] < time)
                {
                    index = i + 1;
                    break;
                }
            }
            return index;
        }
    }
    static class Mq4Colors
    {
        public static Colors GetColorByInteger(int integer)
        {
            switch (integer)
            {
                case 16777215:
                    return Colors.White;
                case 16448255:
                    return Colors.Snow;
                case 16449525:
                    return Colors.MintCream;
                case 16118015:
                    return Colors.LavenderBlush;
                case 16775408:
                    return Colors.AliceBlue;
                case 15794160:
                    return Colors.Honeydew;
                case 15794175:
                    return Colors.Ivory;
                case 16119285:
                    return Colors.WhiteSmoke;
                case 15136253:
                    return Colors.OldLace;
                case 14804223:
                    return Colors.MistyRose;
                case 16443110:
                    return Colors.Lavender;
                case 15134970:
                    return Colors.Linen;
                case 16777184:
                    return Colors.LightCyan;
                case 14745599:
                    return Colors.LightYellow;
                case 14481663:
                    return Colors.Cornsilk;
                case 14020607:
                    return Colors.PapayaWhip;
                case 14150650:
                    return Colors.AntiqueWhite;
                case 14480885:
                    return Colors.Beige;
                case 13499135:
                    return Colors.LemonChiffon;
                case 13495295:
                    return Colors.BlanchedAlmond;
                case 12903679:
                    return Colors.Bisque;
                case 13353215:
                    return Colors.Pink;
                case 12180223:
                    return Colors.PeachPuff;
                case 14474460:
                    return Colors.Gainsboro;
                case 12695295:
                    return Colors.LightPink;
                case 11920639:
                    return Colors.Moccasin;
                case 11394815:
                    return Colors.NavajoWhite;
                case 11788021:
                    return Colors.Wheat;
                case 13882323:
                    return Colors.LightGray;
                case 15658671:
                    return Colors.PaleTurquoise;
                case 11200750:
                    return Colors.PaleGoldenrod;
                case 15130800:
                    return Colors.PowderBlue;
                case 14204888:
                    return Colors.Thistle;
                case 10025880:
                    return Colors.PaleGreen;
                case 15128749:
                    return Colors.LightBlue;
                case 14599344:
                    return Colors.LightSteelBlue;
                case 16436871:
                    return Colors.LightSkyBlue;
                case 12632256:
                    return Colors.Silver;
                case 13959039:
                    return Colors.Aquamarine;
                case 9498256:
                    return Colors.LightGreen;
                case 9234160:
                    return Colors.Khaki;
                case 14524637:
                    return Colors.Plum;
                case 8036607:
                    return Colors.LightSalmon;
                case 15453831:
                    return Colors.SkyBlue;
                case 8421616:
                    return Colors.LightCoral;
                case 15631086:
                    return Colors.Violet;
                case 7504122:
                    return Colors.Salmon;
                case 11823615:
                    return Colors.HotPink;
                case 8894686:
                    return Colors.BurlyWood;
                case 8034025:
                    return Colors.DarkSalmon;
                case 9221330:
                    return Colors.Tan;
                case 15624315:
                    return Colors.MediumSlateBlue;
                case 6333684:
                    return Colors.SandyBrown;
                case 11119017:
                    return Colors.DarkGray;
                case 15570276:
                    return Colors.CornflowerBlue;
                case 5275647:
                    return Colors.Coral;
                case 9662683:
                    return Colors.PaleVioletRed;
                case 14381203:
                    return Colors.MediumPurple;
                case 14053594:
                    return Colors.Orchid;
                case 9408444:
                    return Colors.RosyBrown;
                case 4678655:
                    return Colors.Tomato;
                case 9419919:
                    return Colors.DarkSeaGreen;
                case 11193702:
                    return Colors.MediumAquamarine;
                case 3145645:
                    return Colors.GreenYellow;
                case 13850042:
                    return Colors.MediumOrchid;
                case 6053069:
                    return Colors.IndianRed;
                case 7059389:
                    return Colors.DarkKhaki;
                case 13458026:
                    return Colors.SlateBlue;
                case 14772545:
                    return Colors.RoyalBlue;
                case 13688896:
                    return Colors.Turquoise;
                case 16748574:
                    return Colors.DodgerBlue;
                case 13422920:
                    return Colors.MediumTurquoise;
                case 9639167:
                    return Colors.DeepPink;
                case 10061943:
                    return Colors.LightSlateGray;
                case 14822282:
                    return Colors.BlueViolet;
                case 4163021:
                    return Colors.Peru;
                case 9470064:
                    return Colors.SlateGray;
                case 8421504:
                    return Colors.Gray;
                case 255:
                    return Colors.Red;
                case 16711935:
                    return Colors.Magenta;
                case 16711680:
                    return Colors.Blue;
                case 16760576:
                    return Colors.DeepSkyBlue;
                case 16776960:
                    return Colors.Aqua;
                case 8388352:
                    return Colors.SpringGreen;
                case 65280:
                    return Colors.Lime;
                case 65407:
                    return Colors.Chartreuse;
                case 65535:
                    return Colors.Yellow;
                case 55295:
                    return Colors.Gold;
                case 42495:
                    return Colors.Orange;
                case 36095:
                    return Colors.DarkOrange;
                case 17919:
                    return Colors.OrangeRed;
                case 3329330:
                    return Colors.LimeGreen;
                case 3329434:
                    return Colors.YellowGreen;
                case 13382297:
                    return Colors.DarkOrchid;
                case 10526303:
                    return Colors.CadetBlue;
                case 64636:
                    return Colors.LawnGreen;
                case 10156544:
                    return Colors.MediumSpringGreen;
                case 2139610:
                    return Colors.Goldenrod;
                case 11829830:
                    return Colors.SteelBlue;
                case 3937500:
                    return Colors.Crimson;
                case 1993170:
                    return Colors.Chocolate;
                case 7451452:
                    return Colors.MediumSeaGreen;
                case 8721863:
                    return Colors.MediumVioletRed;
                case 13828244:
                    return Colors.DarkViolet;
                case 11186720:
                    return Colors.LightSeaGreen;
                case 6908265:
                    return Colors.DimGray;
                case 13749760:
                    return Colors.DarkTurquoise;
                case 2763429:
                    return Colors.Brown;
                case 13434880:
                    return Colors.MediumBlue;
                case 2970272:
                    return Colors.Sienna;
                case 9125192:
                    return Colors.DarkSlateBlue;
                case 755384:
                    return Colors.DarkGoldenrod;
                case 5737262:
                    return Colors.SeaGreen;
                case 2330219:
                    return Colors.OliveDrab;
                case 2263842:
                    return Colors.ForestGreen;
                case 1262987:
                    return Colors.SaddleBrown;
                case 3107669:
                    return Colors.DarkOliveGreen;
                case 9109504:
                    return Colors.DarkBlue;
                case 7346457:
                    return Colors.MidnightBlue;
                case 8519755:
                    return Colors.Indigo;
                case 128:
                    return Colors.Maroon;
                case 8388736:
                    return Colors.Purple;
                case 8388608:
                    return Colors.Navy;
                case 8421376:
                    return Colors.Teal;
                case 32768:
                    return Colors.Green;
                case 32896:
                    return Colors.Olive;
                case 5197615:
                    return Colors.DarkSlateGray;
                case 25600:
                    return Colors.DarkGreen;
                case 0:
                default:
                    return Colors.Black;
            }
        }
    }
    static class EventExtensions
    {
        public static void Raise<T1, T2>(this Action<T1, T2> action, T1 arg1, T2 arg2)
        {
            if (action != null)
                action(arg1, arg2);
        }
    }
    static class Mq4LineStyles
    {
        public static LineStyle ToLineStyle(int style)
        {
            switch (style)
            {
                case 1:
                    return LineStyle.Lines;
                case 2:
                    return LineStyle.Dots;
                case 3:
                case 4:
                    return LineStyle.LinesDots;
                default:
                    return LineStyle.Solid;
            }
        }
    }
    class Mq4TimeSeries
    {
        private readonly TimeSeries _timeSeries;
        private static readonly DateTime StartDateTime = new DateTime(1970, 1, 1);

        public Mq4TimeSeries(TimeSeries timeSeries)
        {
            _timeSeries = timeSeries;
        }

        public static int ToInteger(DateTime dateTime)
        {
            return (int)(dateTime - StartDateTime).TotalSeconds;
        }

        public static DateTime ToDateTime(int seconds)
        {
            return StartDateTime.AddSeconds(seconds);
        }

        public int this[int index]
        {
            get
            {
                if (index < 0 || index >= _timeSeries.Count)
                    return 0;

                DateTime dateTime = _timeSeries[_timeSeries.Count - 1 - index];

                return ToInteger(dateTime);
            }
        }
    }
    static class ConvertExtensions
    {
        public static double? ToNullableDouble(this double protection)
        {
            if (protection == 0)
                return null;
            return protection;
        }

        public static DateTime? ToNullableDateTime(this int time)
        {
            if (time == 0)
                return null;

            return Mq4TimeSeries.ToDateTime(time);
        }

        public static long ToUnitsVolume(this Symbol symbol, double lots)
        {
            return symbol.NormalizeVolume(symbol.ToNotNormalizedUnitsVolume(lots));
        }

        public static double ToNotNormalizedUnitsVolume(this Symbol symbol, double lots)
        {
            if (symbol.Code.Contains("XAU") || symbol.Code.Contains("XAG"))
                return 100 * lots;

            return 100000 * lots;
        }

        public static double ToLotsVolume(this Symbol symbol, long volume)
        {
            if (symbol.Code.Contains("XAU") || symbol.Code.Contains("XAG"))
                return volume * 1.0 / 100;

            return volume * 1.0 / 100000;
        }
    }
    struct Mq4Double : IComparable, IComparable<Mq4Double>
    {
        private readonly double _value;

        public Mq4Double(double value)
        {
            _value = value;
        }

        public static implicit operator double(Mq4Double property)
        {
            return property._value;
        }

        public static implicit operator int(Mq4Double property)
        {
            return (int)property._value;
        }

        public static implicit operator bool(Mq4Double property)
        {
            return (int)property._value != 0;
        }

        public static implicit operator Mq4Double(double value)
        {
            return new Mq4Double(value);
        }

        public static implicit operator Mq4Double(int value)
        {
            return new Mq4Double(value);
        }

        public static implicit operator Mq4Double(bool value)
        {
            return new Mq4Double(value ? 1 : 0);
        }

        public static implicit operator Mq4Double(Mq4Null value)
        {
            return new Mq4Double(0);
        }

        public static Mq4Double operator +(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value + d2._value);
        }

        public static Mq4Double operator -(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value - d2._value);
        }

        public static Mq4Double operator -(Mq4Double d)
        {
            return new Mq4Double(-d._value);
        }

        public static Mq4Double operator +(Mq4Double d)
        {
            return new Mq4Double(+d._value);
        }

        public static Mq4Double operator *(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value * d2._value);
        }

        public static Mq4Double operator /(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value / d2._value);
        }

        public static bool operator ==(Mq4Double d1, Mq4Double d2)
        {
            return d1._value == d2._value;
        }

        public static bool operator >(Mq4Double d1, Mq4Double d2)
        {
            return d1._value > d2._value;
        }

        public static bool operator >=(Mq4Double d1, Mq4Double d2)
        {
            return d1._value >= d2._value;
        }

        public static bool operator <(Mq4Double d1, Mq4Double d2)
        {
            return d1._value < d2._value;
        }

        public static bool operator <=(Mq4Double d1, Mq4Double d2)
        {
            return d1._value <= d2._value;
        }

        public static bool operator !=(Mq4Double d1, Mq4Double d2)
        {
            return d1._value != d2._value;
        }

        public override string ToString()
        {
            return _value.ToString();
        }

        public int CompareTo(object obj)
        {
            return _value.CompareTo(obj);
        }

        public int CompareTo(Mq4Double obj)
        {
            return _value.CompareTo(obj);
        }
    }
    class Mq4DoubleTwoDimensionalArray
    {
        private List<Mq4Double> _data = new List<Mq4Double>();
        private List<Mq4DoubleArray> _arrays = new List<Mq4DoubleArray>();
        private readonly Mq4Double _defaultValue;
        private readonly int _size2;

        public Mq4DoubleTwoDimensionalArray(int size2)
        {
            _defaultValue = 0;
            _size2 = size2;
        }

        public void Add(Mq4Double value)
        {
            _data.Add(value);
        }

        private void EnsureCountIsEnough(int index)
        {
            while (_arrays.Count <= index)
                _arrays.Add(new Mq4DoubleArray());
        }

        public void Initialize(Mq4Double value)
        {
            for (var i = 0; i < _data.Count; i++)
                _data[i] = value;
        }

        public int Range(int index)
        {
            if (index == 0)
                return _data.Count;
            return this[0].Length;
        }

        public Mq4DoubleArray this[int index]
        {
            get
            {
                if (index < 0)
                    return new Mq4DoubleArray();

                EnsureCountIsEnough(index);

                return _arrays[index];
            }
        }

        public Mq4Double this[int index1, int index2]
        {
            get
            {
                if (index1 < 0)
                    return 0;

                EnsureCountIsEnough(index1);

                return _arrays[index1][index2];
            }
            set
            {
                if (index1 < 0)
                    return;

                EnsureCountIsEnough(index1);

                _arrays[index1][index2] = value;
            }
        }
    }
    class Mq4DoubleArray : IMq4DoubleArray, IEnumerable
    {
        private List<Mq4Double> _data = new List<Mq4Double>();
        private readonly Mq4Double _defaultValue;

        public Mq4DoubleArray(int size = 0)
        {
            _defaultValue = 0;
        }

        public IEnumerator GetEnumerator()
        {
            return _data.GetEnumerator();
        }

        private bool _isInverted;
        public bool IsInverted
        {
            get { return _isInverted; }
            set { _isInverted = value; }
        }

        public void Add(Mq4Double value)
        {
            _data.Add(value);
        }

        private void EnsureCountIsEnough(int index)
        {
            while (_data.Count <= index)
                _data.Add(_defaultValue);
        }

        public int Length
        {
            get { return _data.Count; }
        }

        public void Resize(int newSize)
        {
            while (newSize < _data.Count)
                _data.RemoveAt(_data.Count - 1);

            while (newSize > _data.Count)
                _data.Add(_defaultValue);
        }

        public Mq4Double this[int index]
        {
            get
            {
                if (index < 0)
                    return _defaultValue;

                EnsureCountIsEnough(index);

                return _data[index];
            }
            set
            {
                if (index < 0)
                    return;

                EnsureCountIsEnough(index);

                _data[index] = value;
                Changed.Raise(index, value);
            }
        }
        public event Action<int, Mq4Double> Changed;
    }
    class Mq4MarketDataSeries : IMq4DoubleArray
    {
        private DataSeries _dataSeries;

        public Mq4MarketDataSeries(DataSeries dataSeries)
        {
            _dataSeries = dataSeries;
        }

        public Mq4Double this[int index]
        {
            get { return _dataSeries.Last(index); }
            set { }
        }

        public int Length
        {
            get { return _dataSeries.Count; }
        }

        public void Resize(int newSize)
        {
        }
    }
    class Mq4StringArray : IEnumerable
    {
        private List<Mq4String> _data = new List<Mq4String>();
        private readonly Mq4String _defaultValue;

        public Mq4StringArray(int size = 0)
        {
            _defaultValue = "";
        }

        public IEnumerator GetEnumerator()
        {
            return _data.GetEnumerator();
        }

        private bool _isInverted;
        public bool IsInverted
        {
            get { return _isInverted; }
            set { _isInverted = value; }
        }

        public void Add(Mq4String value)
        {
            _data.Add(value);
        }

        private void EnsureCountIsEnough(int index)
        {
            while (_data.Count <= index)
                _data.Add(_defaultValue);
        }

        public int Length
        {
            get { return _data.Count; }
        }

        public void Resize(int newSize)
        {
            while (newSize < _data.Count)
                _data.RemoveAt(_data.Count - 1);

            while (newSize > _data.Count)
                _data.Add(_defaultValue);
        }

        public Mq4String this[int index]
        {
            get
            {
                if (index < 0)
                    return _defaultValue;

                EnsureCountIsEnough(index);

                return _data[index];
            }
            set
            {
                if (index < 0)
                    return;

                EnsureCountIsEnough(index);

                _data[index] = value;
            }
        }
    }
    interface IMq4DoubleArray
    {
        Mq4Double this[int index] { get; set; }
        int Length { get; }
        void Resize(int newSize);
    }
    class Mq4ArrayToDataSeriesConverter
    {
        private readonly Mq4DoubleArray _mq4Array;
        private readonly IndicatorDataSeries _dataSeries;

        public Mq4ArrayToDataSeriesConverter(Mq4DoubleArray mq4Array, IndicatorDataSeries dataSeries)
        {
            _mq4Array = mq4Array;
            _dataSeries = dataSeries;
            _mq4Array.Changed += OnValueChanged;
            CopyAllValues();
        }

        private void CopyAllValues()
        {
            for (var i = 0; i < _mq4Array.Length; i++)
            {
                if (_mq4Array.IsInverted)
                    _dataSeries[_mq4Array.Length - i] = _mq4Array[i];
                else
                    _dataSeries[i] = _mq4Array[i];
            }
        }

        private void OnValueChanged(int index, Mq4Double value)
        {
            int indexToSet;
            if (_mq4Array.IsInverted)
                indexToSet = _mq4Array.Length - index;
            else
                indexToSet = index;

            if (indexToSet < 0)
                return;

            _dataSeries[indexToSet] = value;
        }
    }
    class Mq4ArrayToDataSeriesConverterFactory
    {
        private readonly Dictionary<Mq4DoubleArray, IndicatorDataSeries> _cachedAdapters = new Dictionary<Mq4DoubleArray, IndicatorDataSeries>();
        private Func<IndicatorDataSeries> _dataSeriesFactory;

        public Mq4ArrayToDataSeriesConverterFactory(Func<IndicatorDataSeries> dataSeriesFactory)
        {
            _dataSeriesFactory = dataSeriesFactory;
        }

        public DataSeries Create(Mq4DoubleArray mq4Array)
        {
            IndicatorDataSeries dataSeries;

            if (_cachedAdapters.TryGetValue(mq4Array, out dataSeries))
                return dataSeries;

            dataSeries = _dataSeriesFactory();
            new Mq4ArrayToDataSeriesConverter(mq4Array, dataSeries);
            _cachedAdapters[mq4Array] = dataSeries;

            return dataSeries;
        }
    }

}

 

 


@tgjobscv
Replies

tgjobscv
16 Dec 2019, 19:50

BrainWashing algo

 

What wrong with code ?

//#reference: ..\Indicators\PriceChannel_Stop_v1_Indicator.algo
//#reference: ..\Indicators\iTrend_Indicator.algo
// ------------------------------------------------------------                   
// Paste this code into your cAlgo editor. 
// -----------------------------------------------------------
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using cAlgo.API.Requests;
// ---------------------------------------------------------------------------                   
// Converted from MQ4 to cAlgo with http://2calgo.com
// ---------------------------------------------------------------------------

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.FullAccess)]
    public class ConvertedRobot : Robot
    {
        Mq4Double Mq4Init()
        {
            s_symbol = Symbol.Code;

            digit = MarketInfo(s_symbol, MODE_DIGITS);
            if (digit == 2 || digit == 4)
                point = 1;
            if (digit == 3 || digit == 5)
                point = 10;
            if (digit == 6)
                point = 100;

            if (UseAutoMagic)
                MAGIC = GetMagicFunc();
            else
                MAGIC = ManualMagic;

            return 0;
            return 0;
        }
        Mq4Double deinitFunc()
        {
            Comment("");
            return 0;
            return 0;
        }
        Mq4Double Mq4Start()
        {
            Mq4Double Sellpre = 0;
            Mq4Double Sellnow = 0;
            Mq4Double Buypre = 0;
            Mq4Double Buynow = 0;
            Mq4Double i = 0;
            Mq4Double te2 = 0;
            Mq4Double te1 = 0;
            Mq4Double ts2 = 0;
            Mq4Double ts1 = 0;
            Mq4String et1 = "";
            Mq4String st1 = "";
            Mq4Double canEnterNewTrade = false;

            if (Bars < 100)
            {
                Mq4Print("bars less than 100");
                return 0;
            }
            if (lTrailingStop == 0 && sTrailingStop == 0 && UsePCSTrail)
                PCS_TSFunc();







            canEnterNewTrade = true;
            if (canEnterNewTrade)
            {
                st1 = normalizeTimeFunc(Trade_startFrom);
                et1 = normalizeTimeFunc(Trade_endAt);
                ts1 = StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + st1);
                ts2 = ts1;
                te1 = StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + et1);
                te2 = te1;
                if (te1 < ts1)
                {
                    ts1 -= 24 * 60 * 60;
                    te2 += 24 * 60 * 60;
                }
                canEnterNewTrade = ((TimeCurrent() >= ts1 && TimeCurrent() <= te1) || (TimeCurrent() >= ts2 && TimeCurrent() <= te2));
            }







            if (CloseOnFriday && TimeDayOfWeek(TimeCurrent()) == 5)
            {
                if (TimeHour(TimeCurrent()) > FridayCloseHour || (TimeHour(TimeCurrent()) == FridayCloseHour && TimeMinute(TimeCurrent()) >= FridayCloseMinute))
                {
                    for (i = OrdersTotal() - 1; i >= 0; i--)
                    {
                        dummyResult = OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
                        if (OrderSymbol() != s_symbol)
                            continue;
                        if (OrderMagicNumber() != MAGIC)
                            continue;

                        if (OrderType() == OP_BUY)
                        {
                            dummyResult = OrderClose(OrderTicket(), OrderLots(), Ask, 0, CLR_NONE);
                            continue;
                        }
                        if (OrderType() == OP_SELL)
                        {
                            dummyResult = OrderClose(OrderTicket(), OrderLots(), Bid, 0, CLR_NONE);
                            continue;
                        }
                    }
                    return 0;
                }
            }







            Buynow = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ChannelPeriod, Risk, 0, entrybar);
            Buypre = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ChannelPeriod, Risk, 0, entrybar + 1);
            Sellnow = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ChannelPeriod, Risk, 1, entrybar);
            Sellpre = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ChannelPeriod, Risk, 1, entrybar + 1);
            iTredn1 = iCustom<iTrend_Indicator>(NULL, 0, "iTrend", Price, ItPeriod, PowerPeriod, MaMethod, LevelBars, LevelFactor, 0,
            entrybar);
            iTredn2 = iCustom<iTrend_Indicator>(NULL, 0, "iTrend", Price, ItPeriod, PowerPeriod, MaMethod, LevelBars, LevelFactor, 1,
            entrybar);
            iTredn3 = iCustom<iTrend_Indicator>(NULL, 0, "iTrend", Price, ItPeriod, PowerPeriod, MaMethod, LevelBars, LevelFactor, 2,
            entrybar);







            if (!ExistPositionsFunc() && canEnterNewTrade)
            {

                if (Buynow != EMPTY_VALUE && Buypre == EMPTY_VALUE && Sellnow == EMPTY_VALUE && Sellpre == EMPTY_VALUE && (((ItrendFilter && iTredn1 > iTredn3 && iTredn1 > iTredn2 && canOpenFunc(OP_BUY)) || !ItrendFilter) && canOpenFunc(OP_BUY)))
                {
                    OpenBuyFunc();
                    return 0;
                }

                if (Buynow == EMPTY_VALUE && Buypre == EMPTY_VALUE && Sellnow != EMPTY_VALUE && Sellpre == EMPTY_VALUE && (((ItrendFilter && iTredn2 > iTredn3 && iTredn2 > iTredn1 && canOpenFunc(OP_SELL)) || !ItrendFilter) && canOpenFunc(OP_SELL)))
                {
                    OpenSellFunc();
                    return 0;
                }

            }

            if (lTrailingStop > 0)
                TrailingPositionsBuyFunc();
            if (sTrailingStop > 0)
                TrailingPositionsSellFunc();
            if (useCloseOnTrendChange)
                CheckForCloseFunc();
            if (useCloseTradeRules)
                CheckForClose2Func();

            return 0;
            return 0;
        }
        Mq4Double ExistPositionsFunc()
        {
            Mq4Double i = 0;
            for (i = 0; i < OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
                {
                    if (OrderSymbol() == s_symbol && OrderMagicNumber() == MAGIC)
                    {
                        return true;
                    }
                }
            }
            return false;
            return true;
        }
        void TrailingPositionsBuyFunc()
        {
            Mq4Double i = 0;
            for (i = 0; i < OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
                {
                    if (OrderSymbol() == s_symbol && OrderMagicNumber() == MAGIC)
                    {
                        if (OrderType() == OP_BUY)
                        {
                            if (Bid - OrderOpenPrice() > lTrailingStop * Point * point)
                            {
                                if (OrderStopLoss() < Bid - lTrailingStop * Point * point)
                                    ModifyStopLossFunc(Bid - lTrailingStop * Point * point);
                            }
                        }
                    }
                }
            }
            return;
        }
        void TrailingPositionsSellFunc()
        {
            Mq4Double i = 0;
            for (i = 0; i < OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
                {
                    if (OrderSymbol() == s_symbol && OrderMagicNumber() == MAGIC)
                    {
                        if (OrderType() == OP_SELL)
                        {
                            if (OrderOpenPrice() - Ask > sTrailingStop * Point * point)
                            {
                                if (OrderStopLoss() > Ask + sTrailingStop * Point * point || OrderStopLoss() == 0)
                                    ModifyStopLossFunc(Ask + sTrailingStop * Point * point);
                            }
                        }
                    }
                }
            }
            return;
        }
        void ModifyStopLossFunc(Mq4Double ldStopLoss)
        {
            Mq4String ErrLog = "";
            Mq4String ErrAlert = "";
            Mq4String ErrDesc = "";
            Mq4Double ErrorCode = 0;
            Mq4Double fm = false;

            fm = OrderModify(OrderTicket(), OrderOpenPrice(), ldStopLoss, OrderTakeProfit(), 0, CLR_NONE);

            if (fm == false)
            {
                ErrorCode = GetLastError();
                ErrDesc = ErrorDescription(ErrorCode);

                ErrAlert = StringConcatenate("Trailing StopMq4 Modification - Error ", ErrorCode, ": ", ErrDesc);
                if (ShowAlerts == true)
                    Alert(ErrAlert);

                ErrLog = StringConcatenate("Ask: ", MarketInfo(s_symbol, MODE_ASK), " Ticket: ", OrderTicket(), " StopMq4: ", OrderStopLoss(), " Trail: ", ldStopLoss);
                Mq4Print(ErrLog);
            }

            return;
        }
        void PCS_TSFunc()
        {
            Mq4Double sellTsMod = false;
            Mq4String ErrLog = "";
            Mq4String ErrAlert = "";
            Mq4String ErrDesc = "";
            Mq4Double ErrorCode = 0;
            Mq4Double buyTsMod = false;
            Mq4Double i = 0;
            Mq4Double dnLinepre = 0;
            Mq4Double dnLinenow = 0;
            Mq4Double upLinepre = 0;
            Mq4Double upLinenow = 0;
            RefreshRates();
            upLinenow = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ts_ChannelPeriod, ts_Risk, 4, ts_entrybar);
            upLinepre = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ts_ChannelPeriod, ts_Risk, 4, ts_entrybar + 1);
            dnLinenow = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ts_ChannelPeriod, ts_Risk, 5, ts_entrybar);
            dnLinepre = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", ts_ChannelPeriod, ts_Risk, 5, ts_entrybar + 1);







            for (i = 0; i <= OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false)
                    break;
                if (OrderMagicNumber() != MAGIC)
                    continue;
                if (OrderSymbol() != s_symbol)
                    continue;







                if (OrderType() == OP_BUY)
                {
                    if (upLinenow != EMPTY_VALUE && dnLinenow == EMPTY_VALUE && (OrderOpenPrice() + TrailStep * point) < upLinenow)
                    {
                        if (NormalizeDouble(upLinenow, digit) > NormalizeDouble(OrderStopLoss(), digit))
                        {
                            buyTsMod = OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(upLinenow, digit), OrderTakeProfit(), 0, Blue);

                            if (buyTsMod == false)
                            {
                                ErrorCode = GetLastError();
                                ErrDesc = ErrorDescription(ErrorCode);

                                ErrAlert = StringConcatenate("Trailing StopMq4 Modification ", ErrorCode, ": ", ErrDesc);
                                if (ShowAlerts == true)
                                    Alert(ErrAlert);

                                ErrLog = StringConcatenate("Ask: ", MarketInfo(s_symbol, MODE_ASK), " Ticket: ", OrderTicket(), " StopMq4: ", OrderStopLoss());
                                Mq4Print(ErrLog);
                            }
                        }
                    }
                    break;
                }







                if (OrderType() == OP_SELL)
                {
                    if (upLinenow == EMPTY_VALUE && dnLinenow != EMPTY_VALUE && (OrderOpenPrice() - TrailStep * point) > dnLinenow)
                    {
                        if (NormalizeDouble(dnLinenow, digit) < NormalizeDouble(OrderStopLoss(), digit) || OrderStopLoss() == 0)
                        {
                            sellTsMod = OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(dnLinenow, digit), OrderTakeProfit(), 0, Red);
                            if (sellTsMod == false)
                            {
                                ErrorCode = GetLastError();
                                ErrDesc = ErrorDescription(ErrorCode);

                                ErrAlert = StringConcatenate("Trailing StopMq4 Modification ", ErrorCode, ": ", ErrDesc);
                                if (ShowAlerts == true)
                                    Alert(ErrAlert);

                                ErrLog = StringConcatenate("Ask: ", MarketInfo(s_symbol, MODE_ASK), " Ticket: ", OrderTicket(), " StopMq4: ", OrderStopLoss());
                                Mq4Print(ErrLog);
                            }
                        }
                    }
                    break;
                }
            }
            return;
        }
        void OpenBuyFunc()
        {
            Mq4String ErrLog = "";
            Mq4String ErrAlert = "";
            Mq4String ErrDesc = "";
            Mq4Double ErrorCode = 0;
            Mq4Double buyOrderMod = false;
            Mq4Double buyTicket = 0;
            Mq4Double lbTake = 0;
            Mq4Double lbStop = 0;

            lbStop = 0;
            if (lStopLoss > 0)
                lbStop = NormalizeDouble(Ask - lStopLoss * Point * point, digit);
            lbTake = 0;
            if (lTakeProfit > 0)
                lbTake = NormalizeDouble(Ask + lTakeProfit * Point * point, digit);

            if (AccountFreeMargin() < (100 * Lots))
            {
                Mq4Print("We have no money. Free Margin = ", AccountFreeMargin());
                return;
            }







            ResetLastError();
            if (!EcnBroker)
                dummyResult = OrderSend(s_symbol, OP_BUY, LotsOptimizedFunc(), Ask, Slippage * Point * point, lbStop, lbTake, Name_Expert, MAGIC, 0,
                clOpenBuy);
            else
            {
                buyTicket = OrderSend(s_symbol, OP_BUY, LotsOptimizedFunc(), Ask, Slippage * Point * point, 0, 0, Name_Expert, MAGIC, 0,
                clOpenBuy);
                if (buyTicket >= 0)
                    buyOrderMod = OrderModify(buyTicket, OrderOpenPrice(), lbStop, lbTake, 0, CLR_NONE);

                if (buyOrderMod == false)
                {

                    ErrorCode = GetLastError();
                    ErrDesc = ErrorDescription(ErrorCode);

                    ErrAlert = StringConcatenate("Modify Buy Order - Error ", ErrorCode, ": ", ErrDesc);
                    if (ShowAlerts == true)
                        Alert(ErrAlert);

                    ErrLog = StringConcatenate("Ask: ", Ask, " Bid: ", Bid, " Ticket: ", buyTicket, " StopMq4: ", lbStop, " Profit: ", lbTake);
                    Mq4Print(ErrLog);
                }
            }

            return;
        }
        void OpenSellFunc()
        {
            Mq4String ErrLog = "";
            Mq4String ErrAlert = "";
            Mq4String ErrDesc = "";
            Mq4Double ErrorCode = 0;
            Mq4Double sellOrderMod = false;
            Mq4Double sellTicket = 0;
            Mq4Double lsTake = 0;
            Mq4Double lsStop = 0;
            lsStop = 0;
            if (sStopLoss > 0)
                lsStop = NormalizeDouble(Bid + sStopLoss * Point * point, digit);
            lsTake = 0;
            if (sTakeProfit > 0)
                lsTake = NormalizeDouble(Bid - sTakeProfit * Point * point, digit);

            if (AccountFreeMargin() < (100 * Lots))
            {
                Mq4Print("We have no money. Free Margin = ", AccountFreeMargin());
                return;
            }







            ResetLastError();
            if (!EcnBroker)
                dummyResult = OrderSend(s_symbol, OP_SELL, LotsOptimizedFunc(), Bid, Slippage * Point * point, lsStop, lsTake, Name_Expert, MAGIC, 0,
                clOpenSell);
            else
            {
                sellTicket = OrderSend(s_symbol, OP_SELL, LotsOptimizedFunc(), Bid, Slippage * Point * point, 0, 0, Name_Expert, MAGIC, 0,
                clOpenSell);
                if (sellTicket >= 0)
                    sellOrderMod = OrderModify(sellTicket, OrderOpenPrice(), lsStop, lsTake, 0, CLR_NONE);

                if (sellOrderMod == false)
                {
                    ErrorCode = GetLastError();
                    ErrDesc = ErrorDescription(ErrorCode);

                    ErrAlert = StringConcatenate("Modify Sell Order - Error ", ErrorCode, ": ", ErrDesc);
                    if (ShowAlerts == true)
                        Alert(ErrAlert);

                    ErrLog = StringConcatenate("Ask: ", Ask, " Bid: ", Bid, " Ticket: ", sellTicket, " StopMq4: ", lsStop, " Profit: ", lsTake);
                    Mq4Print(ErrLog);
                }
            }
            return;
        }
        void CheckForCloseFunc()
        {
            Mq4Double sellClose = false;
            Mq4String ErrLog = "";
            Mq4String ErrAlert = "";
            Mq4String ErrDesc = "";
            Mq4Double ErrorCode = 0;
            Mq4Double buyClose = false;
            Mq4Double i = 0;
            Mq4Double xSell1 = 0;
            Mq4Double xSell = 0;
            Mq4Double xBuy1 = 0;
            Mq4Double xBuy = 0;
            RefreshRates();
            xBuy = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", cl_ChannelPeriod, cl_Risk, 0, cl_entrybar);
            xBuy1 = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", cl_ChannelPeriod, cl_Risk, 0, cl_entrybar + 1);
            xSell = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", cl_ChannelPeriod, cl_Risk, 1, cl_entrybar);
            xSell1 = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", cl_ChannelPeriod, cl_Risk, 1, cl_entrybar + 1);







            for (i = 0; i < OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false)
                    break;
                if (OrderMagicNumber() != MAGIC)
                    continue;
                if (OrderSymbol() != s_symbol)
                    continue;







                if (OrderType() == OP_BUY)
                {
                    if (xBuy == EMPTY_VALUE && xBuy1 == EMPTY_VALUE && xSell != EMPTY_VALUE && xSell1 == EMPTY_VALUE && ((ItrendFilter && iTredn1 > iTredn3 && iTredn1 > iTredn2) || !ItrendFilter))
                    {
                        buyClose = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage * Point * point, clCloseBuy);
                        if (buyClose == false)
                        {
                            ErrorCode = GetLastError();
                            ErrDesc = ErrorDescription(ErrorCode);

                            ErrAlert = StringConcatenate("Close Buy Order - Error ", ErrorCode, ": ", ErrDesc);
                            if (ShowAlerts == true)
                                Alert(ErrAlert);

                            ErrLog = StringConcatenate("Bid: ", Bid, " Lots: ", OrderLots(), " Ticket: ", OrderTicket());
                            Mq4Print(ErrLog);
                        }
                    }
                    break;
                }







                if (OrderType() == OP_SELL)
                {
                    if (xBuy != EMPTY_VALUE && xBuy1 == EMPTY_VALUE && xSell == EMPTY_VALUE && xSell1 == EMPTY_VALUE && ((ItrendFilter && iTredn2 > iTredn3 && iTredn2 > iTredn1) || !ItrendFilter))
                    {
                        sellClose = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage * Point * point, clCloseSell);
                        if (sellClose == false)
                        {
                            ErrorCode = GetLastError();
                            ErrDesc = ErrorDescription(ErrorCode);

                            ErrAlert = StringConcatenate("Close Sell Order - Error ", ErrorCode, ": ", ErrDesc);
                            if (ShowAlerts == true)
                                Alert(ErrAlert);

                            ErrLog = StringConcatenate("Ask: ", Ask, " Lots: ", OrderLots(), " Ticket: ", OrderTicket());
                            Mq4Print(ErrLog);
                        }
                    }
                    break;
                }
            }
            return;
        }
        void CheckForClose2Func()
        {
            Mq4Double sellClose = false;
            Mq4String ErrLog = "";
            Mq4String ErrAlert = "";
            Mq4String ErrDesc = "";
            Mq4Double ErrorCode = 0;
            Mq4Double buyClose = false;
            Mq4Double i = 0;
            Mq4Double low = 0;
            Mq4Double high = 0;
            RefreshRates();
            high = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", cl2_ChannelPeriod, cl2_Risk, 0, cl2_entrybar);
            low = iCustom<PriceChannel_Stop_v1_Indicator>(NULL, 0, "PriceChannel_Stop_v1", cl2_ChannelPeriod, cl2_Risk, 1, cl2_entrybar);







            for (i = 0; i < OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false)
                    break;
                if (OrderMagicNumber() != MAGIC)
                    continue;
                if (OrderSymbol() != s_symbol)
                    continue;







                if (OrderType() == OP_BUY)
                {
                    if (Close[cl2_entrybar] == high)
                    {
                        buyClose = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage * Point * point, clCloseBuy);
                        if (buyClose == false)
                        {
                            ErrorCode = GetLastError();
                            ErrDesc = ErrorDescription(ErrorCode);

                            ErrAlert = StringConcatenate("Close Buy Order - Error ", ErrorCode, ": ", ErrDesc);
                            if (ShowAlerts == true)
                                Alert(ErrAlert);

                            ErrLog = StringConcatenate("Bid: ", Bid, " Lots: ", OrderLots(), " Ticket: ", OrderTicket());
                            Mq4Print(ErrLog);
                        }
                    }
                    break;
                }







                if (OrderType() == OP_SELL)
                {
                    if (Close[cl2_entrybar] == low)
                    {
                        sellClose = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage * Point * point, clCloseSell);
                        if (sellClose == false)
                        {
                            ErrorCode = GetLastError();
                            ErrDesc = ErrorDescription(ErrorCode);

                            ErrAlert = StringConcatenate("Close Sell Order - Error ", ErrorCode, ": ", ErrDesc);
                            if (ShowAlerts == true)
                                Alert(ErrAlert);

                            ErrLog = StringConcatenate("Ask: ", Ask, " Lots: ", OrderLots(), " Ticket: ", OrderTicket());
                            Mq4Print(ErrLog);
                        }
                    }
                    break;
                }
            }
            return;
        }
        Mq4Double LotsOptimizedFunc()
        {
            Mq4Double i = 0;
            Mq4Double losses = 0;
            Mq4Double orders = 0;
            Mq4Double lot = 0;
            Mq4Double contract = 0;
            Mq4Double lot_step = 0;
            Mq4Double lot_max = 0;
            Mq4Double lot_min = 0;
            lot_min = MarketInfo(s_symbol, MODE_MINLOT);
            lot_max = MarketInfo(s_symbol, MODE_MAXLOT);
            lot_step = MarketInfo(s_symbol, MODE_LOTSTEP);
            contract = MarketInfo(s_symbol, MODE_LOTSIZE);
            lot = Lots;
            orders = HistoryTotal();
            losses = 0;







            if (lot_min < 0.0 || lot_max <= 0.0 || lot_step <= 0.0)
            {
                Mq4Print("CalculateVolume: invalid MarketInfo() results [", lot_min, ",", lot_max, ",", lot_step, "]");
                return 0;
            }
            if (AccountLeverage() <= 0)
            {
                Mq4Print("CalculateVolume: invalid AccountLeverage() [", AccountLeverage(), "]");
                return 0;
            }







            if (MaximumRisk > 0)
            {
                lot = NormalizeDouble(AccountFreeMargin() * MaximumRisk * AccountLeverage() / contract, 2);
            }

            if (DecreaseFactor > 0)
            {
                for (i = orders - 1; i >= 0; i--)
                {
                    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == false)
                    {
                        Mq4Print("Error in_ history!");
                        break;
                    }
                    if (OrderSymbol() != s_symbol || OrderType() > OP_SELL)
                        continue;







                    if (OrderProfit() > 0)
                        break;
                    if (OrderProfit() < 0)
                        losses++;
                }
                if (losses > 1)
                    lot = NormalizeDouble(lot - lot * losses / DecreaseFactor, 2);
            }







            lot = NormalizeDouble(lot / lot_step, 0) * lot_step;
            if (lot < lot_min)
                lot = lot_min;
            if (lot > lot_max)
                lot = lot_max;

            return lot;
            return 0;
        }
        Mq4Double canOpenFunc(Mq4Double openWhat)
        {
            Mq4Double i = 0;
            if (!NoHedge)
                return true;







            for (i = 0; i < OrdersTotal(); i++)
            {
                if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false)
                    break;
                if (OrderSymbol() != s_symbol)
                    continue;
                if (!StrictNoHedge && OrderMagicNumber() != MAGIC)
                    continue;

                if (OrderType() == OP_BUY && openWhat == OP_SELL)
                    return false;
                if (OrderType() == OP_SELL && openWhat == OP_BUY)
                    return false;
            }
            return true;
            return true;
        }
        Mq4String normalizeTimeFunc(Mq4String time)
        {
            Mq4String answer = "";
            Mq4Double minute = 0;
            Mq4Double hour = 0;
            Mq4Double sepAt = 0;
            sepAt = StringFind(time, ":", 0);
            hour = StrToInteger(StringSubstr(time, 0, sepAt));
            minute = StrToInteger(StringSubstr(time, sepAt + 1, 0));







            hour = MathMax(MathMin(hour, 24), 0);
            minute = MathMax(MathMin(minute, 59), 0);
            answer = "";
            while (true)
            {
                if (hour == 0)
                {
                    answer = "00";
                    break;
                }
                if (hour < 10)
                {
                    answer = "0" + hour;
                    break;
                }
                answer = hour;
                break;
            }
            while (true)
            {
                if (minute == 0)
                {
                    answer = answer + ":00";
                    break;
                }
                if (minute < 10)
                {
                    answer = answer + ":0" + minute;
                    break;
                }
                answer = answer + ":" + minute;
                break;
            }
            return " " + answer;
            return Mq4String.Empty;
        }
        Mq4Double GetMagicFunc()
        {
            if (StringFind(s_symbol, "CADJPY") >= 0)
                return 1933921;
            if (StringFind(s_symbol, "CADCHF") >= 0)
                return 1933922;

            if (StringFind(s_symbol, "GOLD") >= 0)
                return 1933931;
            if (StringFind(s_symbol, "SILVER") >= 0)
                return 1933932;

            if (StringFind(s_symbol, "NZDJPY") >= 0)
                return 1933941;
            if (StringFind(s_symbol, "NZDUSD") >= 0)
                return 1933942;

            if (StringFind(s_symbol, "CHFJPY") >= 0)
                return 1933951;

            if (StringFind(s_symbol, "EURAUD") >= 0)
                return 1933961;
            if (StringFind(s_symbol, "EURCAD") >= 0)
                return 1933962;
            if (StringFind(s_symbol, "EURUSD") >= 0)
                return 1933963;
            if (StringFind(s_symbol, "EURGBP") >= 0)
                return 1933964;
            if (StringFind(s_symbol, "EURCHF") >= 0)
                return 1933965;
            if (StringFind(s_symbol, "EURNZD") >= 0)
                return 1933966;
            if (StringFind(s_symbol, "EURJPY") >= 0)
                return 1933967;

            if (StringFind(s_symbol, "GBPUSD") >= 0)
                return 1933971;
            if (StringFind(s_symbol, "GBPCHF") >= 0)
                return 1933972;
            if (StringFind(s_symbol, "GBPJPY") >= 0)
                return 1933973;

            if (StringFind(s_symbol, "USDCHF") >= 0)
                return 1933981;
            if (StringFind(s_symbol, "USDJPY") >= 0)
                return 1933982;
            if (StringFind(s_symbol, "USDCAD") >= 0)
                return 1933983;

            if (StringFind(s_symbol, "AUDUSD") >= 0)
                return 1933991;
            if (StringFind(s_symbol, "AUDNZD") >= 0)
                return 1933992;
            if (StringFind(s_symbol, "AUDCAD") >= 0)
                return 1933993;
            if (StringFind(s_symbol, "AUDCHF") >= 0)
                return 1933994;
            if (StringFind(s_symbol, "AUDJPY") >= 0)
                return 1933995;

            return ManualMagic;
            return 0;
        }

        [Parameter("Name_Expert", DefaultValue = "BrainWashing")]
        public string Name_Expert_parameter { get; set; }
        bool _Name_ExpertGot;
        Mq4String Name_Expert_backfield;
        Mq4String Name_Expert
        {
            get
            {
                if (!_Name_ExpertGot)
                    Name_Expert_backfield = Name_Expert_parameter;
                return Name_Expert_backfield;
            }
            set { Name_Expert_backfield = value; }
        }

        [Parameter("EcnBroker", DefaultValue = true)]
        public bool EcnBroker_parameter { get; set; }
        bool _EcnBrokerGot;
        Mq4Double EcnBroker_backfield;
        Mq4Double EcnBroker
        {
            get
            {
                if (!_EcnBrokerGot)
                    EcnBroker_backfield = EcnBroker_parameter;
                return EcnBroker_backfield;
            }
            set { EcnBroker_backfield = value; }
        }

        [Parameter("NoHedge", DefaultValue = true)]
        public bool NoHedge_parameter { get; set; }
        bool _NoHedgeGot;
        Mq4Double NoHedge_backfield;
        Mq4Double NoHedge
        {
            get
            {
                if (!_NoHedgeGot)
                    NoHedge_backfield = NoHedge_parameter;
                return NoHedge_backfield;
            }
            set { NoHedge_backfield = value; }
        }

        [Parameter("StrictNoHedge", DefaultValue = true)]
        public bool StrictNoHedge_parameter { get; set; }
        bool _StrictNoHedgeGot;
        Mq4Double StrictNoHedge_backfield;
        Mq4Double StrictNoHedge
        {
            get
            {
                if (!_StrictNoHedgeGot)
                    StrictNoHedge_backfield = StrictNoHedge_parameter;
                return StrictNoHedge_backfield;
            }
            set { StrictNoHedge_backfield = value; }
        }

        [Parameter("UseAutoMagic", DefaultValue = true)]
        public bool UseAutoMagic_parameter { get; set; }
        bool _UseAutoMagicGot;
        Mq4Double UseAutoMagic_backfield;
        Mq4Double UseAutoMagic
        {
            get
            {
                if (!_UseAutoMagicGot)
                    UseAutoMagic_backfield = UseAutoMagic_parameter;
                return UseAutoMagic_backfield;
            }
            set { UseAutoMagic_backfield = value; }
        }

        [Parameter("ManualMagic", DefaultValue = 17171717)]
        public int ManualMagic_parameter { get; set; }
        bool _ManualMagicGot;
        Mq4Double ManualMagic_backfield;
        Mq4Double ManualMagic
        {
            get
            {
                if (!_ManualMagicGot)
                    ManualMagic_backfield = ManualMagic_parameter;
                return ManualMagic_backfield;
            }
            set { ManualMagic_backfield = value; }
        }

        [Parameter("lStopLoss", DefaultValue = 100)]
        public double lStopLoss_parameter { get; set; }
        bool _lStopLossGot;
        Mq4Double lStopLoss_backfield;
        Mq4Double lStopLoss
        {
            get
            {
                if (!_lStopLossGot)
                    lStopLoss_backfield = lStopLoss_parameter;
                return lStopLoss_backfield;
            }
            set { lStopLoss_backfield = value; }
        }

        [Parameter("sStopLoss", DefaultValue = 100)]
        public double sStopLoss_parameter { get; set; }
        bool _sStopLossGot;
        Mq4Double sStopLoss_backfield;
        Mq4Double sStopLoss
        {
            get
            {
                if (!_sStopLossGot)
                    sStopLoss_backfield = sStopLoss_parameter;
                return sStopLoss_backfield;
            }
            set { sStopLoss_backfield = value; }
        }

        [Parameter("lTakeProfit", DefaultValue = 200)]
        public double lTakeProfit_parameter { get; set; }
        bool _lTakeProfitGot;
        Mq4Double lTakeProfit_backfield;
        Mq4Double lTakeProfit
        {
            get
            {
                if (!_lTakeProfitGot)
                    lTakeProfit_backfield = lTakeProfit_parameter;
                return lTakeProfit_backfield;
            }
            set { lTakeProfit_backfield = value; }
        }

        [Parameter("sTakeProfit", DefaultValue = 200)]
        public double sTakeProfit_parameter { get; set; }
        bool _sTakeProfitGot;
        Mq4Double sTakeProfit_backfield;
        Mq4Double sTakeProfit
        {
            get
            {
                if (!_sTakeProfitGot)
                    sTakeProfit_backfield = sTakeProfit_parameter;
                return sTakeProfit_backfield;
            }
            set { sTakeProfit_backfield = value; }
        }

        [Parameter("lTrailingStop", DefaultValue = 20)]
        public double lTrailingStop_parameter { get; set; }
        bool _lTrailingStopGot;
        Mq4Double lTrailingStop_backfield;
        Mq4Double lTrailingStop
        {
            get
            {
                if (!_lTrailingStopGot)
                    lTrailingStop_backfield = lTrailingStop_parameter;
                return lTrailingStop_backfield;
            }
            set { lTrailingStop_backfield = value; }
        }

        [Parameter("sTrailingStop", DefaultValue = 20)]
        public double sTrailingStop_parameter { get; set; }
        bool _sTrailingStopGot;
        Mq4Double sTrailingStop_backfield;
        Mq4Double sTrailingStop
        {
            get
            {
                if (!_sTrailingStopGot)
                    sTrailingStop_backfield = sTrailingStop_parameter;
                return sTrailingStop_backfield;
            }
            set { sTrailingStop_backfield = value; }
        }

        [Parameter("Slippage", DefaultValue = 4)]
        public int Slippage_parameter { get; set; }
        bool _SlippageGot;
        Mq4Double Slippage_backfield;
        Mq4Double Slippage
        {
            get
            {
                if (!_SlippageGot)
                    Slippage_backfield = Slippage_parameter;
                return Slippage_backfield;
            }
            set { Slippage_backfield = value; }
        }

        [Parameter("Lots", DefaultValue = 0.1)]
        public double Lots_parameter { get; set; }
        bool _LotsGot;
        Mq4Double Lots_backfield;
        Mq4Double Lots
        {
            get
            {
                if (!_LotsGot)
                    Lots_backfield = Lots_parameter;
                return Lots_backfield;
            }
            set { Lots_backfield = value; }
        }

        [Parameter("MaximumRisk", DefaultValue = 0)]
        public double MaximumRisk_parameter { get; set; }
        bool _MaximumRiskGot;
        Mq4Double MaximumRisk_backfield;
        Mq4Double MaximumRisk
        {
            get
            {
                if (!_MaximumRiskGot)
                    MaximumRisk_backfield = MaximumRisk_parameter;
                return MaximumRisk_backfield;
            }
            set { MaximumRisk_backfield = value; }
        }

        [Parameter("DecreaseFactor", DefaultValue = 3)]
        public double DecreaseFactor_parameter { get; set; }
        bool _DecreaseFactorGot;
        Mq4Double DecreaseFactor_backfield;
        Mq4Double DecreaseFactor
        {
            get
            {
                if (!_DecreaseFactorGot)
                    DecreaseFactor_backfield = DecreaseFactor_parameter;
                return DecreaseFactor_backfield;
            }
            set { DecreaseFactor_backfield = value; }
        }

        [Parameter("ah", DefaultValue = "Price Channel StopMq4 Trailing")]
        public string ah_parameter { get; set; }
        bool _ahGot;
        Mq4String ah_backfield;
        Mq4String ah
        {
            get
            {
                if (!_ahGot)
                    ah_backfield = ah_parameter;
                return ah_backfield;
            }
            set { ah_backfield = value; }
        }

        [Parameter("ah1", DefaultValue = "need lTrailing stop=0")]
        public string ah1_parameter { get; set; }
        bool _ah1Got;
        Mq4String ah1_backfield;
        Mq4String ah1
        {
            get
            {
                if (!_ah1Got)
                    ah1_backfield = ah1_parameter;
                return ah1_backfield;
            }
            set { ah1_backfield = value; }
        }

        [Parameter("ah2", DefaultValue = "and sTrailing stop=0")]
        public string ah2_parameter { get; set; }
        bool _ah2Got;
        Mq4String ah2_backfield;
        Mq4String ah2
        {
            get
            {
                if (!_ah2Got)
                    ah2_backfield = ah2_parameter;
                return ah2_backfield;
            }
            set { ah2_backfield = value; }
        }

        [Parameter("UsePCSTrail", DefaultValue = false)]
        public bool UsePCSTrail_parameter { get; set; }
        bool _UsePCSTrailGot;
        Mq4Double UsePCSTrail_backfield;
        Mq4Double UsePCSTrail
        {
            get
            {
                if (!_UsePCSTrailGot)
                    UsePCSTrail_backfield = UsePCSTrail_parameter;
                return UsePCSTrail_backfield;
            }
            set { UsePCSTrail_backfield = value; }
        }

        [Parameter("ts_ChannelPeriod", DefaultValue = 34)]
        public int ts_ChannelPeriod_parameter { get; set; }
        bool _ts_ChannelPeriodGot;
        Mq4Double ts_ChannelPeriod_backfield;
        Mq4Double ts_ChannelPeriod
        {
            get
            {
                if (!_ts_ChannelPeriodGot)
                    ts_ChannelPeriod_backfield = ts_ChannelPeriod_parameter;
                return ts_ChannelPeriod_backfield;
            }
            set { ts_ChannelPeriod_backfield = value; }
        }

        [Parameter("ts_Risk", DefaultValue = 0.3)]
        public double ts_Risk_parameter { get; set; }
        bool _ts_RiskGot;
        Mq4Double ts_Risk_backfield;
        Mq4Double ts_Risk
        {
            get
            {
                if (!_ts_RiskGot)
                    ts_Risk_backfield = ts_Risk_parameter;
                return ts_Risk_backfield;
            }
            set { ts_Risk_backfield = value; }
        }

        [Parameter("ts_entrybar", DefaultValue = 2)]
        public int ts_entrybar_parameter { get; set; }
        bool _ts_entrybarGot;
        Mq4Double ts_entrybar_backfield;
        Mq4Double ts_entrybar
        {
            get
            {
                if (!_ts_entrybarGot)
                    ts_entrybar_backfield = ts_entrybar_parameter;
                return ts_entrybar_backfield;
            }
            set { ts_entrybar_backfield = value; }
        }

        [Parameter("TrailStep", DefaultValue = 0)]
        public int TrailStep_parameter { get; set; }
        bool _TrailStepGot;
        Mq4Double TrailStep_backfield;
        Mq4Double TrailStep
        {
            get
            {
                if (!_TrailStepGot)
                    TrailStep_backfield = TrailStep_parameter;
                return TrailStep_backfield;
            }
            set { TrailStep_backfield = value; }
        }

        [Parameter("useCloseTradeRules", DefaultValue = false)]
        public bool useCloseTradeRules_parameter { get; set; }
        bool _useCloseTradeRulesGot;
        Mq4Double useCloseTradeRules_backfield;
        Mq4Double useCloseTradeRules
        {
            get
            {
                if (!_useCloseTradeRulesGot)
                    useCloseTradeRules_backfield = useCloseTradeRules_parameter;
                return useCloseTradeRules_backfield;
            }
            set { useCloseTradeRules_backfield = value; }
        }

        [Parameter("useCloseOnTrendChange", DefaultValue = false)]
        public bool useCloseOnTrendChange_parameter { get; set; }
        bool _useCloseOnTrendChangeGot;
        Mq4Double useCloseOnTrendChange_backfield;
        Mq4Double useCloseOnTrendChange
        {
            get
            {
                if (!_useCloseOnTrendChangeGot)
                    useCloseOnTrendChange_backfield = useCloseOnTrendChange_parameter;
                return useCloseOnTrendChange_backfield;
            }
            set { useCloseOnTrendChange_backfield = value; }
        }

        [Parameter("INDICATOR_ONE", DefaultValue = "PriceChannel_Stop_v1")]
        public string INDICATOR_ONE_parameter { get; set; }
        bool _INDICATOR_ONEGot;
        Mq4String INDICATOR_ONE_backfield;
        Mq4String INDICATOR_ONE
        {
            get
            {
                if (!_INDICATOR_ONEGot)
                    INDICATOR_ONE_backfield = INDICATOR_ONE_parameter;
                return INDICATOR_ONE_backfield;
            }
            set { INDICATOR_ONE_backfield = value; }
        }

        [Parameter("ChannelPeriod", DefaultValue = 9)]
        public int ChannelPeriod_parameter { get; set; }
        bool _ChannelPeriodGot;
        Mq4Double ChannelPeriod_backfield;
        Mq4Double ChannelPeriod
        {
            get
            {
                if (!_ChannelPeriodGot)
                    ChannelPeriod_backfield = ChannelPeriod_parameter;
                return ChannelPeriod_backfield;
            }
            set { ChannelPeriod_backfield = value; }
        }

        [Parameter("Risk", DefaultValue = 0.3)]
        public double Risk_parameter { get; set; }
        bool _RiskGot;
        Mq4Double Risk_backfield;
        Mq4Double Risk
        {
            get
            {
                if (!_RiskGot)
                    Risk_backfield = Risk_parameter;
                return Risk_backfield;
            }
            set { Risk_backfield = value; }
        }

        [Parameter("entrybar", DefaultValue = 1)]
        public int entrybar_parameter { get; set; }
        bool _entrybarGot;
        Mq4Double entrybar_backfield;
        Mq4Double entrybar
        {
            get
            {
                if (!_entrybarGot)
                    entrybar_backfield = entrybar_parameter;
                return entrybar_backfield;
            }
            set { entrybar_backfield = value; }
        }

        [Parameter("_INDICATOR_2", DefaultValue = "i_Trend")]
        public string _INDICATOR_2_parameter { get; set; }
        bool __INDICATOR_2Got;
        Mq4String _INDICATOR_2_backfield;
        Mq4String _INDICATOR_2
        {
            get
            {
                if (!__INDICATOR_2Got)
                    _INDICATOR_2_backfield = _INDICATOR_2_parameter;
                return _INDICATOR_2_backfield;
            }
            set { _INDICATOR_2_backfield = value; }
        }

        [Parameter("ItrendFilter", DefaultValue = true)]
        public bool ItrendFilter_parameter { get; set; }
        bool _ItrendFilterGot;
        Mq4Double ItrendFilter_backfield;
        Mq4Double ItrendFilter
        {
            get
            {
                if (!_ItrendFilterGot)
                    ItrendFilter_backfield = ItrendFilter_parameter;
                return ItrendFilter_backfield;
            }
            set { ItrendFilter_backfield = value; }
        }

        [Parameter("Price", DefaultValue = 0)]
        public int Price_parameter { get; set; }
        bool _PriceGot;
        Mq4Double Price_backfield;
        Mq4Double Price
        {
            get
            {
                if (!_PriceGot)
                    Price_backfield = Price_parameter;
                return Price_backfield;
            }
            set { Price_backfield = value; }
        }

        [Parameter("ItPeriod", DefaultValue = 13)]
        public double ItPeriod_parameter { get; set; }
        bool _ItPeriodGot;
        Mq4Double ItPeriod_backfield;
        Mq4Double ItPeriod
        {
            get
            {
                if (!_ItPeriodGot)
                    ItPeriod_backfield = ItPeriod_parameter;
                return ItPeriod_backfield;
            }
            set { ItPeriod_backfield = value; }
        }

        [Parameter("PowerPeriod", DefaultValue = 13)]
        public double PowerPeriod_parameter { get; set; }
        bool _PowerPeriodGot;
        Mq4Double PowerPeriod_backfield;
        Mq4Double PowerPeriod
        {
            get
            {
                if (!_PowerPeriodGot)
                    PowerPeriod_backfield = PowerPeriod_parameter;
                return PowerPeriod_backfield;
            }
            set { PowerPeriod_backfield = value; }
        }

        [Parameter("MaMethod", DefaultValue = MODE_LWMA)]
        public int MaMethod_parameter { get; set; }
        bool _MaMethodGot;
        Mq4Double MaMethod_backfield;
        Mq4Double MaMethod
        {
            get
            {
                if (!_MaMethodGot)
                    MaMethod_backfield = MaMethod_parameter;
                return MaMethod_backfield;
            }
            set { MaMethod_backfield = value; }
        }

        [Parameter("LevelBars", DefaultValue = 425)]
        public int LevelBars_parameter { get; set; }
        bool _LevelBarsGot;
        Mq4Double LevelBars_backfield;
        Mq4Double LevelBars
        {
            get
            {
                if (!_LevelBarsGot)
                    LevelBars_backfield = LevelBars_parameter;
                return LevelBars_backfield;
            }
            set { LevelBars_backfield = value; }
        }

        [Parameter("LevelFactor", DefaultValue = 0.2)]
        public double LevelFactor_parameter { get; set; }
        bool _LevelFactorGot;
        Mq4Double LevelFactor_backfield;
        Mq4Double LevelFactor
        {
            get
            {
                if (!_LevelFactorGot)
                    LevelFactor_backfield = LevelFactor_parameter;
                return LevelFactor_backfield;
            }
            set { LevelFactor_backfield = value; }
        }

        [Parameter("INDICATOR_CloseONE", DefaultValue = "PC_Stop_for trend change close")]
        public string INDICATOR_CloseONE_parameter { get; set; }
        bool _INDICATOR_CloseONEGot;
        Mq4String INDICATOR_CloseONE_backfield;
        Mq4String INDICATOR_CloseONE
        {
            get
            {
                if (!_INDICATOR_CloseONEGot)
                    INDICATOR_CloseONE_backfield = INDICATOR_CloseONE_parameter;
                return INDICATOR_CloseONE_backfield;
            }
            set { INDICATOR_CloseONE_backfield = value; }
        }

        [Parameter("cl_ChannelPeriod", DefaultValue = 9)]
        public int cl_ChannelPeriod_parameter { get; set; }
        bool _cl_ChannelPeriodGot;
        Mq4Double cl_ChannelPeriod_backfield;
        Mq4Double cl_ChannelPeriod
        {
            get
            {
                if (!_cl_ChannelPeriodGot)
                    cl_ChannelPeriod_backfield = cl_ChannelPeriod_parameter;
                return cl_ChannelPeriod_backfield;
            }
            set { cl_ChannelPeriod_backfield = value; }
        }

        [Parameter("cl_Risk", DefaultValue = 0.3)]
        public double cl_Risk_parameter { get; set; }
        bool _cl_RiskGot;
        Mq4Double cl_Risk_backfield;
        Mq4Double cl_Risk
        {
            get
            {
                if (!_cl_RiskGot)
                    cl_Risk_backfield = cl_Risk_parameter;
                return cl_Risk_backfield;
            }
            set { cl_Risk_backfield = value; }
        }

        [Parameter("cl_entrybar", DefaultValue = 1)]
        public int cl_entrybar_parameter { get; set; }
        bool _cl_entrybarGot;
        Mq4Double cl_entrybar_backfield;
        Mq4Double cl_entrybar
        {
            get
            {
                if (!_cl_entrybarGot)
                    cl_entrybar_backfield = cl_entrybar_parameter;
                return cl_entrybar_backfield;
            }
            set { cl_entrybar_backfield = value; }
        }

        [Parameter("closetradeRules", DefaultValue = "PC_Stop Sig._for close trade rules")]
        public string closetradeRules_parameter { get; set; }
        bool _closetradeRulesGot;
        Mq4String closetradeRules_backfield;
        Mq4String closetradeRules
        {
            get
            {
                if (!_closetradeRulesGot)
                    closetradeRules_backfield = closetradeRules_parameter;
                return closetradeRules_backfield;
            }
            set { closetradeRules_backfield = value; }
        }

        [Parameter("cl2_ChannelPeriod", DefaultValue = 14)]
        public int cl2_ChannelPeriod_parameter { get; set; }
        bool _cl2_ChannelPeriodGot;
        Mq4Double cl2_ChannelPeriod_backfield;
        Mq4Double cl2_ChannelPeriod
        {
            get
            {
                if (!_cl2_ChannelPeriodGot)
                    cl2_ChannelPeriod_backfield = cl2_ChannelPeriod_parameter;
                return cl2_ChannelPeriod_backfield;
            }
            set { cl2_ChannelPeriod_backfield = value; }
        }

        [Parameter("cl2_Risk", DefaultValue = 0.3)]
        public double cl2_Risk_parameter { get; set; }
        bool _cl2_RiskGot;
        Mq4Double cl2_Risk_backfield;
        Mq4Double cl2_Risk
        {
            get
            {
                if (!_cl2_RiskGot)
                    cl2_Risk_backfield = cl2_Risk_parameter;
                return cl2_Risk_backfield;
            }
            set { cl2_Risk_backfield = value; }
        }

        [Parameter("cl2_entrybar", DefaultValue = 1)]
        public int cl2_entrybar_parameter { get; set; }
        bool _cl2_entrybarGot;
        Mq4Double cl2_entrybar_backfield;
        Mq4Double cl2_entrybar
        {
            get
            {
                if (!_cl2_entrybarGot)
                    cl2_entrybar_backfield = cl2_entrybar_parameter;
                return cl2_entrybar_backfield;
            }
            set { cl2_entrybar_backfield = value; }
        }

        [Parameter("____TimeFilter", DefaultValue = "Time filter settings")]
        public string ____TimeFilter_parameter { get; set; }
        bool _____TimeFilterGot;
        Mq4String ____TimeFilter_backfield;
        Mq4String ____TimeFilter
        {
            get
            {
                if (!_____TimeFilterGot)
                    ____TimeFilter_backfield = ____TimeFilter_parameter;
                return ____TimeFilter_backfield;
            }
            set { ____TimeFilter_backfield = value; }
        }

        [Parameter("Trade_startFrom", DefaultValue = "00:00")]
        public string Trade_startFrom_parameter { get; set; }
        bool _Trade_startFromGot;
        Mq4String Trade_startFrom_backfield;
        Mq4String Trade_startFrom
        {
            get
            {
                if (!_Trade_startFromGot)
                    Trade_startFrom_backfield = Trade_startFrom_parameter;
                return Trade_startFrom_backfield;
            }
            set { Trade_startFrom_backfield = value; }
        }

        [Parameter("Trade_endAt", DefaultValue = "24:00")]
        public string Trade_endAt_parameter { get; set; }
        bool _Trade_endAtGot;
        Mq4String Trade_endAt_backfield;
        Mq4String Trade_endAt
        {
            get
            {
                if (!_Trade_endAtGot)
                    Trade_endAt_backfield = Trade_endAt_parameter;
                return Trade_endAt_backfield;
            }
            set { Trade_endAt_backfield = value; }
        }

        [Parameter("__fricl", DefaultValue = "Setting for friday positions close")]
        public string __fricl_parameter { get; set; }
        bool ___friclGot;
        Mq4String __fricl_backfield;
        Mq4String __fricl
        {
            get
            {
                if (!___friclGot)
                    __fricl_backfield = __fricl_parameter;
                return __fricl_backfield;
            }
            set { __fricl_backfield = value; }
        }

        [Parameter("CloseOnFriday", DefaultValue = false)]
        public bool CloseOnFriday_parameter { get; set; }
        bool _CloseOnFridayGot;
        Mq4Double CloseOnFriday_backfield;
        Mq4Double CloseOnFriday
        {
            get
            {
                if (!_CloseOnFridayGot)
                    CloseOnFriday_backfield = CloseOnFriday_parameter;
                return CloseOnFriday_backfield;
            }
            set { CloseOnFriday_backfield = value; }
        }

        [Parameter("FridayCloseHour", DefaultValue = 21)]
        public int FridayCloseHour_parameter { get; set; }
        bool _FridayCloseHourGot;
        Mq4Double FridayCloseHour_backfield;
        Mq4Double FridayCloseHour
        {
            get
            {
                if (!_FridayCloseHourGot)
                    FridayCloseHour_backfield = FridayCloseHour_parameter;
                return FridayCloseHour_backfield;
            }
            set { FridayCloseHour_backfield = value; }
        }

        [Parameter("FridayCloseMinute", DefaultValue = 59)]
        public int FridayCloseMinute_parameter { get; set; }
        bool _FridayCloseMinuteGot;
        Mq4Double FridayCloseMinute_backfield;
        Mq4Double FridayCloseMinute
        {
            get
            {
                if (!_FridayCloseMinuteGot)
                    FridayCloseMinute_backfield = FridayCloseMinute_parameter;
                return FridayCloseMinute_backfield;
            }
            set { FridayCloseMinute_backfield = value; }
        }

        [Parameter("ShowAlerts", DefaultValue = false)]
        public bool ShowAlerts_parameter { get; set; }
        bool _ShowAlertsGot;
        Mq4Double ShowAlerts_backfield;
        Mq4Double ShowAlerts
        {
            get
            {
                if (!_ShowAlertsGot)
                    ShowAlerts_backfield = ShowAlerts_parameter;
                return ShowAlerts_backfield;
            }
            set { ShowAlerts_backfield = value; }
        }

        [Parameter("clOpenBuy", DefaultValue = Blue)]
        public int clOpenBuy_parameter { get; set; }
        bool _clOpenBuyGot;
        Mq4Double clOpenBuy_backfield;
        Mq4Double clOpenBuy
        {
            get
            {
                if (!_clOpenBuyGot)
                    clOpenBuy_backfield = clOpenBuy_parameter;
                return clOpenBuy_backfield;
            }
            set { clOpenBuy_backfield = value; }
        }

        [Parameter("clCloseBuy", DefaultValue = Aqua)]
        public int clCloseBuy_parameter { get; set; }
        bool _clCloseBuyGot;
        Mq4Double clCloseBuy_backfield;
        Mq4Double clCloseBuy
        {
            get
            {
                if (!_clCloseBuyGot)
                    clCloseBuy_backfield = clCloseBuy_parameter;
                return clCloseBuy_backfield;
            }
            set { clCloseBuy_backfield = value; }
        }

        [Parameter("clOpenSell", DefaultValue = Red)]
        public int clOpenSell_parameter { get; set; }
        bool _clOpenSellGot;
        Mq4Double clOpenSell_backfield;
        Mq4Double clOpenSell
        {
            get
            {
                if (!_clOpenSellGot)
                    clOpenSell_backfield = clOpenSell_parameter;
                return clOpenSell_backfield;
            }
            set { clOpenSell_backfield = value; }
        }

        [Parameter("clCloseSell", DefaultValue = Violet)]
        public int clCloseSell_parameter { get; set; }
        bool _clCloseSellGot;
        Mq4Double clCloseSell_backfield;
        Mq4Double clCloseSell
        {
            get
            {
                if (!_clCloseSellGot)
                    clCloseSell_backfield = clCloseSell_parameter;
                return clCloseSell_backfield;
            }
            set { clCloseSell_backfield = value; }
        }





        Mq4Double dummyResult;
        Mq4Double iTredn3;
        Mq4Double iTredn2;
        Mq4Double iTredn1;
        Mq4Double point = 1;
        Mq4Double digit;
        Mq4Double MAGIC;
        Mq4String s_symbol;

        int indicator_buffers = 0;


        Mq4Double indicator_width1 = 1;
        Mq4Double indicator_width2 = 1;
        Mq4Double indicator_width3 = 1;
        Mq4Double indicator_width4 = 1;
        Mq4Double indicator_width5 = 1;
        Mq4Double indicator_width6 = 1;
        Mq4Double indicator_width7 = 1;
        Mq4Double indicator_width8 = 1;






        List<Mq4OutputDataSeries> AllBuffers = new List<Mq4OutputDataSeries>();
        public List<DataSeries> AllOutputDataSeries = new List<DataSeries>();

        protected override void OnStart()
        {


            CommonInitialize();


            try
            {
                Mq4Init();
            } catch (Exception e)
            {

            }
        }

        protected override void OnTick()
        {
            var index = MarketSeries.Close.Count - 1;


            try
            {
                Mq4Start();
            } catch (Exception e)
            {

            }
        }

        private bool IsLastBar
        {
            get { return true; }
        }

        int _currentIndex;
        CachedStandardIndicators _cachedStandardIndicators;
        Mq4ChartObjects _mq4ChartObjects;
        Mq4ArrayToDataSeriesConverterFactory _mq4ArrayToDataSeriesConverterFactory;
        Mq4MarketDataSeries Open;
        Mq4MarketDataSeries High;
        Mq4MarketDataSeries Low;
        Mq4MarketDataSeries Close;
        Mq4MarketDataSeries Median;
        Mq4MarketDataSeries Volume;
        Mq4TimeSeries Time;

        private void CommonInitialize()
        {
            Open = new Mq4MarketDataSeries(MarketSeries.Open);
            High = new Mq4MarketDataSeries(MarketSeries.High);
            Low = new Mq4MarketDataSeries(MarketSeries.Low);
            Close = new Mq4MarketDataSeries(MarketSeries.Close);
            Volume = new Mq4MarketDataSeries(MarketSeries.TickVolume);
            Median = new Mq4MarketDataSeries(MarketSeries.Median);
            Time = new Mq4TimeSeries(MarketSeries.OpenTime);

            _cachedStandardIndicators = new CachedStandardIndicators(Indicators);
            _mq4ChartObjects = new Mq4ChartObjects(ChartObjects, MarketSeries.OpenTime);
            _mq4ArrayToDataSeriesConverterFactory = new Mq4ArrayToDataSeriesConverterFactory(() => CreateDataSeries());
        }
        private int Bars
        {
            get { return MarketSeries.Close.Count; }
        }
        private int Digits
        {
            get
            {
                if (Symbol == null)
                    return 0;
                return Symbol.Digits;
            }
        }

        Mq4Double Point
        {
            get
            {
                if (Symbol == null)
                    return 1E-05;

                return Symbol.TickSize;
            }
        }
        private int Period()
        {
            if (TimeFrame == TimeFrame.Minute)
                return 1;
            if (TimeFrame == TimeFrame.Minute2)
                return 2;
            if (TimeFrame == TimeFrame.Minute3)
                return 3;
            if (TimeFrame == TimeFrame.Minute4)
                return 4;
            if (TimeFrame == TimeFrame.Minute5)
                return 5;
            if (TimeFrame == TimeFrame.Minute10)
                return 10;
            if (TimeFrame == TimeFrame.Minute15)
                return 15;
            if (TimeFrame == TimeFrame.Minute30)
                return 30;
            if (TimeFrame == TimeFrame.Hour)
                return 60;
            if (TimeFrame == TimeFrame.Hour4)
                return 240;
            if (TimeFrame == TimeFrame.Hour12)
                return 720;
            if (TimeFrame == TimeFrame.Daily)
                return 1440;
            if (TimeFrame == TimeFrame.Weekly)
                return 10080;

            return 43200;
        }

        public TimeFrame PeriodToTimeFrame(int period)
        {
            switch (period)
            {
                case 0:
                    return TimeFrame;
                case 1:
                    return TimeFrame.Minute;
                case 2:
                    return TimeFrame.Minute2;
                case 3:
                    return TimeFrame.Minute3;
                case 4:
                    return TimeFrame.Minute4;
                case 5:
                    return TimeFrame.Minute5;
                case 10:
                    return TimeFrame.Minute10;
                case 15:
                    return TimeFrame.Minute15;
                case 30:
                    return TimeFrame.Minute30;
                case 60:
                    return TimeFrame.Hour;
                case 240:
                    return TimeFrame.Hour4;
                case 720:
                    return TimeFrame.Hour12;
                case 1440:
                    return TimeFrame.Daily;
                case 10080:
                    return TimeFrame.Weekly;
                case 43200:
                    return TimeFrame.Monthly;
                default:
                    throw new NotSupportedException(string.Format("TimeFrame {0} minutes isn't supported by cAlgo", period));
            }
        }


        Mq4Double MathMax(double value1, double value2)
        {
            return Math.Max(value1, value2);
        }

        Mq4Double MathMin(double value1, double value2)
        {
            return Math.Min(value1, value2);
        }

















        Mq4Double NormalizeDouble(double value, int digits)
        {
            return Math.Round(value, digits);
        }


        Mq4Double StrToInteger(Mq4String value)
        {
            return int.Parse(value);
        }

        Mq4String TimeToStr(int value, int mode = TIME_DATE | TIME_MINUTES)
        {
            var formatString = "";
            if ((mode & TIME_DATE) != 0)
                formatString += "yyyy.MM.dd ";
            if ((mode & TIME_SECONDS) != 0)
                formatString += "HH:mm:ss";
            else if ((mode & TIME_MINUTES) != 0)
                formatString += "HH:mm";
            formatString = formatString.Trim();

            return Mq4TimeSeries.ToDateTime(value).ToString(formatString);
        }

        int StrToTime(Mq4String value)
        {
            var dateTime = StrToDateTime(value);
            return Mq4TimeSeries.ToInteger(dateTime);
        }

//{
        private static readonly Regex TimeRegex = new Regex("((?<year>\\d+)\\.(?<month>\\d+)\\.(?<day>\\d+)){0,1}\\s*((?<hour>\\d+)\\:(?<minute>\\d+)){0,1}", RegexOptions.Compiled);
        DateTime StrToDateTime(Mq4String value)
        {
            var dateTime = Server.Time.Date;

            var match = TimeRegex.Match(value);
            if (!match.Success)
                return dateTime;

            if (match.Groups["year"].Value != string.Empty)
            {
                dateTime = new DateTime(int.Parse(match.Groups["year"].Value), int.Parse(match.Groups["month"].Value), int.Parse(match.Groups["day"].Value));
            }
            if (match.Groups["hour"].Value != string.Empty)
                dateTime = dateTime.AddHours(int.Parse(match.Groups["hour"].Value));
            if (match.Groups["minute"].Value != string.Empty)
                dateTime = dateTime.AddMinutes(int.Parse(match.Groups["minute"].Value));

            return dateTime;
        }
        //}
        int ToMq4ErrorCode(ErrorCode errorCode)
        {
            switch (errorCode)
            {
                case ErrorCode.BadVolume:
                    return ERR_INVALID_TRADE_VOLUME;
                case ErrorCode.NoMoney:
                    return ERR_NOT_ENOUGH_MONEY;
                case ErrorCode.MarketClosed:
                    return ERR_MARKET_CLOSED;
                case ErrorCode.Disconnected:
                    return ERR_NO_CONNECTION;
                case ErrorCode.Timeout:
                    return ERR_TRADE_TIMEOUT;
                default:
                    return ERR_COMMON_ERROR;
            }
        }



        Mq4Double RefreshRates()
        {
            RefreshData();
            return true;
        }



        Mq4String StringConcatenate(params object[] parameters)
        {
            var stringBuilder = new StringBuilder();
            foreach (var parameter in parameters)
                stringBuilder.Append(parameter.ToString());
            return stringBuilder.ToString();
        }

        int StringFind(Mq4String text, string matched_text, int start = 0)
        {
            return ((string)text).IndexOf(matched_text, start);
        }


        Mq4String StringSubstr(Mq4String text, int start, int length = 0)
        {
            if (length == 0 || length > ((string)text).Length - start)
                return ((string)text).Substring(start, ((string)text).Length - start);

            return ((string)text).Substring(start, length);
        }











        int TimeCurrent()
        {
            return Mq4TimeSeries.ToInteger(Server.Time);
        }



        int TimeDayOfWeek(int time)
        {
            return (int)Mq4TimeSeries.ToDateTime(time).DayOfWeek;
        }


        int TimeHour(int time)
        {
            return Mq4TimeSeries.ToDateTime(time).Hour;
        }



        int TimeMinute(int time)
        {
            return Mq4TimeSeries.ToDateTime(time).Minute;
        }





        const string NotSupportedMaShift = "Converter supports only ma_shift = 0";













        Mq4Double MarketInfo(Mq4String symbol, int type)
        {
            var symbolObject = GetSymbol(symbol);
            switch (type)
            {
                case MODE_LOW:
                    return GetSeries(symbol, PERIOD_D1).Low.LastValue;
                case MODE_HIGH:
                    return GetSeries(symbol, PERIOD_D1).High.LastValue;
                case MODE_DIGITS:
                    return symbolObject.Digits;
                case MODE_TIME:
                    return TimeCurrent();
                case MODE_ASK:
                    return symbolObject.Ask;
                case MODE_BID:
                    return symbolObject.Bid;
                case MODE_SPREAD:
                    return symbolObject.Spread / symbolObject.TickSize;
                case MODE_PROFITCALCMODE:
                    return 0;
                case MODE_FREEZELEVEL:
                    return 0;
                case MODE_TRADEALLOWED:
                    return 1;
                case MODE_POINT:
                    return symbolObject.TickSize;
                case MODE_TICKSIZE:
                    return symbolObject.TickSize;
                case MODE_SWAPTYPE:
                    return 0;
                case MODE_MARGINCALCMODE:
                    return 0;
                case MODE_STOPLEVEL:
                    return symbolObject.TickSize;
                case MODE_MINLOT:
                    return symbolObject.ToLotsVolume(symbolObject.VolumeMin);
                case MODE_MAXLOT:
                    return symbolObject.ToLotsVolume(symbolObject.VolumeMax);
                case MODE_LOTSTEP:
                    return symbolObject.ToLotsVolume(symbolObject.VolumeStep);
                case MODE_TICKVALUE:
                    return symbolObject.TickValue;
                case MODE_LOTSIZE:
                    return symbolObject.ToNotNormalizedUnitsVolume(1);
                case MODE_MARGINREQUIRED:
                    return symbolObject.ToNotNormalizedUnitsVolume(1) / Account.Leverage * symbolObject.Ask * symbolObject.TickValue / symbolObject.TickSize;
            }
            return 0;
        }

        Mq4Double Bid
        {
            get
            {
                if (Symbol == null || double.IsNaN(Symbol.Bid))
                    return 0;
                return Symbol.Bid;
            }
        }

        Mq4Double Ask
        {
            get
            {
                if (Symbol == null || double.IsNaN(Symbol.Ask))
                    return 0;
                return Symbol.Ask;
            }
        }

        void Comment(params object[] objects)
        {
            var text = string.Join("", objects.Select(o => o.ToString()));
            ChartObjects.DrawText("top left comment", text, StaticPosition.TopLeft);
        }



        void Mq4Print(params object[] parameters)
        {
            Print(string.Join(string.Empty, parameters));
        }



        void ResetLastError()
        {
            _lastError = ERR_NO_ERROR;
        }
















//{
        //AccessRights = AccessRights.FullAccess

        void Alert(params object[] objects)
        {
            if (IsBacktesting)
                return;

            var text = string.Join("", objects.Select(o => o.ToString()));
            _alertWindowWrapper.Value.ShowAlert(text);
            PlayAlertSoundIfNeeded();
        }

        Lazy<AlertWindowWrapper> _alertWindowWrapper = new Lazy<AlertWindowWrapper>(() => { return new AlertWindowWrapper(); });

        private const string _alertSound = "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";
        void PlayAlertSoundIfNeeded()
        {
            if (!IsLastBar || IsTesting() || (DateTime.Now - _lastPlayedTime) < TimeSpan.FromSeconds(1))
                return;

            _lastPlayedTime = DateTime.Now;
            _mediaPlayer = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.Media.MediaPlayer");

            var soundFilePath = Path.Combine(FolderPaths._2calgoAppDataFolder, "alert_sound.mp3");
            if (!File.Exists(soundFilePath))
            {
                var binaryData = Convert.FromBase64String(_alertSound);
                File.WriteAllBytes(soundFilePath, binaryData);
            }
            var uri = new Uri(soundFilePath);

            ReflectionHelper.InvokeMethod(_mediaPlayer, "Open", uri);
            ReflectionHelper.InvokeMethod(_mediaPlayer, "Play");
        }

        private DateTime _lastPlayedTime;
        private object _mediaPlayer;

        public class AlertWindowWrapper : MarshalByRefObject
        {
            private static Thread _windowThread;
            private static readonly AutoResetEvent LoadedEvent = new AutoResetEvent(false);
            private static readonly object SyncObject = new object();

            private static object _window;
            private static AlertWindowModel _alertWindowModel;

            public void ShowAlert(string message)
            {
                lock (SyncObject)
                {
                    if (_window == null)
                        CreateWindow();

                    _alertWindowModel.Message = message;
                    var items = new List<AlertItem>(_alertWindowModel.Items);
                    items.Insert(0, new AlertItem(DateTime.Now, message));
                    _alertWindowModel.Items = items;
                }
            }

            private void CreateWindow()
            {
                _windowThread = new Thread(() =>
                {
                    try
                    {
                        _window = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Window");
                        SubscribeToEvent(_window, "Loaded", "Window_Loaded");
                        SubscribeToEvent(_window, "Closing", "Window_Closing");
                        ReflectionHelper.SetProperty(_window, "ShowInTaskbar", true);
                        ReflectionHelper.SetProperty(_window, "ShowActivated", true);
                        ReflectionHelper.SetProperty(_window, "Width", 525);
                        ReflectionHelper.SetProperty(_window, "Height", 400);
                        ReflectionHelper.SetProperty(_window, "WindowStartupLocation", ReflectionHelper.GetStaticValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.WindowStartupLocation", "CenterScreen"));
                        ReflectionHelper.SetProperty(_window, "WindowStyle", ReflectionHelper.GetStaticValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.WindowStyle", "ToolWindow"));
                        ReflectionHelper.SetProperty(_window, "Title", "Alert");
                        var rootGrid = WpfReflectionHelper.CreateGrid();
                        WpfReflectionHelper.SetMargin(rootGrid, 5);
                        WpfReflectionHelper.AddAutoRowDefinition(rootGrid);
                        WpfReflectionHelper.AddStarRowDefinition(rootGrid);

                        var messageGrid = WpfReflectionHelper.CreateGrid();
                        WpfReflectionHelper.AddAutoColumnDefinition(messageGrid);
                        WpfReflectionHelper.AddStarColumnDefinition(messageGrid);

                        var image = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.Image");
                        WpfReflectionHelper.SetMargin(image, 20);
                        var bitmapImage = Base64ToImage("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");
                        ReflectionHelper.SetProperty(image, "Source", bitmapImage);
                        WpfReflectionHelper.AddChild(messageGrid, image);

                        var messageTextBlock = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.TextBlock");

                        WpfReflectionHelper.SetGridColumn(messageTextBlock, 1);
                        ReflectionHelper.SetProperty(messageTextBlock, "HorizontalAlignment", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.HorizontalAlignment", "Left"));
                        ReflectionHelper.SetProperty(messageTextBlock, "TextWrapping", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.TextWrapping", "Wrap"));
                        ReflectionHelper.SetProperty(messageTextBlock, "VerticalAlignment", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.VerticalAlignment", "Center"));
                        ReflectionHelper.SetProperty(messageTextBlock, "FontSize", 18);
                        WpfReflectionHelper.SetBinding(messageTextBlock, "Message", "System.Windows.Controls.TextBlock", "TextProperty");
                        WpfReflectionHelper.AddChild(messageGrid, messageTextBlock);

                        var allAlertsGrid = WpfReflectionHelper.CreateGrid();
                        WpfReflectionHelper.SetGridRow(allAlertsGrid, 1);
                        WpfReflectionHelper.AddStarRowDefinition(allAlertsGrid);
                        WpfReflectionHelper.AddAutoRowDefinition(allAlertsGrid);
                        var dataGrid = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.DataGrid");
                        WpfReflectionHelper.SetBinding(dataGrid, "Items", "System.Windows.Controls.ItemsControl", "ItemsSourceProperty");
                        WpfReflectionHelper.AddChild(allAlertsGrid, dataGrid);
                        var closeButton = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.Button");
                        SubscribeToEvent(closeButton, "Click", "ButtonOnClick");
                        WpfReflectionHelper.SetGridRow(closeButton, 1);
                        ReflectionHelper.SetProperty(closeButton, "Width", 100);
                        WpfReflectionHelper.SetMargin(closeButton, 0, 5, 0, 0);
                        ReflectionHelper.SetProperty(closeButton, "Content", "Close");
                        WpfReflectionHelper.AddChild(allAlertsGrid, closeButton);

                        WpfReflectionHelper.AddChild(rootGrid, messageGrid);
                        WpfReflectionHelper.AddChild(rootGrid, allAlertsGrid);

                        ReflectionHelper.SetProperty(_window, "Content", rootGrid);
                        _alertWindowModel = new AlertWindowModel();
                        ReflectionHelper.SetProperty(_window, "DataContext", _alertWindowModel);

                        ReflectionHelper.InvokeMethod(_window, "ShowDialog");
                    } catch (Exception exception)
                    {
                    }
                }) 
                {
                    IsBackground = false,
                    Name = "Alert Window thread"
                };

                _windowThread.TrySetApartmentState(ApartmentState.STA);
                _windowThread.Start();
                LoadedEvent.WaitOne();
            }

            private static object Base64ToImage(string stringValue)
            {

                var binaryData = Convert.FromBase64String(stringValue);

                var bitmapImage = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.Media.Imaging.BitmapImage");

                ReflectionHelper.InvokeMethod(bitmapImage, "BeginInit");
                ReflectionHelper.SetProperty(bitmapImage, "StreamSource", new MemoryStream(binaryData));
                ReflectionHelper.InvokeMethod(bitmapImage, "EndInit");

                return bitmapImage;
            }

            public void ButtonOnClick(object sender, object routedEventArgs)
            {
                ReflectionHelper.InvokeMethod(_window, "Close");
            }

            public void Window_Loaded(object s, object e)
            {
                LoadedEvent.Set();
            }

            public void Window_Closing(object sender, CancelEventArgs e)
            {
                _window = null;
                _alertWindowModel = null;
            }

            private void SubscribeToEvent(object @object, string eventName, string handlerName)
            {
                var eventInfo = @object.GetType().GetEvent(eventName);
                var methodInfo = GetType().GetMethod(handlerName);
                var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
                eventInfo.AddEventHandler(@object, handler);
            }
        }

        public class AlertWindowModel : INotifyPropertyChanged
        {
            private string _message;
            private IEnumerable<AlertItem> _items = new List<AlertItem>();

            public string Message
            {
                get { return _message; }
                set
                {
                    if (_message == value)
                        return;

                    _message = value;
                    OnPropertyChanged("Message");
                }
            }

            public IEnumerable<AlertItem> Items
            {
                get { return _items; }
                set
                {
                    if (_items == value)
                        return;

                    _items = value;
                    OnPropertyChanged("Items");
                }
            }


            public event PropertyChangedEventHandler PropertyChanged;

            protected virtual void OnPropertyChanged(string propertyName)
            {
                var handler = PropertyChanged;
                if (handler != null)
                    handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public class AlertItem
        {
            public DateTime Time { get; private set; }
            public string Message { get; private set; }

            public AlertItem(DateTime time, string message)
            {
                Time = time;
                Message = message;
            }
        }

        public static class WpfReflectionHelper
        {
            public static Assembly PresentationFrameworkAssembly = Assembly.Load("PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            public static Assembly PresentationCoreAssembly = Assembly.Load("PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

            public static void SetMargin(object rootGrid, params object[] parameters)
            {
                var thickness = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Thickness", parameters);
                ReflectionHelper.SetProperty(rootGrid, "Margin", thickness);
            }

            public static object CreateGrid()
            {
                return ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.Grid");
            }

            public static void AddChild(object grid, object child)
            {
                var rootGridChildren = ReflectionHelper.GetPropertyValue(grid, "Children");
                ReflectionHelper.InvokeMethod(rootGridChildren, "Add", child);
            }

            private static readonly object AutoGridLegth = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.GridLength", "Auto");

            public static void AddAutoRowDefinition(object grid)
            {
                var rowDefinition = CreateRowDefinition();
                ReflectionHelper.SetProperty(rowDefinition, "Height", AutoGridLegth);
                AddRowDefinition(grid, rowDefinition);
            }

            public static void AddStarRowDefinition(object grid)
            {
                var rowDefinition = CreateRowDefinition();
                var starUnitType = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.GridUnitType", "Star");
                var gridLength = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.GridLength", new[] 
                {
                    1,
                    starUnitType
                });
                ReflectionHelper.SetProperty(rowDefinition, "Height", gridLength);
                AddRowDefinition(grid, rowDefinition);
            }

            private static object CreateRowDefinition()
            {
                var rowDefinition = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.RowDefinition");
                return rowDefinition;
            }

            public static void AddRowDefinition(object grid, object rowDefinition)
            {
                var rowDefinitions = ReflectionHelper.GetPropertyValue(grid, "RowDefinitions");
                ReflectionHelper.InvokeMethod(rowDefinitions, "Add", rowDefinition);
            }

            public static void AddAutoColumnDefinition(object grid)
            {
                var ColumnDefinition = CreateColumnDefinition();
                ReflectionHelper.SetProperty(ColumnDefinition, "Width", AutoGridLegth);
                AddColumnDefinition(grid, ColumnDefinition);
            }

            public static void AddStarColumnDefinition(object grid)
            {
                var ColumnDefinition = CreateColumnDefinition();
                var starUnitType = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.GridUnitType", "Star");
                var gridLength = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.GridLength", new[] 
                {
                    1,
                    starUnitType
                });
                ReflectionHelper.SetProperty(ColumnDefinition, "Width", gridLength);
                AddColumnDefinition(grid, ColumnDefinition);
            }

            private static object CreateColumnDefinition()
            {
                var ColumnDefinition = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.ColumnDefinition");
                return ColumnDefinition;
            }

            public static void AddColumnDefinition(object grid, object ColumnDefinition)
            {
                var ColumnDefinitions = ReflectionHelper.GetPropertyValue(grid, "ColumnDefinitions");
                ReflectionHelper.InvokeMethod(ColumnDefinitions, "Add", ColumnDefinition);
            }

            public static void SetGridColumn(object element, int column)
            {
                var columnProperty = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.Controls.Grid", "ColumnProperty");
                ReflectionHelper.InvokeMethod(element, "SetValue", columnProperty, column);
            }

            public static void SetGridRow(object element, int row)
            {
                var columnProperty = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.Controls.Grid", "RowProperty");
                ReflectionHelper.InvokeMethod(element, "SetValue", columnProperty, row);
            }

            public static void SetBinding(object element, string path, string propertyTypeName, string propertyName)
            {
                var property = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, propertyTypeName, propertyName);
                ReflectionHelper.InvokeMethod(element, "SetBinding", property, path);
            }
        }

        public static class ReflectionHelper
        {
            public static object GetEnumValue(Assembly assembly, string typeName, string value)
            {
                var type = assembly.GetType(typeName);
                return Enum.Parse(type, value);
            }

            public static void InvokeMethod(object instance, string methodName, params object[] parameters)
            {
                instance.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod, null, instance, parameters);
            }

            public static object InvokeStaticMethod(Assembly assembly, string typeName, string methodName, params object[] parameters)
            {
                return assembly.GetType(typeName).InvokeMember(methodName, BindingFlags.InvokeMethod, null, null, parameters);
            }

            public static object GetStaticValue(Assembly assembly, string typeName, string propertyName)
            {
                var type = assembly.GetType(typeName);
                var propertyInfo = type.GetProperty(propertyName);
                if (propertyInfo != null)
                    return propertyInfo.GetValue(null, null);

                var fieldInfo = type.GetField(propertyName);
                return fieldInfo.GetValue(null);
            }

            public static void SetProperty(object instance, string propertyName, Assembly assembly, string typeName, params object[] parameters)
            {
                var propertyInfo = instance.GetType().GetProperty(propertyName);
                var propertyValue = CreateInstance(assembly, typeName, parameters);
                propertyInfo.SetValue(instance, propertyValue, null);
            }

            public static void SetProperty(object instance, string propertyName, object value)
            {
                var propertyInfo = instance.GetType().GetProperty(propertyName);
                propertyInfo.SetValue(instance, value, null);
            }

            public static object GetPropertyValue(object instance, string propertyName)
            {
                var propertyInfo = instance.GetType().GetProperty(propertyName);
                return propertyInfo.GetValue(instance, null);
            }

            public static object CreateInstance(Assembly assembly, string typeName)
            {
                return CreateInstance(assembly, typeName, new object[0]);
            }

            public static object CreateInstance(Assembly assembly, string typeName, object[] parameters)
            {
                var pointType = assembly.GetType(typeName);
                var propertyValue = Activator.CreateInstance(pointType, parameters);
                return propertyValue;
            }
        }
        //}

        private int _lastError;
        Mq4Double GetLastError()
        {
            return _lastError;
        }

        Mq4Double IsTesting()
        {
            return IsBacktesting;
        }











        Mq4String ErrorDescription(int code)
        {
            string error_string;
            switch (code)
            {
                case 0:
                case 1:
                    return "no error";
                case 2:
                    return "common error";
                case 4203:
                    return "unknown object type";
                case 4204:
                    return "no object name";
                case 4205:
                    return "object coordinates error";
                default:
                    return "unknown error";
            }
            return error_string;
        }

        const string GlobalVariablesPath = "Software\\2calgo\\Global Variables\\";






        Symbol GetSymbol(string symbolCode)
        {
            if (symbolCode == "0" || string.IsNullOrEmpty(symbolCode))
            {
                return Symbol;
            }
            return MarketData.GetSymbol(symbolCode);
        }

        MarketSeries GetSeries(string symbol, int period)
        {
            var timeFrame = PeriodToTimeFrame(period);
            var symbolObject = GetSymbol(symbol);

            if (symbolObject == Symbol && timeFrame == TimeFrame)
                return MarketSeries;

            return MarketData.GetSeries(symbolObject.Code, timeFrame);
        }

        private DataSeries ToAppliedPrice(string symbol, int timeframe, int constant)
        {
            var series = GetSeries(symbol, timeframe);
            switch (constant)
            {
                case PRICE_OPEN:
                    return series.Open;
                case PRICE_HIGH:
                    return series.High;
                case PRICE_LOW:
                    return series.Low;
                case PRICE_CLOSE:
                    return series.Close;
                case PRICE_MEDIAN:
                    return series.Median;
                case PRICE_TYPICAL:
                    return series.Typical;
                case PRICE_WEIGHTED:
                    return series.WeightedClose;
            }
            throw new NotImplementedException("Converter doesn't support working with this type of AppliedPrice");
        }
        const string xArrow = "✖";

        public static string GetArrowByCode(int code)
        {
            switch (code)
            {
                case 0:
                    return string.Empty;
                case 32:
                    return " ";
                case 33:
                    return "✏";
                case 34:
                    return "✂";
                case 35:
                    return "✁";
                case 40:
                    return "☎";
                case 41:
                    return "✆";
                case 42:
                    return "✉";
                case 54:
                    return "⌛";
                case 55:
                    return "⌨";
                case 62:
                    return "✇";
                case 63:
                    return "✍";
                case 65:
                    return "✌";
                case 69:
                    return "☜";
                case 70:
                    return "☞";
                case 71:
                    return "☝";
                case 72:
                    return "☟";
                case 74:
                    return "☺";
                case 76:
                    return "☹";
                case 78:
                    return "☠";
                case 79:
                    return "⚐";
                case 81:
                    return "✈";
                case 82:
                    return "☼";
                case 84:
                    return "❄";
                case 86:
                    return "✞";
                case 88:
                    return "✠";
                case 89:
                    return "✡";
                case 90:
                    return "☪";
                case 91:
                    return "☯";
                case 92:
                    return "ॐ";
                case 93:
                    return "☸";
                case 94:
                    return "♈";
                case 95:
                    return "♉";
                case 96:
                    return "♊";
                case 97:
                    return "♋";
                case 98:
                    return "♌";
                case 99:
                    return "♍";
                case 100:
                    return "♎";
                case 101:
                    return "♏";
                case 102:
                    return "♐";
                case 103:
                    return "♑";
                case 104:
                    return "♒";
                case 105:
                    return "♓";
                case 106:
                    return "&";
                case 107:
                    return "&";
                case 108:
                    return "●";
                case 109:
                    return "❍";
                case 110:
                    return "■";
                case 111:
                case 112:
                    return "□";
                case 113:
                    return "❑";
                case 114:
                    return "❒";
                case 115:
                case 116:
                    return "⧫";
                case 117:
                case 119:
                    return "◆";
                case 118:
                    return "❖";
                case 120:
                    return "⌧";
                case 121:
                    return "⍓";
                case 122:
                    return "⌘";
                case 123:
                    return "❀";
                case 124:
                    return "✿";
                case 125:
                    return "❝";
                case 126:
                    return "❞";
                case 127:
                    return "▯";
                case 128:
                    return "⓪";
                case 129:
                    return "①";
                case 130:
                    return "②";
                case 131:
                    return "③";
                case 132:
                    return "④";
                case 133:
                    return "⑤";
                case 134:
                    return "⑥";
                case 135:
                    return "⑦";
                case 136:
                    return "⑧";
                case 137:
                    return "⑨";
                case 138:
                    return "⑩";
                case 139:
                    return "⓿";
                case 140:
                    return "❶";
                case 141:
                    return "❷";
                case 142:
                    return "❸";
                case 143:
                    return "❹";
                case 144:
                    return "❺";
                case 145:
                    return "❻";
                case 146:
                    return "❼";
                case 147:
                    return "❽";
                case 148:
                    return "❾";
                case 149:
                    return "❿";
                case 158:
                    return "·";
                case 159:
                    return "•";
                case 160:
                case 166:
                    return "▪";
                case 161:
                    return "○";
                case 162:
                case 164:
                    return "⭕";
                case 165:
                    return "◎";
                case 167:
                    return "✖";
                case 168:
                    return "◻";
                case 170:
                    return "✦";
                case 171:
                    return "★";
                case 172:
                    return "✶";
                case 173:
                    return "✴";
                case 174:
                    return "✹";
                case 175:
                    return "✵";
                case 177:
                    return "⌖";
                case 178:
                    return "⟡";
                case 179:
                    return "⌑";
                case 181:
                    return "✪";
                case 182:
                    return "✰";
                case 195:
                case 197:
                case 215:
                case 219:
                case 223:
                case 231:
                    return "◀";
                case 196:
                case 198:
                case 224:
                    return "▶";
                case 213:
                    return "⌫";
                case 214:
                    return "⌦";
                case 216:
                    return "➢";
                case 220:
                    return "➲";
                case 232:
                    return "➔";
                case 233:
                case 199:
                case 200:
                case 217:
                case 221:
                case 225:
                    return "◭";
                case 234:
                case 201:
                case 202:
                case 218:
                case 222:
                case 226:
                    return "⧨";
                case 239:
                    return "⇦";
                case 240:
                    return "⇨";
                case 241:
                    return "◭";
                case 242:
                    return "⧨";
                case 243:
                    return "⬄";
                case 244:
                    return "⇳";
                case 245:
                case 227:
                case 235:
                    return "↖";
                case 246:
                case 228:
                case 236:
                    return "↗";
                case 247:
                case 229:
                case 237:
                    return "↙";
                case 248:
                case 230:
                case 238:
                    return "↘";
                case 249:
                    return "▭";
                case 250:
                    return "▫";
                case 251:
                    return "✗";
                case 252:
                    return "✓";
                case 253:
                    return "☒";
                case 254:
                    return "☑";
                default:
                    return xArrow;
            }
        }
        class Mq4OutputDataSeries : IMq4DoubleArray
        {
            public IndicatorDataSeries OutputDataSeries { get; private set; }
            private readonly IndicatorDataSeries _originalValues;
            private int _currentIndex;
            private int _shift;
            private double _emptyValue = EMPTY_VALUE;
            private readonly ChartObjects _chartObjects;
            private readonly int _style;
            private readonly int _bufferIndex;
            private readonly ConvertedRobot _indicator;

            public Mq4OutputDataSeries(ConvertedRobot indicator, IndicatorDataSeries outputDataSeries, ChartObjects chartObjects, int style, int bufferIndex, Func<IndicatorDataSeries> dataSeriesFactory, int lineWidth, Colors? color = null)
            {
                OutputDataSeries = outputDataSeries;
                _chartObjects = chartObjects;
                _style = style;
                _bufferIndex = bufferIndex;
                _indicator = indicator;
                Color = color;
                _originalValues = dataSeriesFactory();
                LineWidth = lineWidth;
            }

            public int LineWidth { get; private set; }
            public Colors? Color { get; private set; }

            public int Length
            {
                get { return OutputDataSeries.Count; }
            }

            public void Resize(int newSize)
            {
            }

            public void SetCurrentIndex(int index)
            {
                _currentIndex = index;
            }

            public void SetShift(int shift)
            {
                _shift = shift;
            }

            public void SetEmptyValue(double emptyValue)
            {
                _emptyValue = emptyValue;
            }

            public Mq4Double this[int index]
            {
                get
                {
                    var indexToGetFrom = _currentIndex - index + _shift;
                    if (indexToGetFrom < 0 || indexToGetFrom > _currentIndex)
                        return 0;
                    if (indexToGetFrom >= _originalValues.Count)
                        return _emptyValue;

                    return _originalValues[indexToGetFrom];
                }
                set
                {
                    var indexToSet = _currentIndex - index + _shift;
                    if (indexToSet < 0)
                        return;

                    _originalValues[indexToSet] = value;

                    var valueToSet = value;
                    if (valueToSet == _emptyValue)
                        valueToSet = double.NaN;

                    if (indexToSet < 0)
                        return;

                    OutputDataSeries[indexToSet] = valueToSet;

                    switch (_style)
                    {
                        case DRAW_ARROW:
                            var arrowName = GetArrowName(indexToSet);
                            if (double.IsNaN(valueToSet))
                                _chartObjects.RemoveObject(arrowName);
                            else
                            {
                                var color = Color.HasValue ? Color.Value : Colors.Red;
                                _chartObjects.DrawText(arrowName, _indicator.ArrowByIndex[_bufferIndex], indexToSet, valueToSet, VerticalAlignment.Center, HorizontalAlignment.Center, color);
                            }
                            break;
                        case DRAW_HISTOGRAM:
                            if (false)
                            {
                                var anotherLine = _indicator.AllBuffers.FirstOrDefault(b => b.LineWidth == LineWidth && b != this);
                                if (anotherLine != null)
                                {
                                    var name = GetNameOfHistogramLineOnChartWindow(indexToSet);
                                    Colors color;
                                    if (this[index] > anotherLine[index])
                                        color = Color ?? Colors.Green;
                                    else
                                        color = anotherLine.Color ?? Colors.Green;
                                    var lineWidth = LineWidth;
                                    if (lineWidth != 1 && lineWidth < 5)
                                        lineWidth = 5;

                                    _chartObjects.DrawLine(name, indexToSet, this[index], indexToSet, anotherLine[index], color, lineWidth);
                                }
                            }
                            break;
                    }
                }
            }

            private string GetNameOfHistogramLineOnChartWindow(int index)
            {
                return string.Format("Histogram on chart window {0} {1}", LineWidth, index);
            }

            private string GetArrowName(int index)
            {
                return string.Format("Arrow {0} {1}", GetHashCode(), index);
            }
        }
















        public Dictionary<int, string> ArrowByIndex = new Dictionary<int, string> 
        {
            {
                0,
                xArrow
            },
            {
                1,
                xArrow
            },
            {
                2,
                xArrow
            },
            {
                3,
                xArrow
            },
            {
                4,
                xArrow
            },
            {
                5,
                xArrow
            },
            {
                6,
                xArrow
            },
            {
                7,
                xArrow
            }
        };
        void SetIndexArrow(int index, int code)
        {
            ArrowByIndex[index] = GetArrowByCode(code);
        }

        private int _indicatorCounted;
        int FILE_READ = 1;
        int FILE_WRITE = 2;
//int FILE_BIN = 8;
        int FILE_CSV = 8;

        int SEEK_END = 2;

        class FileInfo
        {
            public int Mode { get; set; }
            public int Handle { get; set; }
            public char Separator { get; set; }
            public string FileName { get; set; }
            public List<string> PendingParts { get; set; }
            public StreamWriter StreamWriter { get; set; }
            public StreamReader StreamReader { get; set; }
        }

        private Dictionary<int, FileInfo> _openedFiles = new Dictionary<int, FileInfo>();
        private int _handleCounter = 1000;







        class FolderPaths
        {
            public static string _2calgoAppDataFolder
            {
                get
                {
                    var result = Path.Combine(SystemAppData, "2calgo");
                    if (!Directory.Exists(result))
                        Directory.CreateDirectory(result);
                    return result;
                }
            }

            public static string _2calgoDesktopFolder
            {
                get
                {
                    var result = Path.Combine(Desktop, "2calgo");
                    if (!Directory.Exists(result))
                        Directory.CreateDirectory(result);
                    return result;
                }
            }

            static string SystemAppData
            {
                get { return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); }
            }

            static string Desktop
            {
                get { return Environment.GetFolderPath(Environment.SpecialFolder.Desktop); }
            }
        }
        const int MODE_TRADES = 0;
        const int MODE_HISTORY = 1;
        const int SELECT_BY_POS = 0;
        const int SELECT_BY_TICKET = 1;

        T GetPropertyValue<T>(Func<Position, T> getFromPosition, Func<PendingOrder, T> getFromPendingOrder, Func<HistoricalTrade, T> getFromHistory)
        {
            if (_currentOrder == null)
                return default(T);

            return GetPropertyValue<T>(_currentOrder, getFromPosition, getFromPendingOrder, getFromHistory);
        }

        T GetPropertyValue<T>(object obj, Func<Position, T> getFromPosition, Func<PendingOrder, T> getFromPendingOrder, Func<HistoricalTrade, T> getFromHistory)
        {
            if (obj is Position)
                return getFromPosition((Position)obj);
            if (obj is PendingOrder)
                return getFromPendingOrder((PendingOrder)obj);

            return getFromHistory((HistoricalTrade)obj);
        }

        private Mq4Double GetTicket(object trade)
        {
            return new Mq4Double(GetPropertyValue<int>(trade, _ => _.Id, _ => _.Id, _ => _.ClosingDealId));
        }
        Mq4Double OrderTicket()
        {
            if (_currentOrder == null)
                return 0;

            return GetTicket(_currentOrder);
        }
        private int GetMagicNumber(string label)
        {
            int magicNumber;
            if (int.TryParse(label, out magicNumber))
                return magicNumber;

            return 0;
        }

        private int GetMagicNumber(object order)
        {
            var label = GetPropertyValue<string>(order, _ => _.Label, _ => _.Label, _ => _.Label);
            return GetMagicNumber(label);
        }
        Mq4Double OrderMagicNumber()
        {
            if (_currentOrder == null)
                return 0;

            return GetMagicNumber(_currentOrder);
        }


        Mq4Double OrdersTotal()
        {
            return Positions.Count + PendingOrders.Count;
        }

        Mq4Double HistoryTotal()
        {
            return History.Count;
        }

        object _currentOrder;
        bool OrderSelect(int index, int @select, int pool = MODE_TRADES)
        {
            _currentOrder = null;

            if (pool == MODE_TRADES)
            {
                var allOrders = Positions.OfType<object>().Concat(PendingOrders.OfType<object>()).ToArray();

                switch (@select)
                {
                    case SELECT_BY_POS:
                        if (index < 0 || index >= allOrders.Length)
                            return false;

                        _currentOrder = allOrders[index];
                        return true;
                    case SELECT_BY_TICKET:
                        _currentOrder = GetOrderByTicket(index);
                        return _currentOrder != null;
                }
            }
            if (pool == MODE_HISTORY)
            {
                switch (@select)
                {
                    case SELECT_BY_POS:
                        if (index < 0 || index >= History.Count)
                            return false;

                        _currentOrder = History[index];
                        return true;
                    case SELECT_BY_TICKET:
                        _currentOrder = History.FindLast(index.ToString());
                        return _currentOrder != null;
                }
            }

            return false;
        }
        double GetLots(object order)
        {
            var volume = GetPropertyValue<long>(order, _ => _.Volume, _ => _.Volume, _ => _.Volume);
            var symbolCode = GetPropertyValue<string>(order, _ => _.SymbolCode, _ => _.SymbolCode, _ => _.SymbolCode);
            var symbolObject = MarketData.GetSymbol(symbolCode);

            return symbolObject.ToLotsVolume(volume);
        }

        object GetOrderByTicket(int ticket)
        {
            var allOrders = Positions.OfType<object>().Concat(PendingOrders.OfType<object>()).ToArray();

            return allOrders.FirstOrDefault(_ => GetTicket(_) == ticket);
        }
        Mq4Double OrderLots()
        {
            if (_currentOrder == null)
                return 0;

            return GetLots(_currentOrder);
        }

        Mq4Double OrderType()
        {
            if (_currentOrder == null)
                return 0;

            var position = _currentOrder as Position;
            if (position != null)
            {
                return position.TradeType == TradeType.Buy ? OP_BUY : OP_SELL;
            }
            var pendingOrder = _currentOrder as PendingOrder;
            if (pendingOrder != null)
            {
                if (pendingOrder.OrderType == PendingOrderType.Limit)
                    return pendingOrder.TradeType == TradeType.Buy ? OP_BUYLIMIT : OP_SELLLIMIT;
                return pendingOrder.TradeType == TradeType.Buy ? OP_BUYSTOP : OP_SELLSTOP;
            }

            var historicalTrade = (HistoricalTrade)_currentOrder;

            return historicalTrade.TradeType == TradeType.Buy ? OP_BUY : OP_SELL;
        }

        Mq4String OrderSymbol()
        {
            return GetPropertyValue<string>(_ => _.SymbolCode, _ => _.SymbolCode, _ => _.SymbolCode);
        }
        double GetOpenPrice(object order)
        {
            return GetPropertyValue<double>(order, _ => _.EntryPrice, _ => _.TargetPrice, _ => _.EntryPrice);
        }
        Mq4Double OrderOpenPrice()
        {
            if (_currentOrder == null)
                return 0;

            return GetOpenPrice(_currentOrder);
        }


        private double GetStopLoss(object order)
        {
            var nullableValue = GetPropertyValue<double?>(order, _ => _.StopLoss, _ => _.StopLoss, _ => 0);
            return nullableValue ?? 0;
        }

        private double GetTakeProfit(object order)
        {
            var nullableValue = GetPropertyValue<double?>(order, _ => _.TakeProfit, _ => _.TakeProfit, _ => 0);
            return nullableValue ?? 0;
        }
        Mq4Double OrderStopLoss()
        {
            if (_currentOrder == null)
                return 0;
            return GetStopLoss(_currentOrder);
        }

        Mq4Double OrderTakeProfit()
        {
            if (_currentOrder == null)
                return 0;
            return GetTakeProfit(_currentOrder);
        }

        Mq4Double OrderProfit()
        {
            var position = _currentOrder as Position;
            if (position != null)
                return position.NetProfit;

            var historicalTrade = _currentOrder as HistoricalTrade;
            if (historicalTrade != null)
                return historicalTrade.NetProfit;

            return 0;
        }







        Mq4Double AccountFreeMargin()
        {
            return Account.FreeMargin;
        }






        Mq4Double AccountLeverage()
        {
            return Account.Leverage;
        }








        class ParametersKey
        {
            private readonly object[] _parameters;

            public ParametersKey(params object[] parameters)
            {
                _parameters = parameters;
            }

            public override bool Equals(object obj)
            {
                var other = (ParametersKey)obj;
                for (var i = 0; i < _parameters.Length; i++)
                {
                    if (!_parameters[i].Equals(other._parameters[i]))
                        return false;
                }
                return true;
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    var hashCode = 0;
                    foreach (var parameter in _parameters)
                    {
                        hashCode = (hashCode * 397) ^ parameter.GetHashCode();
                    }
                    return hashCode;
                }
            }
        }

        class Cache<TValue>
        {
            private Dictionary<ParametersKey, TValue> _dictionary = new Dictionary<ParametersKey, TValue>();

            public bool TryGetValue(out TValue value, params object[] parameters)
            {
                var key = new ParametersKey(parameters);
                return _dictionary.TryGetValue(key, out value);
            }

            public void Add(TValue value, params object[] parameters)
            {
                var key = new ParametersKey(parameters);
                _dictionary.Add(key, value);
            }
        }


        private static MovingAverageType ToMaType(int constant)
        {
            switch (constant)
            {
                case MODE_SMA:
                    return MovingAverageType.Simple;
                case MODE_EMA:
                    return MovingAverageType.Exponential;
                case MODE_LWMA:
                    return MovingAverageType.Weighted;
                default:
                    throw new ArgumentOutOfRangeException("Not supported moving average type");
            }
        }


















//{
        internal class CustomIndicatorParameters
        {
            public MarketSeries MarketSeries { get; set; }
            public object[] Parameters { get; set; }

            protected bool Equals(CustomIndicatorParameters other)
            {
                if (Parameters.Length != other.Parameters.Length)
                    return false;
                for (var i = 0; i < Parameters.Length; i++)
                {
                    if (!Equals(Parameters[i], other.Parameters[i]))
                        return false;
                }

                return Equals(MarketSeries, other.MarketSeries);
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                    return false;
                if (ReferenceEquals(this, obj))
                    return true;
                if (obj.GetType() != this.GetType())
                    return false;
                return Equals((CustomIndicatorParameters)obj);
            }

            public override int GetHashCode()
            {
                return (MarketSeries != null ? MarketSeries.GetHashCode() : 0);
            }
        }

        private List<DataSeries> GetAllOutputDataSeries(object indicatorInstance)
        {
            var fieldInfo = indicatorInstance.GetType().GetField("AllOutputDataSeries");
            return (List<DataSeries>)fieldInfo.GetValue(indicatorInstance);
        }

        private object CastParameter(object parameter)
        {
            if (parameter is Mq4Double)
            {
                var mq4Double = (Mq4Double)parameter;
                if (Math.Abs(mq4Double - (int)mq4Double) < Symbol.TickSize)
                    return (int)mq4Double;
                return (double)mq4Double;
            }
            if (parameter is string || parameter is Mq4String)
            {
                return (string)parameter;
            }
            return parameter;
        }

        private object[] CastParameters<T>(object[] parameters)
        {
            return parameters.Select(CastParameter).ToArray();
        }

        private static object[] AddEmailParametersIfNeeded<T>(object[] parameters)
        {
            var needed = typeof(T).GetProperties().Where(info => info.GetCustomAttributes(typeof(ParameterAttribute), false).Any()).Any(p => p.Name == "EmailAddressFrom");

            var result = new List<object>();
            result.AddRange(parameters);
            if (needed)
            {
                result.Insert(0, string.Empty);
                result.Insert(0, string.Empty);
            }
            return result.ToArray();
        }

        private readonly Dictionary<CustomIndicatorParameters, List<DataSeries>> _customIndicatorsCache = new Dictionary<CustomIndicatorParameters, List<DataSeries>>();

        Mq4Double iCustom<T>(Mq4String symbol, Mq4Double timeframe, Mq4String name, params object[] parameters) where T : Indicator
        {
            var marketSeries = GetSeries(symbol, timeframe);
            var indicatorParameters = CastParameters<T>(parameters.Take(parameters.Length - 2).ToArray());
            indicatorParameters = AddEmailParametersIfNeeded<T>(indicatorParameters);

            var customIndicatorParameters = new CustomIndicatorParameters 
            {
                MarketSeries = marketSeries,
                Parameters = indicatorParameters
            };
            List<DataSeries> outputSeries;
            if (!_customIndicatorsCache.TryGetValue(customIndicatorParameters, out outputSeries))
            {
                var customIndicator = Indicators.GetIndicator<T>(marketSeries, indicatorParameters);
                outputSeries = GetAllOutputDataSeries(customIndicator);
                _customIndicatorsCache[customIndicatorParameters] = outputSeries;
            }

            var mode = (int)CastParameter(parameters[parameters.Length - 2]);
            var shift = (int)CastParameter(parameters[parameters.Length - 1]);
            return outputSeries[mode].Last(shift);
        }
//}








        class CachedStandardIndicators
        {
            private readonly IIndicatorsAccessor _indicatorsAccessor;

            public CachedStandardIndicators(IIndicatorsAccessor indicatorsAccessor)
            {
                _indicatorsAccessor = indicatorsAccessor;
            }

        }
        const bool True = true;
        const bool False = false;
        const bool TRUE = true;
        const bool FALSE = false;
        Mq4Null NULL;
        const int EMPTY = -1;
        const double EMPTY_VALUE = 2147483647;
        public const int WHOLE_ARRAY = 0;

        const int MODE_SMA = 0;
        //Simple moving average
        const int MODE_EMA = 1;
        //Exponential moving average,
        const int MODE_SMMA = 2;
        //Smoothed moving average,
        const int MODE_LWMA = 3;
        //Linear weighted moving average. 
        const int PRICE_CLOSE = 0;
        //Close price. 
        const int PRICE_OPEN = 1;
        //Open price. 
        const int PRICE_HIGH = 2;
        //High price. 
        const int PRICE_LOW = 3;
        //Low price. 
        const int PRICE_MEDIAN = 4;
        //Median price, (high+low)/2. 
        const int PRICE_TYPICAL = 5;
        //Typical price, (high+low+close)/3. 
        const int PRICE_WEIGHTED = 6;
        //Weighted close price, (high+low+close+close)/4. 
        const int DRAW_LINE = 0;
        const int DRAW_SECTION = 1;
        const int DRAW_HISTOGRAM = 2;
        const int DRAW_ARROW = 3;
        const int DRAW_ZIGZAG = 4;
        const int DRAW_NONE = 12;

        const int STYLE_SOLID = 0;
        const int STYLE_DASH = 1;
        const int STYLE_DOT = 2;
        const int STYLE_DASHDOT = 3;
        const int STYLE_DASHDOTDOT = 4;

        const int MODE_OPEN = 0;
        const int MODE_LOW = 1;
        const int MODE_HIGH = 2;
        const int MODE_CLOSE = 3;
        const int MODE_VOLUME = 4;
        const int MODE_TIME = 5;
        const int MODE_BID = 9;
        const int MODE_ASK = 10;
        const int MODE_POINT = 11;
        const int MODE_DIGITS = 12;
        const int MODE_SPREAD = 13;
        const int MODE_TRADEALLOWED = 22;
        const int MODE_PROFITCALCMODE = 27;
        const int MODE_MARGINCALCMODE = 28;
        const int MODE_SWAPTYPE = 26;
        const int MODE_TICKSIZE = 17;
        const int MODE_FREEZELEVEL = 33;
        const int MODE_STOPLEVEL = 14;
        const int MODE_LOTSIZE = 15;
        const int MODE_TICKVALUE = 16;
        /*const int MODE_SWAPLONG = 18;
const int MODE_SWAPSHORT = 19;
const int MODE_STARTING = 20;
const int MODE_EXPIRATION = 21;    
*/
        const int MODE_MINLOT = 23;
        const int MODE_LOTSTEP = 24;
        const int MODE_MAXLOT = 25;
        /*const int MODE_MARGININIT = 29;
const int MODE_MARGINMAINTENANCE = 30;
const int MODE_MARGINHEDGED = 31;*/
        const int MODE_MARGINREQUIRED = 32;

        const int OBJ_VLINE = 0;
        const int OBJ_HLINE = 1;
        const int OBJ_TREND = 2;
        const int OBJ_FIBO = 10;

        /*const int OBJ_TRENDBYANGLE = 3;
    const int OBJ_REGRESSION = 4;
    const int OBJ_CHANNEL = 5;
    const int OBJ_STDDEVCHANNEL = 6;
    const int OBJ_GANNLINE = 7;
    const int OBJ_GANNFAN = 8;
    const int OBJ_GANNGRID = 9;
    const int OBJ_FIBOTIMES = 11;
    const int OBJ_FIBOFAN = 12;
    const int OBJ_FIBOARC = 13;
    const int OBJ_EXPANSION = 14;
    const int OBJ_FIBOCHANNEL = 15;*/
        const int OBJ_RECTANGLE = 16;
        /*const int OBJ_TRIANGLE = 17;
    const int OBJ_ELLIPSE = 18;
    const int OBJ_PITCHFORK = 19;
    const int OBJ_CYCLES = 20;*/
        const int OBJ_TEXT = 21;
        const int OBJ_ARROW = 22;
        const int OBJ_LABEL = 23;

        const int OBJPROP_TIME1 = 0;
        const int OBJPROP_PRICE1 = 1;
        const int OBJPROP_TIME2 = 2;
        const int OBJPROP_PRICE2 = 3;
        const int OBJPROP_TIME3 = 4;
        const int OBJPROP_PRICE3 = 5;
        const int OBJPROP_COLOR = 6;
        const int OBJPROP_STYLE = 7;
        const int OBJPROP_WIDTH = 8;
        const int OBJPROP_BACK = 9;
        const int OBJPROP_RAY = 10;
        const int OBJPROP_ELLIPSE = 11;
        //const int OBJPROP_SCALE = 12;
        const int OBJPROP_ANGLE = 13;
        //angle for text rotation
        const int OBJPROP_ARROWCODE = 14;
        const int OBJPROP_TIMEFRAMES = 15;
        //const int OBJPROP_DEVIATION = 16;
        const int OBJPROP_FONTSIZE = 100;
        const int OBJPROP_CORNER = 101;
        const int OBJPROP_XDISTANCE = 102;
        const int OBJPROP_YDISTANCE = 103;
        const int OBJPROP_FIBOLEVELS = 200;
        const int OBJPROP_LEVELCOLOR = 201;
        const int OBJPROP_LEVELSTYLE = 202;
        const int OBJPROP_LEVELWIDTH = 203;
        const int OBJPROP_FIRSTLEVEL = 210;

        const int PERIOD_M1 = 1;
        const int PERIOD_M5 = 5;
        const int PERIOD_M15 = 15;
        const int PERIOD_M30 = 30;
        const int PERIOD_H1 = 60;
        const int PERIOD_H4 = 240;
        const int PERIOD_D1 = 1440;
        const int PERIOD_W1 = 10080;
        const int PERIOD_MN1 = 43200;

        const int TIME_DATE = 1;
        const int TIME_MINUTES = 2;
        const int TIME_SECONDS = 4;

        const int MODE_MAIN = 0;
        const int MODE_BASE = 0;
        const int MODE_PLUSDI = 1;
        const int MODE_MINUSDI = 2;
        const int MODE_SIGNAL = 1;

        const int MODE_UPPER = 1;
        const int MODE_LOWER = 2;

        const int MODE_GATORLIPS = 3;
        const int MODE_GATORJAW = 1;
        const int MODE_GATORTEETH = 2;

        const int CLR_NONE = 32768;

        const int White = 16777215;
        const int Snow = 16448255;
        const int MintCream = 16449525;
        const int LavenderBlush = 16118015;
        const int AliceBlue = 16775408;
        const int Honeydew = 15794160;
        const int Ivory = 15794175;
        const int Seashell = 15660543;
        const int WhiteSmoke = 16119285;
        const int OldLace = 15136253;
        const int MistyRose = 14804223;
        const int Lavender = 16443110;
        const int Linen = 15134970;
        const int LightCyan = 16777184;
        const int LightYellow = 14745599;
        const int Cornsilk = 14481663;
        const int PapayaWhip = 14020607;
        const int AntiqueWhite = 14150650;
        const int Beige = 14480885;
        const int LemonChiffon = 13499135;
        const int BlanchedAlmond = 13495295;
        const int LightGoldenrod = 13826810;
        const int Bisque = 12903679;
        const int Pink = 13353215;
        const int PeachPuff = 12180223;
        const int Gainsboro = 14474460;
        const int LightPink = 12695295;
        const int Moccasin = 11920639;
        const int NavajoWhite = 11394815;
        const int Wheat = 11788021;
        const int LightGray = 13882323;
        const int PaleTurquoise = 15658671;
        const int PaleGoldenrod = 11200750;
        const int PowderBlue = 15130800;
        const int Thistle = 14204888;
        const int PaleGreen = 10025880;
        const int LightBlue = 15128749;
        const int LightSteelBlue = 14599344;
        const int LightSkyBlue = 16436871;
        const int Silver = 12632256;
        const int Aquamarine = 13959039;
        const int LightGreen = 9498256;
        const int Khaki = 9234160;
        const int Plum = 14524637;
        const int LightSalmon = 8036607;
        const int SkyBlue = 15453831;
        const int LightCoral = 8421616;
        const int Violet = 15631086;
        const int Salmon = 7504122;
        const int HotPink = 11823615;
        const int BurlyWood = 8894686;
        const int DarkSalmon = 8034025;
        const int Tan = 9221330;
        const int MediumSlateBlue = 15624315;
        const int SandyBrown = 6333684;
        const int DarkGray = 11119017;
        const int CornflowerBlue = 15570276;
        const int Coral = 5275647;
        const int PaleVioletRed = 9662683;
        const int MediumPurple = 14381203;
        const int Orchid = 14053594;
        const int RosyBrown = 9408444;
        const int Tomato = 4678655;
        const int DarkSeaGreen = 9419919;
        const int Cyan = 16776960;
        const int MediumAquamarine = 11193702;
        const int GreenYellow = 3145645;
        const int MediumOrchid = 13850042;
        const int IndianRed = 6053069;
        const int DarkKhaki = 7059389;
        const int SlateBlue = 13458026;
        const int RoyalBlue = 14772545;
        const int Turquoise = 13688896;
        const int DodgerBlue = 16748574;
        const int MediumTurquoise = 13422920;
        const int DeepPink = 9639167;
        const int LightSlateGray = 10061943;
        const int BlueViolet = 14822282;
        const int Peru = 4163021;
        const int SlateGray = 9470064;
        const int Gray = 8421504;
        const int Red = 255;
        const int Magenta = 16711935;
        const int Blue = 16711680;
        const int DeepSkyBlue = 16760576;
        const int Aqua = 16776960;
        const int SpringGreen = 8388352;
        const int Lime = 65280;
        const int Chartreuse = 65407;
        const int Yellow = 65535;
        const int Gold = 55295;
        const int Orange = 42495;
        const int DarkOrange = 36095;
        const int OrangeRed = 17919;
        const int LimeGreen = 3329330;
        const int YellowGreen = 3329434;
        const int DarkOrchid = 13382297;
        const int CadetBlue = 10526303;
        const int LawnGreen = 64636;
        const int MediumSpringGreen = 10156544;
        const int Goldenrod = 2139610;
        const int SteelBlue = 11829830;
        const int Crimson = 3937500;
        const int Chocolate = 1993170;
        const int MediumSeaGreen = 7451452;
        const int MediumVioletRed = 8721863;
        const int FireBrick = 2237106;
        const int DarkViolet = 13828244;
        const int LightSeaGreen = 11186720;
        const int DimGray = 6908265;
        const int DarkTurquoise = 13749760;
        const int Brown = 2763429;
        const int MediumBlue = 13434880;
        const int Sienna = 2970272;
        const int DarkSlateBlue = 9125192;
        const int DarkGoldenrod = 755384;
        const int SeaGreen = 5737262;
        const int OliveDrab = 2330219;
        const int ForestGreen = 2263842;
        const int SaddleBrown = 1262987;
        const int DarkOliveGreen = 3107669;
        const int DarkBlue = 9109504;
        const int MidnightBlue = 7346457;
        const int Indigo = 8519755;
        const int Maroon = 128;
        const int Purple = 8388736;
        const int Navy = 8388608;
        const int Teal = 8421376;
        const int Green = 32768;
        const int Olive = 32896;
        const int DarkSlateGray = 5197615;
        const int DarkGreen = 25600;
        const int Fuchsia = 16711935;
        const int Black = 0;

        const int SYMBOL_LEFTPRICE = 5;
        const int SYMBOL_RIGHTPRICE = 6;

        const int SYMBOL_ARROWUP = 241;
        const int SYMBOL_ARROWDOWN = 242;
        const int SYMBOL_STOPSIGN = 251;
        /*
const int SYMBOL_THUMBSUP = 67;
const int SYMBOL_THUMBSDOWN = 68;	
const int SYMBOL_CHECKSIGN = 25;
*/

        public const int MODE_ASCEND = 1;
        public const int MODE_DESCEND = 2;

        const int MODE_TENKANSEN = 1;
        const int MODE_KIJUNSEN = 2;
        const int MODE_SENKOUSPANA = 3;
        const int MODE_SENKOUSPANB = 4;
        const int MODE_CHINKOUSPAN = 5;
        const int OP_BUY = 0;
        const int OP_SELL = 1;
        const int OP_BUYLIMIT = 2;
        const int OP_SELLLIMIT = 3;
        const int OP_BUYSTOP = 4;
        const int OP_SELLSTOP = 5;
        const int OBJ_PERIOD_M1 = 0x1;
        const int OBJ_PERIOD_M5 = 0x2;
        const int OBJ_PERIOD_M15 = 0x4;
        const int OBJ_PERIOD_M30 = 0x8;
        const int OBJ_PERIOD_H1 = 0x10;
        const int OBJ_PERIOD_H4 = 0x20;
        const int OBJ_PERIOD_D1 = 0x40;
        const int OBJ_PERIOD_W1 = 0x80;
        const int OBJ_PERIOD_MN1 = 0x100;
        const int OBJ_ALL_PERIODS = 0x1ff;

        const int REASON_REMOVE = 1;
        const int REASON_RECOMPILE = 2;
        const int REASON_CHARTCHANGE = 3;
        const int REASON_CHARTCLOSE = 4;
        const int REASON_PARAMETERS = 5;
        const int REASON_ACCOUNT = 6;
        const int ERR_NO_ERROR = 0;
        const int ERR_NO_RESULT = 1;
        const int ERR_COMMON_ERROR = 2;
        const int ERR_INVALID_TRADE_PARAMETERS = 3;
        const int ERR_SERVER_BUSY = 4;
        const int ERR_OLD_VERSION = 5;
        const int ERR_NO_CONNECTION = 6;
        const int ERR_NOT_ENOUGH_RIGHTS = 7;
        const int ERR_TOO_FREQUENT_REQUESTS = 8;
        const int ERR_MALFUNCTIONAL_TRADE = 9;
        const int ERR_ACCOUNT_DISABLED = 64;
        const int ERR_INVALID_ACCOUNT = 65;
        const int ERR_TRADE_TIMEOUT = 128;
        const int ERR_INVALID_PRICE = 129;
        const int ERR_INVALID_STOPS = 130;
        const int ERR_INVALID_TRADE_VOLUME = 131;
        const int ERR_MARKET_CLOSED = 132;
        const int ERR_TRADE_DISABLED = 133;
        const int ERR_NOT_ENOUGH_MONEY = 134;
        const int ERR_PRICE_CHANGED = 135;
        const int ERR_OFF_QUOTES = 136;
        const int ERR_BROKER_BUSY = 137;
        const int ERR_REQUOTE = 138;
        const int ERR_ORDER_LOCKED = 139;
        const int ERR_LONG_POSITIONS_ONLY_ALLOWED = 140;
        const int ERR_TOO_MANY_REQUESTS = 141;
        const int ERR_TRADE_MODIFY_DENIED = 145;
        const int ERR_TRADE_CONTEXT_BUSY = 146;
        const int ERR_TRADE_EXPIRATION_DENIED = 147;
        const int ERR_TRADE_TOO_MANY_ORDERS = 148;
        const int ERR_TRADE_HEDGE_PROHIBITED = 149;
        const int ERR_TRADE_PROHIBITED_BY_FIFO = 150;
        const int ERR_NO_MQLERROR = 4000;
        const int ERR_WRONG_FUNCTION_POINTER = 4001;
        const int ERR_ARRAY_INDEX_OUT_OF_RANGE = 4002;
        const int ERR_NO_MEMORY_FOR_CALL_STACK = 4003;
        const int ERR_RECURSIVE_STACK_OVERFLOW = 4004;
        const int ERR_NOT_ENOUGH_STACK_FOR_PARAM = 4005;
        const int ERR_NO_MEMORY_FOR_PARAM_STRING = 4006;
        const int ERR_NO_MEMORY_FOR_TEMP_STRING = 4007;
        const int ERR_NOT_INITIALIZED_STRING = 4008;
        const int ERR_NOT_INITIALIZED_ARRAYSTRING = 4009;
        const int ERR_NO_MEMORY_FOR_ARRAYSTRING = 4010;
        const int ERR_TOO_LONG_STRING = 4011;
        const int ERR_REMAINDER_FROM_ZERO_DIVIDE = 4012;
        const int ERR_ZERO_DIVIDE = 4013;
        const int ERR_UNKNOWN_COMMAND = 4014;
        const int ERR_WRONG_JUMP = 4015;
        const int ERR_NOT_INITIALIZED_ARRAY = 4016;
        const int ERR_DLL_CALLS_NOT_ALLOWED = 4017;
        const int ERR_CANNOT_LOAD_LIBRARY = 4018;
        const int ERR_CANNOT_CALL_FUNCTION = 4019;
        const int ERR_EXTERNAL_CALLS_NOT_ALLOWED = 4020;
        const int ERR_NO_MEMORY_FOR_RETURNED_STR = 4021;
        const int ERR_SYSTEM_BUSY = 4022;
        const int ERR_INVALID_FUNCTION_PARAMSCNT = 4050;
        const int ERR_INVALID_FUNCTION_PARAMVALUE = 4051;
        const int ERR_STRING_FUNCTION_INTERNAL = 4052;
        const int ERR_SOME_ARRAY_ERROR = 4053;
        const int ERR_INCORRECT_SERIESARRAY_USING = 4054;
        const int ERR_CUSTOM_INDICATOR_ERROR = 4055;
        const int ERR_INCOMPATIBLE_ARRAYS = 4056;
        const int ERR_GLOBAL_VARIABLES_PROCESSING = 4057;
        const int ERR_GLOBAL_VARIABLE_NOT_FOUND = 4058;
        const int ERR_FUNC_NOT_ALLOWED_IN_TESTING = 4059;
        const int ERR_FUNCTION_NOT_CONFIRMED = 4060;
        const int ERR_SEND_MAIL_ERROR = 4061;
        const int ERR_STRING_PARAMETER_EXPECTED = 4062;
        const int ERR_INTEGER_PARAMETER_EXPECTED = 4063;
        const int ERR_DOUBLE_PARAMETER_EXPECTED = 4064;
        const int ERR_ARRAY_AS_PARAMETER_EXPECTED = 4065;
        const int ERR_HISTORY_WILL_UPDATED = 4066;
        const int ERR_TRADE_ERROR = 4067;
        const int ERR_END_OF_FILE = 4099;
        const int ERR_SOME_FILE_ERROR = 4100;
        const int ERR_WRONG_FILE_NAME = 4101;
        const int ERR_TOO_MANY_OPENED_FILES = 4102;
        const int ERR_CANNOT_OPEN_FILE = 4103;
        const int ERR_INCOMPATIBLE_FILEACCESS = 4104;
        const int ERR_NO_ORDER_SELECTED = 4105;
        const int ERR_UNKNOWN_SYMBOL = 4106;
        const int ERR_INVALID_PRICE_PARAM = 4107;
        const int ERR_INVALID_TICKET = 4108;
        const int ERR_TRADE_NOT_ALLOWED = 4109;
        const int ERR_LONGS_NOT_ALLOWED = 4110;
        const int ERR_SHORTS_NOT_ALLOWED = 4111;
        const int ERR_OBJECT_ALREADY_EXISTS = 4200;
        const int ERR_UNKNOWN_OBJECT_PROPERTY = 4201;
        const int ERR_OBJECT_DOES_NOT_EXIST = 4202;
        const int ERR_UNKNOWN_OBJECT_TYPE = 4203;
        const int ERR_NO_OBJECT_NAME = 4204;
        const int ERR_OBJECT_COORDINATES_ERROR = 4205;
        const int ERR_NO_SPECIFIED_SUBWINDOW = 4206;
        const int ERR_SOME_OBJECT_ERROR = 4207;
        class Mq4ChartObjects
        {
            private readonly ChartObjects _algoChartObjects;
            private readonly TimeSeries _timeSeries;

            private readonly Dictionary<string, Mq4Object> _mq4ObjectByName = new Dictionary<string, Mq4Object>();
            private readonly List<string> _mq4ObjectNameByIndex = new List<string>();

            public Mq4ChartObjects(ChartObjects chartObjects, TimeSeries timeSeries)
            {
                _algoChartObjects = chartObjects;
                _timeSeries = timeSeries;
            }

            public void Set(string name, int index, Mq4Double value)
            {
                if (!_mq4ObjectByName.ContainsKey(name))
                    return;
                _mq4ObjectByName[name].Set(index, value);
                _mq4ObjectByName[name].Draw();
            }
            public void SetText(string name, string text, int font_size, string font, int color)
            {
                if (!_mq4ObjectByName.ContainsKey(name))
                    return;

                Set(name, OBJPROP_COLOR, color);
            }







            private T GetObject<T>(string name) where T : Mq4Object
            {
                Mq4Object mq4Object;
                if (!_mq4ObjectByName.TryGetValue(name, out mq4Object))
                    return null;
                return mq4Object as T;
            }

        }

        abstract class Mq4Object : IDisposable
        {
            private readonly ChartObjects _chartObjects;

            protected Mq4Object(string name, int type, ChartObjects chartObjects)
            {
                Name = name;
                Type = type;
                _chartObjects = chartObjects;
            }

            public int Type { get; private set; }

            public string Name { get; private set; }

            protected DateTime Time1
            {
                get
                {
                    int seconds = Get(OBJPROP_TIME1);
                    return Mq4TimeSeries.ToDateTime(seconds);
                }
            }

            protected double Price1
            {
                get { return Get(OBJPROP_PRICE1); }
            }

            protected DateTime Time2
            {
                get
                {
                    int seconds = Get(OBJPROP_TIME2);
                    return Mq4TimeSeries.ToDateTime(seconds);
                }
            }

            protected double Price2
            {
                get { return Get(OBJPROP_PRICE2); }
            }

            protected Colors Color
            {
                get
                {
                    int intColor = Get(OBJPROP_COLOR);
                    if (intColor != CLR_NONE)
                        return Mq4Colors.GetColorByInteger(intColor);

                    return Colors.Yellow;
                }
            }

            protected int Width
            {
                get { return Get(OBJPROP_WIDTH); }
            }

            protected int Style
            {
                get { return Get(OBJPROP_STYLE); }
            }

            public abstract void Draw();

            private readonly Dictionary<int, Mq4Double> _properties = new Dictionary<int, Mq4Double> 
            {
                {
                    OBJPROP_WIDTH,
                    new Mq4Double(1)
                },
                {
                    OBJPROP_COLOR,
                    new Mq4Double(CLR_NONE)
                },
                {
                    OBJPROP_RAY,
                    new Mq4Double(1)
                },

                {
                    OBJPROP_LEVELCOLOR,
                    new Mq4Double(CLR_NONE)
                },
                {
                    OBJPROP_LEVELSTYLE,
                    new Mq4Double(0)
                },
                {
                    OBJPROP_LEVELWIDTH,
                    new Mq4Double(1)
                },
                {
                    OBJPROP_FIBOLEVELS,
                    new Mq4Double(9)
                },
                {
                    OBJPROP_FIRSTLEVEL + 0,
                    new Mq4Double(0)
                },
                {
                    OBJPROP_FIRSTLEVEL + 1,
                    new Mq4Double(0.236)
                },
                {
                    OBJPROP_FIRSTLEVEL + 2,
                    new Mq4Double(0.382)
                },
                {
                    OBJPROP_FIRSTLEVEL + 3,
                    new Mq4Double(0.5)
                },
                {
                    OBJPROP_FIRSTLEVEL + 4,
                    new Mq4Double(0.618)
                },
                {
                    OBJPROP_FIRSTLEVEL + 5,
                    new Mq4Double(1)
                },
                {
                    OBJPROP_FIRSTLEVEL + 6,
                    new Mq4Double(1.618)
                },
                {
                    OBJPROP_FIRSTLEVEL + 7,
                    new Mq4Double(2.618)
                },
                {
                    OBJPROP_FIRSTLEVEL + 8,
                    new Mq4Double(4.236)
                }
            };

            public virtual void Set(int index, Mq4Double value)
            {
                _properties[index] = value;
            }

            public Mq4Double Get(int index)
            {
                return _properties.ContainsKey(index) ? _properties[index] : new Mq4Double(0);
            }

            private readonly List<string> _addedAlgoChartObjects = new List<string>();

            protected void DrawText(string objectName, string text, int index, double yValue, VerticalAlignment verticalAlignment = VerticalAlignment.Center, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center, Colors? color = null)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawText(objectName, text, index, yValue, verticalAlignment, horizontalAlignment, color);
            }

            protected void DrawText(string objectName, string text, StaticPosition position, Colors? color = null)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawText(objectName, text, position, color);
            }

            protected void DrawLine(string objectName, int index1, double y1, int index2, double y2, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawLine(objectName, index1, y1, index2, y2, color, thickness, style);
            }

            protected void DrawLine(string objectName, DateTime date1, double y1, DateTime date2, double y2, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawLine(objectName, date1, y1, date2, y2, color, thickness, style);
            }

            protected void DrawVerticalLine(string objectName, DateTime date, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawVerticalLine(objectName, date, color, thickness, style);
            }

            protected void DrawVerticalLine(string objectName, int index, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawVerticalLine(objectName, index, color, thickness, style);
            }

            protected void DrawHorizontalLine(string objectName, double y, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
            {
                _addedAlgoChartObjects.Add(objectName);
                _chartObjects.DrawHorizontalLine(objectName, y, color, thickness, style);
            }

            public void Dispose()
            {
                foreach (var name in _addedAlgoChartObjects)
                {
                    _chartObjects.RemoveObject(name);
                }
            }
        }





        class Mq4Arrow : Mq4Object
        {
            private readonly TimeSeries _timeSeries;
            private int _index;

            public Mq4Arrow(string name, int type, ChartObjects chartObjects, TimeSeries timeSeries) : base(name, type, chartObjects)
            {
                _timeSeries = timeSeries;
            }

            public override void Set(int index, Mq4Double value)
            {
                base.Set(index, value);
                switch (index)
                {
                    case OBJPROP_TIME1:
                        _index = _timeSeries.GetIndexByTime(Time1);
                        break;
                }
            }

            private int ArrowCode
            {
                get { return Get(OBJPROP_ARROWCODE); }
            }

            public override void Draw()
            {
                string arrowString;
                HorizontalAlignment horizontalAlignment;
                switch (ArrowCode)
                {
                    case SYMBOL_RIGHTPRICE:
                        horizontalAlignment = HorizontalAlignment.Right;
                        arrowString = Price1.ToString();
                        break;
                    case SYMBOL_LEFTPRICE:
                        horizontalAlignment = HorizontalAlignment.Left;
                        arrowString = Price1.ToString();
                        break;
                    default:
                        arrowString = ConvertedRobot.GetArrowByCode(ArrowCode);
                        horizontalAlignment = HorizontalAlignment.Center;
                        break;
                }
                DrawText(Name, arrowString, _index, Price1, VerticalAlignment.Center, horizontalAlignment, Color);
            }
        }















        Mq4Double OrderSend(Mq4String symbol, int cmd, Mq4Double volume, Mq4Double price, Mq4Double slippagePoints, Mq4Double stoploss, Mq4Double takeprofit, Mq4String comment = null, Mq4Double? magic = null, int expiration = 0,
        int arrow_color = CLR_NONE)
        {
            _lastError = ERR_NO_ERROR;
            if (magic == null)
                magic = 0;
            var label = magic.Value.ToString();

            var symbolObject = GetSymbol(symbol);
            var volumeInUnits = symbolObject.ToUnitsVolume(volume);

            switch (cmd)
            {
                case OP_BUY:
                case OP_SELL:
                    {
                        var tradeType = cmd == OP_BUY ? TradeType.Buy : TradeType.Sell;
                        var slippageInPrice = symbolObject.TickSize * slippagePoints;
                        var slippageInPips = (int)Math.Round((double)slippageInPrice / symbolObject.PipSize);
                        double? stopLossPips = null;
                        if (stoploss != 0)
                            stopLossPips = tradeType == TradeType.Buy ? (symbolObject.Ask - stoploss) / symbolObject.PipSize : (stoploss - symbolObject.Bid) / symbolObject.PipSize;
                        double? takeProfitPips = null;
                        if (takeprofit != 0)
                            takeProfitPips = tradeType == TradeType.Buy ? (takeprofit - symbolObject.Ask) / symbolObject.PipSize : (symbolObject.Bid - takeprofit) / symbolObject.PipSize;

                        var marketOrderResult = ExecuteMarketOrder(tradeType, symbolObject, volumeInUnits, label, stopLossPips, takeProfitPips, slippageInPips, comment);

                        if (marketOrderResult.IsSuccessful)
                            return GetTicket(marketOrderResult.Position);
                        else
                        {
                            _lastError = ToMq4ErrorCode(marketOrderResult.Error.Value);
                            return -1;
                        }
                    }
                case OP_BUYLIMIT:
                case OP_SELLLIMIT:
                case OP_BUYSTOP:
                case OP_SELLSTOP:
                    {
                        var tradeType = cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? TradeType.Buy : TradeType.Sell;

                        double? stopLossPips = null;
                        if (stoploss != 0)
                            stopLossPips = tradeType == TradeType.Buy ? (price - stoploss) / symbolObject.PipSize : (stoploss - price) / symbolObject.PipSize;
                        double? takeProfitPips = null;
                        if (takeprofit != 0)
                            takeProfitPips = tradeType == TradeType.Buy ? (takeprofit - price) / symbolObject.PipSize : (price - takeprofit) / symbolObject.PipSize;

                        TradeResult placeOrderResult;
                        if (cmd == OP_BUYLIMIT || cmd == OP_SELLLIMIT)
                            placeOrderResult = PlaceLimitOrder(tradeType, symbolObject, volumeInUnits, price, label, stopLossPips, takeProfitPips, expiration.ToNullableDateTime(), comment);
                        else
                            placeOrderResult = PlaceStopOrder(tradeType, symbolObject, volumeInUnits, price, label, stopLossPips, takeProfitPips, expiration.ToNullableDateTime(), comment);

                        if (placeOrderResult.IsSuccessful)
                            return GetTicket(placeOrderResult.PendingOrder);
                        else
                        {
                            _lastError = ToMq4ErrorCode(placeOrderResult.Error.Value);
                            return -1;
                        }
                    }
                default:
                    throw new Exception("Not supported by converter");
            }

            return 0;
        }
        Mq4Double OrderClose(int ticket, double lots, double price, int slippagePoints, int Color = CLR_NONE)
        {
            _lastError = ERR_NO_ERROR;

            var position = GetOrderByTicket(ticket) as Position;
            if (position == null)
            {
                _lastError = ERR_INVALID_TICKET;
                return false;
            }
            var symbolObject = MarketData.GetSymbol(position.SymbolCode);

            var volumeInUnits = symbolObject.ToUnitsVolume(lots);
            ClosePosition(position, volumeInUnits);

            if (!LastResult.IsSuccessful)
                _lastError = ToMq4ErrorCode(LastResult.Error.Value);

            return LastResult.IsSuccessful;
        }

        Mq4Double OrderModify(int ticket, double price, double stoploss, double takeprofit, int expiration, int arrow_color = CLR_NONE)
        {
            _lastError = ERR_NO_ERROR;

            var order = GetOrderByTicket(ticket);
            if (GetTakeProfit(order) == takeprofit && GetStopLoss(order) == stoploss && GetOpenPrice(order) == price)
            {
                _lastError = ERR_NO_RESULT;
                return false;
            }

            var position = order as Position;
            if (position != null)
            {
                ModifyPosition(position, stoploss.ToNullableDouble(), takeprofit.ToNullableDouble());
                if (!LastResult.IsSuccessful)
                    _lastError = ToMq4ErrorCode(LastResult.Error.Value);

                return LastResult.IsSuccessful;
            }

            var pendingOrder = (PendingOrder)order;
            var expirationTime = expiration.ToNullableDateTime();
            ModifyPendingOrder(pendingOrder, price, stoploss.ToNullableDouble(), takeprofit.ToNullableDouble(), expirationTime);

            if (!LastResult.IsSuccessful)
                _lastError = ToMq4ErrorCode(LastResult.Error.Value);

            return LastResult.IsSuccessful;
        }


    }

    //Custom Indicators Place Holder

    class Mq4DoubleComparer : IComparer<Mq4Double>
    {
        public int Compare(Mq4Double x, Mq4Double y)
        {
            return x.CompareTo(y);
        }
    }
    class Mq4String
    {
        private readonly string _value;

        public Mq4String(string value)
        {
            _value = value;
        }

        public static implicit operator Mq4String(string value)
        {
            return new Mq4String(value);
        }

        public static implicit operator Mq4String(int value)
        {
            return new Mq4String(value.ToString());
        }

        public static implicit operator Mq4String(Mq4Null mq4Null)
        {
            return new Mq4String(null);
        }

        public static implicit operator string(Mq4String mq4String)
        {
            if ((object)mq4String == null)
                return null;

            return mq4String._value;
        }

        public static implicit operator Mq4String(Mq4Double mq4Double)
        {
            return new Mq4String(mq4Double.ToString());
        }

        public static bool operator <(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) == -1;
        }

        public static bool operator >(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) == 1;
        }

        public static bool operator <(Mq4String x, string y)
        {
            return string.Compare(x._value, y) == -1;
        }

        public static bool operator >(Mq4String x, string y)
        {
            return string.Compare(x._value, y) == 1;
        }
        public static bool operator <=(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) <= 0;
        }

        public static bool operator >=(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) >= 0;
        }

        public static bool operator <=(Mq4String x, string y)
        {
            return string.Compare(x._value, y) <= 0;
        }

        public static bool operator >=(Mq4String x, string y)
        {
            return string.Compare(x._value, y) >= 0;
        }

        public static bool operator ==(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) == 0;
        }

        public static bool operator !=(Mq4String x, Mq4String y)
        {
            return string.Compare(x._value, y._value) != 0;
        }

        public static bool operator ==(Mq4String x, string y)
        {
            return string.Compare(x._value, y) == 0;
        }

        public static bool operator !=(Mq4String x, string y)
        {
            return string.Compare(x._value, y) != 0;
        }

        public override string ToString()
        {
            if ((object)this == null)
                return string.Empty;

            return _value.ToString();
        }

        public static readonly Mq4String Empty = new Mq4String(string.Empty);

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != this.GetType())
                return false;
            return Equals((Mq4String)obj);
        }

        protected bool Equals(Mq4String other)
        {
            return this == other;
        }

        public override int GetHashCode()
        {
            return (_value != null ? _value.GetHashCode() : 0);
        }
    }
    struct Mq4Char
    {
        char _char;

        public Mq4Char(byte code)
        {
            _char = Encoding.Unicode.GetString(new byte[] 
            {
                code,
                0
            })[0];
        }

        public Mq4Char(char @char)
        {
            _char = @char;
        }

        public static implicit operator char(Mq4Char mq4Char)
        {
            return mq4Char._char;
        }

        public static implicit operator Mq4Char(int code)
        {
            return new Mq4Char((byte)code);
        }

        public static implicit operator Mq4Char(string str)
        {
            if (string.IsNullOrEmpty(str) || str.Length == 0)
                return new Mq4Char(' ');
            return new Mq4Char(str[0]);
        }
    }
    struct Mq4Null
    {
        public static implicit operator string(Mq4Null mq4Null)
        {
            return (string)null;
        }

        public static implicit operator int(Mq4Null mq4Null)
        {
            return 0;
        }

        public static implicit operator double(Mq4Null mq4Null)
        {
            return 0;
        }
    }
    static class Comparers
    {
        public static IComparer<T> GetComparer<T>()
        {
            if (typeof(T) == typeof(Mq4Double))
                return (IComparer<T>)new Mq4DoubleComparer();

            return Comparer<T>.Default;
        }
    }
    static class DataSeriesExtensions
    {
        public static int InvertIndex(this DataSeries dataSeries, int index)
        {
            return dataSeries.Count - 1 - index;
        }

        public static Mq4Double Last(this DataSeries dataSeries, int shift, DataSeries sourceDataSeries)
        {
            return dataSeries[sourceDataSeries.Count - 1 - shift];
        }
    }
    static class TimeSeriesExtensions
    {
        public static DateTime Last(this TimeSeries timeSeries, int index)
        {
            return timeSeries[timeSeries.InvertIndex(index)];
        }

        public static int InvertIndex(this TimeSeries timeSeries, int index)
        {
            return timeSeries.Count - 1 - index;
        }

        public static int GetIndexByTime(this TimeSeries timeSeries, DateTime time)
        {
            var index = timeSeries.Count - 1;
            for (var i = timeSeries.Count - 1; i >= 0; i--)
            {
                if (timeSeries[i] < time)
                {
                    index = i + 1;
                    break;
                }
            }
            return index;
        }
    }
    static class Mq4Colors
    {
        public static Colors GetColorByInteger(int integer)
        {
            switch (integer)
            {
                case 16777215:
                    return Colors.White;
                case 16448255:
                    return Colors.Snow;
                case 16449525:
                    return Colors.MintCream;
                case 16118015:
                    return Colors.LavenderBlush;
                case 16775408:
                    return Colors.AliceBlue;
                case 15794160:
                    return Colors.Honeydew;
                case 15794175:
                    return Colors.Ivory;
                case 16119285:
                    return Colors.WhiteSmoke;
                case 15136253:
                    return Colors.OldLace;
                case 14804223:
                    return Colors.MistyRose;
                case 16443110:
                    return Colors.Lavender;
                case 15134970:
                    return Colors.Linen;
                case 16777184:
                    return Colors.LightCyan;
                case 14745599:
                    return Colors.LightYellow;
                case 14481663:
                    return Colors.Cornsilk;
                case 14020607:
                    return Colors.PapayaWhip;
                case 14150650:
                    return Colors.AntiqueWhite;
                case 14480885:
                    return Colors.Beige;
                case 13499135:
                    return Colors.LemonChiffon;
                case 13495295:
                    return Colors.BlanchedAlmond;
                case 12903679:
                    return Colors.Bisque;
                case 13353215:
                    return Colors.Pink;
                case 12180223:
                    return Colors.PeachPuff;
                case 14474460:
                    return Colors.Gainsboro;
                case 12695295:
                    return Colors.LightPink;
                case 11920639:
                    return Colors.Moccasin;
                case 11394815:
                    return Colors.NavajoWhite;
                case 11788021:
                    return Colors.Wheat;
                case 13882323:
                    return Colors.LightGray;
                case 15658671:
                    return Colors.PaleTurquoise;
                case 11200750:
                    return Colors.PaleGoldenrod;
                case 15130800:
                    return Colors.PowderBlue;
                case 14204888:
                    return Colors.Thistle;
                case 10025880:
                    return Colors.PaleGreen;
                case 15128749:
                    return Colors.LightBlue;
                case 14599344:
                    return Colors.LightSteelBlue;
                case 16436871:
                    return Colors.LightSkyBlue;
                case 12632256:
                    return Colors.Silver;
                case 13959039:
                    return Colors.Aquamarine;
                case 9498256:
                    return Colors.LightGreen;
                case 9234160:
                    return Colors.Khaki;
                case 14524637:
                    return Colors.Plum;
                case 8036607:
                    return Colors.LightSalmon;
                case 15453831:
                    return Colors.SkyBlue;
                case 8421616:
                    return Colors.LightCoral;
                case 15631086:
                    return Colors.Violet;
                case 7504122:
                    return Colors.Salmon;
                case 11823615:
                    return Colors.HotPink;
                case 8894686:
                    return Colors.BurlyWood;
                case 8034025:
                    return Colors.DarkSalmon;
                case 9221330:
                    return Colors.Tan;
                case 15624315:
                    return Colors.MediumSlateBlue;
                case 6333684:
                    return Colors.SandyBrown;
                case 11119017:
                    return Colors.DarkGray;
                case 15570276:
                    return Colors.CornflowerBlue;
                case 5275647:
                    return Colors.Coral;
                case 9662683:
                    return Colors.PaleVioletRed;
                case 14381203:
                    return Colors.MediumPurple;
                case 14053594:
                    return Colors.Orchid;
                case 9408444:
                    return Colors.RosyBrown;
                case 4678655:
                    return Colors.Tomato;
                case 9419919:
                    return Colors.DarkSeaGreen;
                case 11193702:
                    return Colors.MediumAquamarine;
                case 3145645:
                    return Colors.GreenYellow;
                case 13850042:
                    return Colors.MediumOrchid;
                case 6053069:
                    return Colors.IndianRed;
                case 7059389:
                    return Colors.DarkKhaki;
                case 13458026:
                    return Colors.SlateBlue;
                case 14772545:
                    return Colors.RoyalBlue;
                case 13688896:
                    return Colors.Turquoise;
                case 16748574:
                    return Colors.DodgerBlue;
                case 13422920:
                    return Colors.MediumTurquoise;
                case 9639167:
                    return Colors.DeepPink;
                case 10061943:
                    return Colors.LightSlateGray;
                case 14822282:
                    return Colors.BlueViolet;
                case 4163021:
                    return Colors.Peru;
                case 9470064:
                    return Colors.SlateGray;
                case 8421504:
                    return Colors.Gray;
                case 255:
                    return Colors.Red;
                case 16711935:
                    return Colors.Magenta;
                case 16711680:
                    return Colors.Blue;
                case 16760576:
                    return Colors.DeepSkyBlue;
                case 16776960:
                    return Colors.Aqua;
                case 8388352:
                    return Colors.SpringGreen;
                case 65280:
                    return Colors.Lime;
                case 65407:
                    return Colors.Chartreuse;
                case 65535:
                    return Colors.Yellow;
                case 55295:
                    return Colors.Gold;
                case 42495:
                    return Colors.Orange;
                case 36095:
                    return Colors.DarkOrange;
                case 17919:
                    return Colors.OrangeRed;
                case 3329330:
                    return Colors.LimeGreen;
                case 3329434:
                    return Colors.YellowGreen;
                case 13382297:
                    return Colors.DarkOrchid;
                case 10526303:
                    return Colors.CadetBlue;
                case 64636:
                    return Colors.LawnGreen;
                case 10156544:
                    return Colors.MediumSpringGreen;
                case 2139610:
                    return Colors.Goldenrod;
                case 11829830:
                    return Colors.SteelBlue;
                case 3937500:
                    return Colors.Crimson;
                case 1993170:
                    return Colors.Chocolate;
                case 7451452:
                    return Colors.MediumSeaGreen;
                case 8721863:
                    return Colors.MediumVioletRed;
                case 13828244:
                    return Colors.DarkViolet;
                case 11186720:
                    return Colors.LightSeaGreen;
                case 6908265:
                    return Colors.DimGray;
                case 13749760:
                    return Colors.DarkTurquoise;
                case 2763429:
                    return Colors.Brown;
                case 13434880:
                    return Colors.MediumBlue;
                case 2970272:
                    return Colors.Sienna;
                case 9125192:
                    return Colors.DarkSlateBlue;
                case 755384:
                    return Colors.DarkGoldenrod;
                case 5737262:
                    return Colors.SeaGreen;
                case 2330219:
                    return Colors.OliveDrab;
                case 2263842:
                    return Colors.ForestGreen;
                case 1262987:
                    return Colors.SaddleBrown;
                case 3107669:
                    return Colors.DarkOliveGreen;
                case 9109504:
                    return Colors.DarkBlue;
                case 7346457:
                    return Colors.MidnightBlue;
                case 8519755:
                    return Colors.Indigo;
                case 128:
                    return Colors.Maroon;
                case 8388736:
                    return Colors.Purple;
                case 8388608:
                    return Colors.Navy;
                case 8421376:
                    return Colors.Teal;
                case 32768:
                    return Colors.Green;
                case 32896:
                    return Colors.Olive;
                case 5197615:
                    return Colors.DarkSlateGray;
                case 25600:
                    return Colors.DarkGreen;
                case 0:
                default:
                    return Colors.Black;
            }
        }
    }
    static class EventExtensions
    {
        public static void Raise<T1, T2>(this Action<T1, T2> action, T1 arg1, T2 arg2)
        {
            if (action != null)
                action(arg1, arg2);
        }
    }
    static class Mq4LineStyles
    {
        public static LineStyle ToLineStyle(int style)
        {
            switch (style)
            {
                case 1:
                    return LineStyle.Lines;
                case 2:
                    return LineStyle.Dots;
                case 3:
                case 4:
                    return LineStyle.LinesDots;
                default:
                    return LineStyle.Solid;
            }
        }
    }
    class Mq4TimeSeries
    {
        private readonly TimeSeries _timeSeries;
        private static readonly DateTime StartDateTime = new DateTime(1970, 1, 1);

        public Mq4TimeSeries(TimeSeries timeSeries)
        {
            _timeSeries = timeSeries;
        }

        public static int ToInteger(DateTime dateTime)
        {
            return (int)(dateTime - StartDateTime).TotalSeconds;
        }

        public static DateTime ToDateTime(int seconds)
        {
            return StartDateTime.AddSeconds(seconds);
        }

        public int this[int index]
        {
            get
            {
                if (index < 0 || index >= _timeSeries.Count)
                    return 0;

                DateTime dateTime = _timeSeries[_timeSeries.Count - 1 - index];

                return ToInteger(dateTime);
            }
        }
    }
    static class ConvertExtensions
    {
        public static double? ToNullableDouble(this double protection)
        {
            if (protection == 0)
                return null;
            return protection;
        }

        public static DateTime? ToNullableDateTime(this int time)
        {
            if (time == 0)
                return null;

            return Mq4TimeSeries.ToDateTime(time);
        }

        public static long ToUnitsVolume(this Symbol symbol, double lots)
        {
            return symbol.NormalizeVolume(symbol.ToNotNormalizedUnitsVolume(lots));
        }

        public static double ToNotNormalizedUnitsVolume(this Symbol symbol, double lots)
        {
            if (symbol.Code.Contains("XAU") || symbol.Code.Contains("XAG"))
                return 100 * lots;

            return 100000 * lots;
        }

        public static double ToLotsVolume(this Symbol symbol, long volume)
        {
            if (symbol.Code.Contains("XAU") || symbol.Code.Contains("XAG"))
                return volume * 1.0 / 100;

            return volume * 1.0 / 100000;
        }
    }
    struct Mq4Double : IComparable, IComparable<Mq4Double>
    {
        private readonly double _value;

        public Mq4Double(double value)
        {
            _value = value;
        }

        public static implicit operator double(Mq4Double property)
        {
            return property._value;
        }

        public static implicit operator int(Mq4Double property)
        {
            return (int)property._value;
        }

        public static implicit operator bool(Mq4Double property)
        {
            return (int)property._value != 0;
        }

        public static implicit operator Mq4Double(double value)
        {
            return new Mq4Double(value);
        }

        public static implicit operator Mq4Double(int value)
        {
            return new Mq4Double(value);
        }

        public static implicit operator Mq4Double(bool value)
        {
            return new Mq4Double(value ? 1 : 0);
        }

        public static implicit operator Mq4Double(Mq4Null value)
        {
            return new Mq4Double(0);
        }

        public static Mq4Double operator +(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value + d2._value);
        }

        public static Mq4Double operator -(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value - d2._value);
        }

        public static Mq4Double operator -(Mq4Double d)
        {
            return new Mq4Double(-d._value);
        }

        public static Mq4Double operator +(Mq4Double d)
        {
            return new Mq4Double(+d._value);
        }

        public static Mq4Double operator *(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value * d2._value);
        }

        public static Mq4Double operator /(Mq4Double d1, Mq4Double d2)
        {
            return new Mq4Double(d1._value / d2._value);
        }

        public static bool operator ==(Mq4Double d1, Mq4Double d2)
        {
            return d1._value == d2._value;
        }

        public static bool operator >(Mq4Double d1, Mq4Double d2)
        {
            return d1._value > d2._value;
        }

        public static bool operator >=(Mq4Double d1, Mq4Double d2)
        {
            return d1._value >= d2._value;
        }

        public static bool operator <(Mq4Double d1, Mq4Double d2)
        {
            return d1._value < d2._value;
        }

        public static bool operator <=(Mq4Double d1, Mq4Double d2)
        {
            return d1._value <= d2._value;
        }

        public static bool operator !=(Mq4Double d1, Mq4Double d2)
        {
            return d1._value != d2._value;
        }

        public override string ToString()
        {
            return _value.ToString();
        }

        public int CompareTo(object obj)
        {
            return _value.CompareTo(obj);
        }

        public int CompareTo(Mq4Double obj)
        {
            return _value.CompareTo(obj);
        }
    }
    class Mq4DoubleTwoDimensionalArray
    {
        private List<Mq4Double> _data = new List<Mq4Double>();
        private List<Mq4DoubleArray> _arrays = new List<Mq4DoubleArray>();
        private readonly Mq4Double _defaultValue;
        private readonly int _size2;

        public Mq4DoubleTwoDimensionalArray(int size2)
        {
            _defaultValue = 0;
            _size2 = size2;
        }

        public void Add(Mq4Double value)
        {
            _data.Add(value);
        }

        private void EnsureCountIsEnough(int index)
        {
            while (_arrays.Count <= index)
                _arrays.Add(new Mq4DoubleArray());
        }

        public void Initialize(Mq4Double value)
        {
            for (var i = 0; i < _data.Count; i++)
                _data[i] = value;
        }

        public int Range(int index)
        {
            if (index == 0)
                return _data.Count;
            return this[0].Length;
        }

        public Mq4DoubleArray this[int index]
        {
            get
            {
                if (index < 0)
                    return new Mq4DoubleArray();

                EnsureCountIsEnough(index);

                return _arrays[index];
            }
        }

        public Mq4Double this[int index1, int index2]
        {
            get
            {
                if (index1 < 0)
                    return 0;

                EnsureCountIsEnough(index1);

                return _arrays[index1][index2];
            }
            set
            {
                if (index1 < 0)
                    return;

                EnsureCountIsEnough(index1);

                _arrays[index1][index2] = value;
            }
        }
    }
    class Mq4DoubleArray : IMq4DoubleArray, IEnumerable
    {
        private List<Mq4Double> _data = new List<Mq4Double>();
        private readonly Mq4Double _defaultValue;

        public Mq4DoubleArray(int size = 0)
        {
            _defaultValue = 0;
        }

        public IEnumerator GetEnumerator()
        {
            return _data.GetEnumerator();
        }

        private bool _isInverted;
        public bool IsInverted
        {
            get { return _isInverted; }
            set { _isInverted = value; }
        }

        public void Add(Mq4Double value)
        {
            _data.Add(value);
        }

        private void EnsureCountIsEnough(int index)
        {
            while (_data.Count <= index)
                _data.Add(_defaultValue);
        }

        public int Length
        {
            get { return _data.Count; }
        }

        public void Resize(int newSize)
        {
            while (newSize < _data.Count)
                _data.RemoveAt(_data.Count - 1);

            while (newSize > _data.Count)
                _data.Add(_defaultValue);
        }

        public Mq4Double this[int index]
        {
            get
            {
                if (index < 0)
                    return _defaultValue;

                EnsureCountIsEnough(index);

                return _data[index];
            }
            set
            {
                if (index < 0)
                    return;

                EnsureCountIsEnough(index);

                _data[index] = value;
                Changed.Raise(index, value);
            }
        }
        public event Action<int, Mq4Double> Changed;
    }
    class Mq4MarketDataSeries : IMq4DoubleArray
    {
        private DataSeries _dataSeries;

        public Mq4MarketDataSeries(DataSeries dataSeries)
        {
            _dataSeries = dataSeries;
        }

        public Mq4Double this[int index]
        {
            get { return _dataSeries.Last(index); }
            set { }
        }

        public int Length
        {
            get { return _dataSeries.Count; }
        }

        public void Resize(int newSize)
        {
        }
    }
    class Mq4StringArray : IEnumerable
    {
        private List<Mq4String> _data = new List<Mq4String>();
        private readonly Mq4String _defaultValue;

        public Mq4StringArray(int size = 0)
        {
            _defaultValue = "";
        }

        public IEnumerator GetEnumerator()
        {
            return _data.GetEnumerator();
        }

        private bool _isInverted;
        public bool IsInverted
        {
            get { return _isInverted; }
            set { _isInverted = value; }
        }

        public void Add(Mq4String value)
        {
            _data.Add(value);
        }

        private void EnsureCountIsEnough(int index)
        {
            while (_data.Count <= index)
                _data.Add(_defaultValue);
        }

        public int Length
        {
            get { return _data.Count; }
        }

        public void Resize(int newSize)
        {
            while (newSize < _data.Count)
                _data.RemoveAt(_data.Count - 1);

            while (newSize > _data.Count)
                _data.Add(_defaultValue);
        }

        public Mq4String this[int index]
        {
            get
            {
                if (index < 0)
                    return _defaultValue;

                EnsureCountIsEnough(index);

                return _data[index];
            }
            set
            {
                if (index < 0)
                    return;

                EnsureCountIsEnough(index);

                _data[index] = value;
            }
        }
    }
    interface IMq4DoubleArray
    {
        Mq4Double this[int index] { get; set; }
        int Length { get; }
        void Resize(int newSize);
    }
    class Mq4ArrayToDataSeriesConverter
    {
        private readonly Mq4DoubleArray _mq4Array;
        private readonly IndicatorDataSeries _dataSeries;

        public Mq4ArrayToDataSeriesConverter(Mq4DoubleArray mq4Array, IndicatorDataSeries dataSeries)
        {
            _mq4Array = mq4Array;
            _dataSeries = dataSeries;
            _mq4Array.Changed += OnValueChanged;
            CopyAllValues();
        }

        private void CopyAllValues()
        {
            for (var i = 0; i < _mq4Array.Length; i++)
            {
                if (_mq4Array.IsInverted)
                    _dataSeries[_mq4Array.Length - i] = _mq4Array[i];
                else
                    _dataSeries[i] = _mq4Array[i];
            }
        }

        private void OnValueChanged(int index, Mq4Double value)
        {
            int indexToSet;
            if (_mq4Array.IsInverted)
                indexToSet = _mq4Array.Length - index;
            else
                indexToSet = index;

            if (indexToSet < 0)
                return;

            _dataSeries[indexToSet] = value;
        }
    }
    class Mq4ArrayToDataSeriesConverterFactory
    {
        private readonly Dictionary<Mq4DoubleArray, IndicatorDataSeries> _cachedAdapters = new Dictionary<Mq4DoubleArray, IndicatorDataSeries>();
        private Func<IndicatorDataSeries> _dataSeriesFactory;

        public Mq4ArrayToDataSeriesConverterFactory(Func<IndicatorDataSeries> dataSeriesFactory)
        {
            _dataSeriesFactory = dataSeriesFactory;
        }

        public DataSeries Create(Mq4DoubleArray mq4Array)
        {
            IndicatorDataSeries dataSeries;

            if (_cachedAdapters.TryGetValue(mq4Array, out dataSeries))
                return dataSeries;

            dataSeries = _dataSeriesFactory();
            new Mq4ArrayToDataSeriesConverter(mq4Array, dataSeries);
            _cachedAdapters[mq4Array] = dataSeries;

            return dataSeries;
        }
    }

}

 


@tgjobscv

tgjobscv
16 Dec 2019, 20:02

Braintrend V1

 

errors what wrong? 

//#reference: ..\Indicators\BrainTrend1_Indicator.algo
//#reference: ..\Indicators\BrainTrend1Sig_Indicator.algo
//#reference: ..\Indicators\BrainTrend2Sig_Indicator.algo
//#reference: ..\Indicators\BrainTrend1StopLine_Indicator.algo
//#reference: ..\Indicators\BrainTrend2StopLine_Indicator.algo
// ------------------------------------------------------------                   
// Paste this code into your cAlgo editor. 
// -----------------------------------------------------------
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using cAlgo.API.Requests;
// ---------------------------------------------------------------------------                   
// Converted from MQ4 to cAlgo with http://2calgo.com
// ---------------------------------------------------------------------------

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.FullAccess)]
    public class BrainExpert_v1_Robot : Robot
    {
Mq4Double Mq4Init()
{
CurrBar = iTime(Symbol.Code,TimeFrameMq4,0);
  PrevBar = iTime(Symbol.Code,TimeFrameMq4,1);
   return 0;
  return 0;}
Mq4Double ScanTradesFunc()
{
Mq4Double cnt = 0;
Mq4Double numords = 0;
Mq4Double total = 0;   
   total = OrdersTotal();
   numords = 0;
      
   for(cnt=0; cnt<total; cnt++) 
   {        
   OrderSelect(cnt, SELECT_BY_POS);            
   if(OrderSymbol() == Symbol.Code && OrderType()<=OP_SELLSTOP && OrderMagicNumber() == Magic) 
   numords++;
   }
   return numords;
return 0;}
Mq4Double ConfirmSignalFunc(Mq4Double mode, Mq4Double num)
{
Mq4Double lo = 0;
Mq4Double hi = 0;
Mq4Double loBT1 = 0;
Mq4Double hiBT1 = 0;
Mq4Double i = 0;
Mq4Double result = 0;   
   result = 0; 
   
   
   for (i=num;i>=1;i--)
   { 
   hiBT1 = iCustom<BrainTrend1_Indicator>(Symbol.Code,0,"BrainTrend1",500,1,i); 
   loBT1 = iCustom<BrainTrend1_Indicator>(Symbol.Code,0,"BrainTrend1",500,0,i);
   hi = High[i];
   lo = Low[i];
   if (mode==1 && result>=0 && (hiBT1 != lo && loBT1 != hi)) {result+=1;}
   
   if (mode==2 && result<=0 && (hiBT1 != hi && loBT1 != lo)) {result-=1;}  
   
   }
   
   return result; 
return 0;}
Mq4Double TradeSignalFunc()
{
Mq4Double sellBT2 = 0;
Mq4Double sellBT1 = 0;
Mq4Double buyBT2 = 0;
Mq4Double buyBT1 = 0;   
   
   buyBT1  = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend1Sig",500,0,0,1,1);
   buyBT2  = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend2Sig",500,0,1);
   
   sellBT1 = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend1Sig",500,0,0,0,1);
   sellBT2 = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend2Sig",500,1,1);
   
   
   
   if (TimeHour(CurTime()) >= SessionStart && TimeHour(CurTime()) <= SessionEnd)
   {
   if ( buyBT1>0 && sellBT1<=0 && buyBT2>0 && sellBT2<=0 && ConfirmSignalFunc(1,ConfirmBars)==ConfirmBars) return  1;
   if ( buyBT1<=0 && sellBT1>0 && buyBT2<=0 && sellBT2>0 && ConfirmSignalFunc(2,ConfirmBars)==-ConfirmBars) return -1;
   }
return 0;}
Mq4Double MoneyManagementFunc(Mq4Double flag, Mq4Double Lots, Mq4Double risk, Mq4Double maxloss)
{
Lotsi=Lots;
	    
   if ( flag ) Lotsi=Lots*NormalizeDouble(Lots*AccountFreeMargin()*risk/maxloss,1);   
     
   if (Lotsi<01) Lotsi=0.1;  
      
   return Lotsi;
return 0;}
void TrailStopFunc()
{
Mq4Double SellStop = 0;
Mq4Double k = 0;
Mq4Double BuyStop = 0;
Mq4Double mode = 0;
Mq4Double cnt = 0;
Mq4Double Gain = 0;
Mq4Double result = false;
Mq4Double error = 0;
     
   result=false;
   Gain = 0;
    
   for (cnt=0;cnt<OrdersTotal();cnt++)
   { 
   OrderSelect(cnt, SELECT_BY_POS);   
   mode=OrderType();    
      if ( OrderSymbol()==Symbol.Code && OrderMagicNumber()==Magic) 
      {
         if (mode==OP_BUY) 
         {
			   if (TrailStopMode == 1 ) 
			   BuyStop = NormalizeDouble(iCustom<BrainTrend1StopLine_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend1StopLine",500,1,1),Digits);   
			   if (TrailStopMode == 2 )
			   BuyStop = NormalizeDouble(iCustom<BrainTrend2StopLine_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend2StopLine",500,0,0,1),Digits); 
			   
			   
			   if ( BreakEven>0 && BEvent==0 )
			   {
			   Gain = (MarketInfo(Symbol.Code,MODE_BID) - OrderOpenPrice())/Point;
			      if( Gain >= BreakEven && OrderStopLoss()<=OrderOpenPrice()+1*Point) 
			      {
			      BuyStop = NormalizeDouble(OrderOpenPrice()+1*Point,Digits);
			      BEvent=1;
			      }
			   }
			   
			   if ( BuyStop > NormalizeDouble(OrderStopLoss(),Digits)) 
			   {
			      for(k = 0; k < TriesNum; k++)
               {
               result = OrderModify(OrderTicket(),OrderOpenPrice(),
			                           BuyStop,
			                           OrderTakeProfit(),0,Lime);
               error=GetLastError();
                  if(error==0) break;
                  else {Sleep(5000); RefreshRates(); continue;}
               }   		 
            }            
         }   
         if (mode==OP_SELL)
         {
            if (TrailStopMode == 1 ) 
			   SellStop = NormalizeDouble(iCustom<BrainTrend1StopLine_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend1StopLine",500,0,1),Digits);   
			   if (TrailStopMode == 2 )
			   SellStop = NormalizeDouble(iCustom<BrainTrend2StopLine_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend2StopLine",500,0,1,1),Digits); 
            
            if ( BreakEven > 0 && BEvent==0)
			   {
			   Gain = (OrderOpenPrice()-MarketInfo(Symbol.Code,MODE_ASK))/Point;
			      if( Gain >= BreakEven && OrderStopLoss()>=OrderOpenPrice()-1*Point) 
			      {
			      SellStop = NormalizeDouble(OrderOpenPrice()-1*Point,Digits);
			      BEvent=-1;
			      }
			   }
			           
            if( SellStop < NormalizeDouble(OrderStopLoss(),Digits) && SellStop > 0) 
            {
               for( k = 0 ; k < TriesNum; k++)
               {
               result = OrderModify(OrderTicket(),OrderOpenPrice(),
			                           SellStop,
			                           OrderTakeProfit(),0,Orange);
               error=GetLastError();
                  if(error==0) break;
                  else {Sleep(5000); RefreshRates(); continue;}
               }
            }	    
         }
      }
   }     
return;}
void SellOrdOpenFunc()
{
Mq4Double ticket = 0;
Mq4Double SellProfit = 0;
Mq4Double SellStop = 0;
Mq4Double Mode = 0;
Mq4Double StopPrice = 0;
Mq4Double SellPrice = 0;		     
   SellPrice = Bid;
   StopPrice = Bid;
   Mode = OP_SELL;
        	  
   if (StopLossMode == 1) 
   SellStop  = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend1Sig",500,0,0,0,1);
   else
   if (StopLossMode == 2) 
   SellStop  = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend2Sig",500,1,1);
	else SellStop = 0;
	
   if (TakeProfit  > 0) SellProfit = SellPrice - TakeProfit*Point; 
   else SellProfit=0;
   
	ticket = OrderSend( Symbol.Code,Mode,MoneyManagementFunc( MM, Lots, MMRisk, MaxLoss),
	                        NormalizeDouble(SellPrice , Digits),
	                        Slippage,
	                        NormalizeDouble(SellStop  , Digits),
	                        NormalizeDouble(SellProfit, Digits),
	                        Expert_Name+" SELL",Magic,0,Red);
   
   if(ticket > 0) 
   {
      if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) 
      {
		OrderBar =iBars(OrderSymbol(),TimeFrameMq4);
		Mq4Print("SELL order opened : ", OrderOpenPrice());
      BEvent=0;
      if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol.Code + "] " + DoubleToStr(Bid, Digits) + " Open Sell");
		}
   }
	else 	
   if(GetLastError()>0)
   Mq4Print("SELL: OrderSend failed with error #",GetLastError());
   
   return;
return;}
void BuyOrdOpenFunc()
{
Mq4Double ticket = 0;
Mq4Double BuyProfit = 0;
Mq4Double BuyStop = 0;
Mq4Double Mode = 0;
Mq4Double StopPrice = 0;
Mq4Double BuyPrice = 0;		     
   BuyPrice  = Ask;
   StopPrice = Ask;
   Mode      = OP_BUY;
      
   if (StopLossMode == 1) 
   BuyStop  = iCustom<BrainTrend1Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend1Sig",500,0,0,1,1);
   else
   if (StopLossMode == 2) 
   BuyStop  = iCustom<BrainTrend2Sig_Indicator>(Symbol.Code,TimeFrameMq4,"BrainTrend2Sig",500,0,1);
   else BuyStop = 0;
   
   if (TakeProfit  > 0) BuyProfit= BuyPrice + TakeProfit*Point;  
   else BuyProfit=0;  
		 
	ticket = OrderSend(Symbol.Code,Mode, MoneyManagementFunc( MM, Lots, MMRisk, MaxLoss),
	                   NormalizeDouble(BuyPrice , Digits),
	                   Slippage,
	                   NormalizeDouble(BuyStop  , Digits), 
	                   NormalizeDouble(BuyProfit, Digits),
	                   Expert_Name+" BUY",Magic,0,Blue);
      
   if(ticket > 0) 
   {
      if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) 
      {
		OrderBar =iBars(OrderSymbol(),TimeFrameMq4); 
		Mq4Print("BUY order opened : ", OrderOpenPrice());
      BEvent=0;
      if (SignalMail) SendMail("[Signal Alert]", "[" + Symbol.Code + "] " + DoubleToStr(Ask, Digits) + " Open Buy");
		}
   }
	else 	
   if(GetLastError()>0)      
   Mq4Print("BUY : OrderSend failed with error #",GetLastError());

   return;
return;}
void CloseOrderFunc(Mq4Double mode)
{
Mq4Double i = 0;
Mq4Double total = 0;
Mq4Double result = false;
   result=false; 
   total=OrdersTotal();
   
   for (i=0; i<=OrdersTotal(); i++)  
   {
   OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if (OrderMagicNumber() == Magic && OrderSymbol() == Symbol.Code) 
      {
      if ((mode == 0 || mode ==1) && OrderType()==OP_BUY ) result=CloseAtMarketFunc(OrderTicket(),OrderLots(),Aqua);
      if ((mode == 0 || mode ==2) && OrderType()==OP_SELL) result=CloseAtMarketFunc(OrderTicket(),OrderLots(),Pink);
      }
   }
return;}
Mq4Double CloseAtMarketFunc(Mq4Double ticket, Mq4Double lot, Mq4Double clr)
{
Mq4Double tries = 0;
Mq4Double ntr = 0;
Mq4Double result = false;
   result = false; 
   
      
   tries=0;
   while (!result && tries < TriesNum) 
   {
      ntr=0; 
      
      RefreshRates();
      result=OrderClose(ticket,lot,OrderClosePrice(),Slippage,clr);
      tries++;
   }
   if (!result) Mq4Print("Error closing order : ",ErrorDescription(GetLastError()));
   return result;
return true;}
Mq4Double deinitFunc()
{
return 0;
  return 0;}
Mq4Double Mq4Start()
{
if(iBars(Symbol.Code,TimeFrameMq4)< 100 || IsTradeAllowed()==false) return 0; 
      
   if(AccountFreeMargin()< 1000*MoneyManagementFunc( MM, Lots, MMRisk, MaxLoss))
   {
   Mq4Print("We have no money. Free Margin = ", AccountFreeMargin());
   return 0;  
   }
   CurrBar = iTime(Symbol.Code,TimeFrameMq4,0);
   
   
   if (CurrBar != PrevBar)
   {
      if(ScanTradesFunc()>0)
      {
      if (TradeSignalFunc()>0) CloseOrderFunc(2);
      if (TradeSignalFunc()<0) CloseOrderFunc(1);
      }
      
      if(ScanTradesFunc()==0)
      {
      if (TradeSignalFunc()>0) BuyOrdOpenFunc() ;
      if (TradeSignalFunc()<0) SellOrdOpenFunc();
      }
   }
   else
   if(ScanTradesFunc()>0)
   {
   if(BreakEven>0 || TrailStopMode>0) TrailStopFunc();
   }
   PrevBar = CurrBar;
   
   return 0;
return 0;}

//{
		[Parameter("Email from", DefaultValue = "your_email@gmail.com")]
        public string EmailAddressFrom { get; set; }

        [Parameter("Email to", DefaultValue = "your_email@gmail.com")]
        public string EmailAddressTo { get; set; }
//}
[Parameter("Expert_Name", DefaultValue = "BrainExpert_v1")]
public string Expert_Name_parameter { get; set; }
bool _Expert_NameGot;
Mq4String Expert_Name_backfield;
Mq4String Expert_Name { get { if (!_Expert_NameGot) Expert_Name_backfield = Expert_Name_parameter; return Expert_Name_backfield;	} set { Expert_Name_backfield = value; } }

[Parameter("Magic", DefaultValue = 50000)]
public int Magic_parameter { get; set; }
bool _MagicGot;
Mq4Double Magic_backfield;
Mq4Double Magic { get { if (!_MagicGot) Magic_backfield = Magic_parameter; return Magic_backfield;	} set { Magic_backfield = value; } }

[Parameter("Slippage", DefaultValue = 3)]
public int Slippage_parameter { get; set; }
bool _SlippageGot;
Mq4Double Slippage_backfield;
Mq4Double Slippage { get { if (!_SlippageGot) Slippage_backfield = Slippage_parameter; return Slippage_backfield;	} set { Slippage_backfield = value; } }

[Parameter("Main_data", DefaultValue = " TradeMq4 Volume & TradeMq4 Method")]
public string Main_data_parameter { get; set; }
bool _Main_dataGot;
Mq4String Main_data_backfield;
Mq4String Main_data { get { if (!_Main_dataGot) Main_data_backfield = Main_data_parameter; return Main_data_backfield;	} set { Main_data_backfield = value; } }

[Parameter("Lots", DefaultValue = 1)]
public double Lots_parameter { get; set; }
bool _LotsGot;
Mq4Double Lots_backfield;
Mq4Double Lots { get { if (!_LotsGot) Lots_backfield = Lots_parameter; return Lots_backfield;	} set { Lots_backfield = value; } }

[Parameter("TakeProfit", DefaultValue = 0)]
public double TakeProfit_parameter { get; set; }
bool _TakeProfitGot;
Mq4Double TakeProfit_backfield;
Mq4Double TakeProfit { get { if (!_TakeProfitGot) TakeProfit_backfield = TakeProfit_parameter; return TakeProfit_backfield;	} set { TakeProfit_backfield = value; } }

[Parameter("StopLossMode", DefaultValue = 0)]
public int StopLossMode_parameter { get; set; }
bool _StopLossModeGot;
Mq4Double StopLossMode_backfield;
Mq4Double StopLossMode { get { if (!_StopLossModeGot) StopLossMode_backfield = StopLossMode_parameter; return StopLossMode_backfield;	} set { StopLossMode_backfield = value; } }

[Parameter("TrailStopMode", DefaultValue = 0)]
public int TrailStopMode_parameter { get; set; }
bool _TrailStopModeGot;
Mq4Double TrailStopMode_backfield;
Mq4Double TrailStopMode { get { if (!_TrailStopModeGot) TrailStopMode_backfield = TrailStopMode_parameter; return TrailStopMode_backfield;	} set { TrailStopMode_backfield = value; } }

[Parameter("BreakEven", DefaultValue = 0)]
public double BreakEven_parameter { get; set; }
bool _BreakEvenGot;
Mq4Double BreakEven_backfield;
Mq4Double BreakEven { get { if (!_BreakEvenGot) BreakEven_backfield = BreakEven_parameter; return BreakEven_backfield;	} set { BreakEven_backfield = value; } }

[Parameter("SessionStart", DefaultValue = 0)]
public int SessionStart_parameter { get; set; }
bool _SessionStartGot;
Mq4Double SessionStart_backfield;
Mq4Double SessionStart { get { if (!_SessionStartGot) SessionStart_backfield = SessionStart_parameter; return SessionStart_backfield;	} set { SessionStart_backfield = value; } }

[Parameter("SessionEnd", DefaultValue = 24)]
public int SessionEnd_parameter { get; set; }
bool _SessionEndGot;
Mq4Double SessionEnd_backfield;
Mq4Double SessionEnd { get { if (!_SessionEndGot) SessionEnd_backfield = SessionEnd_parameter; return SessionEnd_backfield;	} set { SessionEnd_backfield = value; } }

[Parameter("SignalMail", DefaultValue = false)]
public bool SignalMail_parameter { get; set; }
bool _SignalMailGot;
Mq4Double SignalMail_backfield;
Mq4Double SignalMail { get { if (!_SignalMailGot) SignalMail_backfield = SignalMail_parameter; return SignalMail_backfield;	} set { SignalMail_backfield = value; } }

[Parameter("Inputs", DefaultValue = " BrainTrend parameters ")]
public string Inputs_parameter { get; set; }
bool _InputsGot;
Mq4String Inputs_backfield;
Mq4String Inputs { get { if (!_InputsGot) Inputs_backfield = Inputs_parameter; return Inputs_backfield;	} set { Inputs_backfield = value; } }

[Parameter("TimeFrameMq4", DefaultValue = 60)]
public int TimeFrameMq4_parameter { get; set; }
bool _TimeFrameMq4Got;
Mq4Double TimeFrameMq4_backfield;
Mq4Double TimeFrameMq4 { get { if (!_TimeFrameMq4Got) TimeFrameMq4_backfield = TimeFrameMq4_parameter; return TimeFrameMq4_backfield;	} set { TimeFrameMq4_backfield = value; } }

[Parameter("ConfirmBars", DefaultValue = 3)]
public int ConfirmBars_parameter { get; set; }
bool _ConfirmBarsGot;
Mq4Double ConfirmBars_backfield;
Mq4Double ConfirmBars { get { if (!_ConfirmBarsGot) ConfirmBars_backfield = ConfirmBars_parameter; return ConfirmBars_backfield;	} set { ConfirmBars_backfield = value; } }

[Parameter("MM_inputs", DefaultValue = " MoneyManagement by L.Williams ")]
public string MM_inputs_parameter { get; set; }
bool _MM_inputsGot;
Mq4String MM_inputs_backfield;
Mq4String MM_inputs { get { if (!_MM_inputsGot) MM_inputs_backfield = MM_inputs_parameter; return MM_inputs_backfield;	} set { MM_inputs_backfield = value; } }

[Parameter("MM", DefaultValue = false)]
public bool MM_parameter { get; set; }
bool _MMGot;
Mq4Double MM_backfield;
Mq4Double MM { get { if (!_MMGot) MM_backfield = MM_parameter; return MM_backfield;	} set { MM_backfield = value; } }

[Parameter("MMRisk", DefaultValue = 0.15)]
public double MMRisk_parameter { get; set; }
bool _MMRiskGot;
Mq4Double MMRisk_backfield;
Mq4Double MMRisk { get { if (!_MMRiskGot) MMRisk_backfield = MMRisk_parameter; return MMRisk_backfield;	} set { MMRisk_backfield = value; } }

[Parameter("MaxLoss", DefaultValue = 1000)]
public double MaxLoss_parameter { get; set; }
bool _MaxLossGot;
Mq4Double MaxLoss_backfield;
Mq4Double MaxLoss { get { if (!_MaxLossGot) MaxLoss_backfield = MaxLoss_parameter; return MaxLoss_backfield;	} set { MaxLoss_backfield = value; } }




     
Mq4Double PrevBar;
Mq4Double CurrBar;
Mq4Double TriesNum=5;
Mq4Double BEvent=0;
Mq4Double Lotsi;
Mq4Double OrderBar=0;
        
int indicator_buffers = 0;

                
Mq4Double indicator_width1 = 1;
Mq4Double indicator_width2 = 1;
Mq4Double indicator_width3 = 1;
Mq4Double indicator_width4 = 1;
Mq4Double indicator_width5 = 1;
Mq4Double indicator_width6 = 1;
Mq4Double indicator_width7 = 1;
Mq4Double indicator_width8 = 1;




     

List<Mq4OutputDataSeries> AllBuffers = new List<Mq4OutputDataSeries>();     
public List<DataSeries> AllOutputDataSeries = new List<DataSeries>();
        
	protected override void OnStart()
    {

        
		CommonInitialize();			            
		           

		try
        {
			Mq4Init();
		}
        catch(Exception e)
        {
            
        }  
    }

    protected override void OnTick()
    {        
        var index = MarketSeries.Close.Count - 1;
                

        try
        {
            Mq4Start();
        }
        catch(Exception e)
        {
            
        }    
    }

    private bool IsLastBar
    {
        get { return true; }
    }
private bool IsTradeAllowed()
    {
        return true;
    }

void Sleep(Mq4Double milliseconds)
    {        
        if (!IsBacktesting)
            Thread.Sleep(milliseconds);
    }
int _currentIndex;
CachedStandardIndicators _cachedStandardIndicators;
Mq4ChartObjects _mq4ChartObjects;
Mq4ArrayToDataSeriesConverterFactory _mq4ArrayToDataSeriesConverterFactory;
Mq4MarketDataSeries Open;
Mq4MarketDataSeries High;
Mq4MarketDataSeries Low;
Mq4MarketDataSeries Close;
Mq4MarketDataSeries Median;
Mq4MarketDataSeries Volume;
Mq4TimeSeries Time;

private void CommonInitialize()
{
	Open = new Mq4MarketDataSeries(MarketSeries.Open);
    High = new Mq4MarketDataSeries(MarketSeries.High);
    Low = new Mq4MarketDataSeries(MarketSeries.Low);
    Close = new Mq4MarketDataSeries(MarketSeries.Close);
    Volume = new Mq4MarketDataSeries(MarketSeries.TickVolume);
    Median = new Mq4MarketDataSeries(MarketSeries.Median);
    Time = new Mq4TimeSeries(MarketSeries.OpenTime);

    _cachedStandardIndicators = new CachedStandardIndicators(Indicators);
    _mq4ChartObjects = new Mq4ChartObjects(ChartObjects, MarketSeries.OpenTime);
	_mq4ArrayToDataSeriesConverterFactory = new Mq4ArrayToDataSeriesConverterFactory(() => CreateDataSeries());
}
    private int Bars
    {
        get { return MarketSeries.Close.Count; }
    }
private int Digits
    {
		get
		{
			if (Symbol == null)
				return 0;
			return Symbol.Digits;
		}
    }

Mq4Double Point
	{
		get
		{
			if (Symbol == null)
				return 0.00001;

			return Symbol.TickSize;
		}
	}
private int Period()
	{         
		if (TimeFrame == TimeFrame.Minute)
			return 1;
		if (TimeFrame == TimeFrame.Minute2)
			return 2;
		if (TimeFrame == TimeFrame.Minute3)
			return 3;
		if (TimeFrame == TimeFrame.Minute4)
			return 4;
		if (TimeFrame == TimeFrame.Minute5)
			return 5;
		if (TimeFrame == TimeFrame.Minute10)
			return 10;
		if (TimeFrame == TimeFrame.Minute15)
			return 15;
		if (TimeFrame == TimeFrame.Minute30)
			return 30;
		if (TimeFrame == TimeFrame.Hour)
			return 60;
		if (TimeFrame == TimeFrame.Hour4)
			return 240;
		if (TimeFrame == TimeFrame.Hour12)
			return 720;                    
		if (TimeFrame == TimeFrame.Daily)
			return 1440;
		if (TimeFrame == TimeFrame.Weekly)
			return 10080;
		
		return 43200;
	}

	public TimeFrame PeriodToTimeFrame(int period)
    {
        switch (period) 
		{		
			case 0: 			
				return TimeFrame;
            case 1:
                return TimeFrame.Minute;
            case 2:
                return TimeFrame.Minute2;
            case 3:
                return TimeFrame.Minute3;
            case 4:
                return TimeFrame.Minute4;
            case 5:
                return TimeFrame.Minute5;
            case 10:
                return TimeFrame.Minute10;
            case 15:
                return TimeFrame.Minute15;
            case 30:
                return TimeFrame.Minute30;
            case 60:
                return TimeFrame.Hour;
            case 240:
                return TimeFrame.Hour4;
            case 720:
                return TimeFrame.Hour12;
            case 1440:
                return TimeFrame.Daily;
            case 10080:
                return TimeFrame.Weekly;
            case 43200:
                return TimeFrame.Monthly;
			default:
				throw new NotSupportedException(string.Format("TimeFrame {0} minutes isn't supported by cAlgo", period));
        }
    }



















Mq4String DoubleToStr(double value, int digits)
    {
      return value.ToString("F" + digits);
    }

Mq4Double NormalizeDouble(double value, int digits)
    {
      return Math.Round(value, digits);
    }





int ToMq4ErrorCode(ErrorCode errorCode)
	{
		switch (errorCode)
		{
                case ErrorCode.BadVolume:
                    return ERR_INVALID_TRADE_VOLUME; 
                case ErrorCode.NoMoney:
                    return ERR_NOT_ENOUGH_MONEY;
                case ErrorCode.MarketClosed:
                    return ERR_MARKET_CLOSED;
                case ErrorCode.Disconnected:
                    return ERR_NO_CONNECTION;
                case ErrorCode.Timeout:
                    return ERR_TRADE_TIMEOUT;
                default:
                    return ERR_COMMON_ERROR;
		}
	}



Mq4Double RefreshRates()
{
	RefreshData();
	return true;
}













int Hour()
    {
      return Server.Time.Hour;
    }




int TimeCurrent()
    {
      return Mq4TimeSeries.ToInteger(Server.Time);
    }

int CurTime()
    {
      return TimeCurrent();
    }




int TimeHour(int time)
    {
      return Mq4TimeSeries.ToDateTime(time).Hour;
    }








const string NotSupportedMaShift = "Converter supports only ma_shift = 0";










int iTime(Mq4String symbol, int timeframe, int shift)
    {
		var timeSeries = GetSeries(symbol, timeframe).OpenTime;
		if (shift >= 0 && shift < timeSeries.Count)
			return Mq4TimeSeries.ToInteger(timeSeries.Last(shift));
		return 0;
    }


int iBars(Mq4String symbol, int timeframe)
	{
		return GetSeries(symbol, timeframe).Close.Count;
	}

Mq4Double MarketInfo(Mq4String symbol, int type)
{
	var symbolObject = GetSymbol(symbol);
	switch (type)
	{
		case MODE_LOW:
			return GetSeries(symbol, PERIOD_D1).Low.LastValue;
		case MODE_HIGH:
			return GetSeries(symbol, PERIOD_D1).High.LastValue;
		case MODE_DIGITS:
			return symbolObject.Digits;
		case MODE_TIME:
			return TimeCurrent();
		case MODE_ASK:
			return symbolObject.Ask;
		case MODE_BID:
			return symbolObject.Bid;
		case MODE_SPREAD:
			return symbolObject.Spread / symbolObject.TickSize;
		case MODE_PROFITCALCMODE:
			return 0;
		case MODE_FREEZELEVEL:
			return 0;
		case MODE_TRADEALLOWED:
			return 1;
		case MODE_POINT:
			return symbolObject.TickSize;
		case MODE_TICKSIZE:
			return symbolObject.TickSize;
		case MODE_SWAPTYPE:
			return 0;
		case MODE_MARGINCALCMODE:
			return 0;
        case MODE_STOPLEVEL:
            return symbolObject.TickSize;    
        case MODE_MINLOT:
            return symbolObject.ToLotsVolume(symbolObject.VolumeMin);    
        case MODE_MAXLOT:
            return symbolObject.ToLotsVolume(symbolObject.VolumeMax);  
        case MODE_LOTSTEP:
            return symbolObject.ToLotsVolume(symbolObject.VolumeStep);   
        case MODE_TICKVALUE:
            return symbolObject.TickValue;    
        case MODE_LOTSIZE:
            return symbolObject.ToNotNormalizedUnitsVolume(1);
        case MODE_MARGINREQUIRED:
            return symbolObject.ToNotNormalizedUnitsVolume(1) / Account.Leverage * symbolObject.Ask * symbolObject.TickValue / symbolObject.TickSize;
	}
	return 0;
}

Mq4Double Bid
{
    get 
    {
    if (Symbol == null || double.IsNaN(Symbol.Bid))
        return 0;
    return Symbol.Bid;
    }
}

Mq4Double Ask
{
    get 
    {
    if (Symbol == null || double.IsNaN(Symbol.Ask))
        return 0;
    return Symbol.Ask;
    }
}



void SendMail(Mq4String subject, string text)
{
    Notifications.SendEmail(EmailAddressFrom, EmailAddressTo, subject, text);
    _lastError = ERR_NO_MQLERROR;
}

void Mq4Print(params object[] parameters)
{
	Print(string.Join(string.Empty, parameters));
}



















//{
    //AccessRights = AccessRights.FullAccess
	
	void Alert(params object[] objects)
    {
    	if (IsBacktesting)
    		return; 
    		
        var text = string.Join("", objects.Select(o => o.ToString()));      
        _alertWindowWrapper.Value.ShowAlert(text);
        PlayAlertSoundIfNeeded();
    }

	Lazy<AlertWindowWrapper> _alertWindowWrapper = new Lazy<AlertWindowWrapper>(() => 
	{
		return new AlertWindowWrapper();
	});
    
    private const string _alertSound = @"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";
    void PlayAlertSoundIfNeeded()
    {
        if (!IsLastBar || IsTesting() || (DateTime.Now - _lastPlayedTime) < TimeSpan.FromSeconds(1))
            return;

        _lastPlayedTime = DateTime.Now;
        _mediaPlayer = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.Media.MediaPlayer");

        var soundFilePath = Path.Combine(FolderPaths._2calgoAppDataFolder, "alert_sound.mp3");
        if (!File.Exists(soundFilePath))
        {
            var binaryData = Convert.FromBase64String(_alertSound);
            File.WriteAllBytes(soundFilePath, binaryData);
        }
        var uri = new Uri(soundFilePath);

        ReflectionHelper.InvokeMethod(_mediaPlayer, "Open", uri);
        ReflectionHelper.InvokeMethod(_mediaPlayer, "Play");
    }

    private DateTime _lastPlayedTime;
    private object _mediaPlayer;

	public class AlertWindowWrapper : MarshalByRefObject
    {
        private static Thread _windowThread;
        private static readonly AutoResetEvent LoadedEvent = new AutoResetEvent(false);
        private static readonly object SyncObject = new object();

        private static object _window;
        private static AlertWindowModel _alertWindowModel;

        public void ShowAlert(string message)
        {
            lock (SyncObject)
            {
                if (_window == null)
                    CreateWindow();

                _alertWindowModel.Message = message;
                var items = new List<AlertItem>(_alertWindowModel.Items);
                items.Insert(0, new AlertItem(DateTime.Now, message));
                _alertWindowModel.Items = items;
            }
        }

        private void CreateWindow()
        {
            _windowThread = new Thread(() =>
            {
                try
                {
                    _window = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Window");
                    SubscribeToEvent(_window, "Loaded", "Window_Loaded");
                    SubscribeToEvent(_window, "Closing", "Window_Closing");
                    ReflectionHelper.SetProperty(_window, "ShowInTaskbar", true);
                    ReflectionHelper.SetProperty(_window, "ShowActivated", true);
                    ReflectionHelper.SetProperty(_window, "Width", 525);
                    ReflectionHelper.SetProperty(_window, "Height", 400);
                    ReflectionHelper.SetProperty(_window, "WindowStartupLocation", ReflectionHelper.GetStaticValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.WindowStartupLocation", "CenterScreen"));
                    ReflectionHelper.SetProperty(_window, "WindowStyle", ReflectionHelper.GetStaticValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.WindowStyle", "ToolWindow"));
                    ReflectionHelper.SetProperty(_window, "Title", "Alert");
                    var rootGrid = WpfReflectionHelper.CreateGrid();
                    WpfReflectionHelper.SetMargin(rootGrid, 5);
                    WpfReflectionHelper.AddAutoRowDefinition(rootGrid);
                    WpfReflectionHelper.AddStarRowDefinition(rootGrid);

                    var messageGrid = WpfReflectionHelper.CreateGrid();
                    WpfReflectionHelper.AddAutoColumnDefinition(messageGrid);
                    WpfReflectionHelper.AddStarColumnDefinition(messageGrid);

                    var image = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly,
                                                                "System.Windows.Controls.Image");
                    WpfReflectionHelper.SetMargin(image, 20);
                    var bitmapImage = Base64ToImage("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");
                    ReflectionHelper.SetProperty(image, "Source", bitmapImage);
                    WpfReflectionHelper.AddChild(messageGrid, image);

                    var messageTextBlock =
                        ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly,
                                                        "System.Windows.Controls.TextBlock");

                    WpfReflectionHelper.SetGridColumn(messageTextBlock, 1);
                    ReflectionHelper.SetProperty(messageTextBlock, "HorizontalAlignment", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.HorizontalAlignment", "Left"));
                    ReflectionHelper.SetProperty(messageTextBlock, "TextWrapping", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationCoreAssembly, "System.Windows.TextWrapping", "Wrap"));
                    ReflectionHelper.SetProperty(messageTextBlock, "VerticalAlignment", ReflectionHelper.GetEnumValue(WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.VerticalAlignment", "Center"));
                    ReflectionHelper.SetProperty(messageTextBlock, "FontSize", 18);
                    WpfReflectionHelper.SetBinding(messageTextBlock, "Message", "System.Windows.Controls.TextBlock", "TextProperty");
                    WpfReflectionHelper.AddChild(messageGrid, messageTextBlock);

                    var allAlertsGrid = WpfReflectionHelper.CreateGrid();
                    WpfReflectionHelper.SetGridRow(allAlertsGrid, 1);
                    WpfReflectionHelper.AddStarRowDefinition(allAlertsGrid);
                    WpfReflectionHelper.AddAutoRowDefinition(allAlertsGrid);
                    var dataGrid = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationFrameworkAssembly,
                                                                   "System.Windows.Controls.DataGrid");
                    WpfReflectionHelper.SetBinding(dataGrid, "Items", "System.Windows.Controls.ItemsControl", "ItemsSourceProperty");
                    WpfReflectionHelper.AddChild(allAlertsGrid, dataGrid);
                    var closeButton = ReflectionHelper.CreateInstance(
                        WpfReflectionHelper.PresentationFrameworkAssembly, "System.Windows.Controls.Button");
                    SubscribeToEvent(closeButton, "Click", "ButtonOnClick");
                    WpfReflectionHelper.SetGridRow(closeButton, 1);
                    ReflectionHelper.SetProperty(closeButton, "Width", 100);
                    WpfReflectionHelper.SetMargin(closeButton, 0, 5, 0, 0);
                    ReflectionHelper.SetProperty(closeButton, "Content", "Close");
                    WpfReflectionHelper.AddChild(allAlertsGrid, closeButton);
                    
                    WpfReflectionHelper.AddChild(rootGrid, messageGrid);
                    WpfReflectionHelper.AddChild(rootGrid, allAlertsGrid);
                    
                    ReflectionHelper.SetProperty(_window, "Content", rootGrid);
                    _alertWindowModel = new AlertWindowModel();
                    ReflectionHelper.SetProperty(_window, "DataContext", _alertWindowModel);
                    
                    ReflectionHelper.InvokeMethod(_window, "ShowDialog");
                }
                catch (Exception exception)
                {                    
                }
            }
                )
            {
                IsBackground = false,
                Name = "Alert Window thread"
            };

            _windowThread.TrySetApartmentState(ApartmentState.STA);
            _windowThread.Start();
            LoadedEvent.WaitOne();
        }

        private static object Base64ToImage(string stringValue)
        {

            var binaryData = Convert.FromBase64String(stringValue);

            var bitmapImage = ReflectionHelper.CreateInstance(WpfReflectionHelper.PresentationCoreAssembly,
                                                              "System.Windows.Media.Imaging.BitmapImage");
            
            ReflectionHelper.InvokeMethod(bitmapImage, "BeginInit");
            ReflectionHelper.SetProperty(bitmapImage, "StreamSource", new MemoryStream(binaryData));
            ReflectionHelper.InvokeMethod(bitmapImage, "EndInit");

            return bitmapImage;
        }

        public void ButtonOnClick(object sender, object routedEventArgs)
        {
            ReflectionHelper.InvokeMethod(_window, "Close");
        }

        public void Window_Loaded(object s, object e)
        {
            LoadedEvent.Set();
        }

        public void Window_Closing(object sender, CancelEventArgs e)
        {
            _window = null;
            _alertWindowModel = null;
        }

        private void SubscribeToEvent(object @object, string eventName, string handlerName)
        {
            var eventInfo = @object.GetType().GetEvent(eventName);
            var methodInfo = GetType().GetMethod(handlerName);
            var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
            eventInfo.AddEventHandler(@object, handler);
        }
    }

    public class AlertWindowModel : INotifyPropertyChanged
    {
        private string _message;
        private IEnumerable<AlertItem> _items = new List<AlertItem>();

        public string Message
        {
            get { return _message; }
            set
            {
                if (_message == value)
                    return;

                _message = value;
                OnPropertyChanged("Message");
            }
        }

        public IEnumerable<AlertItem> Items
        {
            get { return _items; }
            set
            {
                if (_items == value)
                    return;

                _items = value;
                OnPropertyChanged("Items");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class AlertItem
    {
        public DateTime Time { get; private set; }
        public string Message { get; private set; }

        public AlertItem(DateTime time, string message)
        {
            Time = time;
            Message = message;
        }
    }

    public static class WpfReflectionHelper
    {
        public static Assembly PresentationFrameworkAssembly = Assembly.Load("PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
        public static Assembly PresentationCoreAssembly = Assembly.Load("PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
        
        public static void SetMargin(object rootGrid, params object[] parameters)
        {
            var thickness = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Thickness", parameters);
            ReflectionHelper.SetProperty(rootGrid, "Margin", thickness);
        }

        public static object CreateGrid()
        {
            return ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.Controls.Grid");
        }

        public static void AddChild(object grid, object child)
        {
            var rootGridChildren = ReflectionHelper.GetPropertyValue(grid, "Children");
            ReflectionHelper.InvokeMethod(rootGridChildren, "Add", child);
        }

        private static readonly object AutoGridLegth = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly,
                                                                                       "System.Windows.GridLength", "Auto");

        public static void AddAutoRowDefinition(object grid)
        {
            var rowDefinition = CreateRowDefinition();
            ReflectionHelper.SetProperty(rowDefinition, "Height", AutoGridLegth);
            AddRowDefinition(grid, rowDefinition);
        }

        public static void AddStarRowDefinition(object grid)
        {
            var rowDefinition = CreateRowDefinition();
            var starUnitType = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly,
                                                               "System.Windows.GridUnitType", "Star");
            var gridLength = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.GridLength", new[]{ 1, starUnitType});
            ReflectionHelper.SetProperty(rowDefinition, "Height", gridLength);
            AddRowDefinition(grid, rowDefinition);
        }

        private static object CreateRowDefinition()
        {
            var rowDefinition = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly,
                                                                "System.Windows.Controls.RowDefinition");
            return rowDefinition;
        }

        public static void AddRowDefinition(object grid, object rowDefinition)
        {
            var rowDefinitions = ReflectionHelper.GetPropertyValue(grid, "RowDefinitions");
            ReflectionHelper.InvokeMethod(rowDefinitions, "Add", rowDefinition);
        }

        public static void AddAutoColumnDefinition(object grid)
        {
            var ColumnDefinition = CreateColumnDefinition();
            ReflectionHelper.SetProperty(ColumnDefinition, "Width", AutoGridLegth);
            AddColumnDefinition(grid, ColumnDefinition);
        }

        public static void AddStarColumnDefinition(object grid)
        {
            var ColumnDefinition = CreateColumnDefinition();
            var starUnitType = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly,
                                                               "System.Windows.GridUnitType", "Star");
            var gridLength = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly, "System.Windows.GridLength", new[]{ 1, starUnitType});
            ReflectionHelper.SetProperty(ColumnDefinition, "Width", gridLength);
            AddColumnDefinition(grid, ColumnDefinition);
        }

        private static object CreateColumnDefinition()
        {
            var ColumnDefinition = ReflectionHelper.CreateInstance(PresentationFrameworkAssembly,
                                                                "System.Windows.Controls.ColumnDefinition");
            return ColumnDefinition;
        }

        public static void AddColumnDefinition(object grid, object ColumnDefinition)
        {
            var ColumnDefinitions = ReflectionHelper.GetPropertyValue(grid, "ColumnDefinitions");
            ReflectionHelper.InvokeMethod(ColumnDefinitions, "Add", ColumnDefinition);
        }

        public static void SetGridColumn(object element, int column)
        {
            var columnProperty = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.Controls.Grid", "ColumnProperty");
            ReflectionHelper.InvokeMethod(element, "SetValue", columnProperty, column);
        }

        public static void SetGridRow(object element, int row)
        {
            var columnProperty = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, "System.Windows.Controls.Grid", "RowProperty");
            ReflectionHelper.InvokeMethod(element, "SetValue", columnProperty, row);
        }

        public static void SetBinding(object element, string path, string propertyTypeName, string propertyName)
        {
            var property = ReflectionHelper.GetStaticValue(PresentationFrameworkAssembly, propertyTypeName, propertyName);
            ReflectionHelper.InvokeMethod(element, "SetBinding", property, path);
        }
    }

    public static class ReflectionHelper
    {
        public static object GetEnumValue(Assembly assembly, string typeName, string value)
        {
            var type = assembly.GetType(typeName);
            return Enum.Parse(type, value);
        }

        public static void InvokeMethod(object instance, string methodName, params object[] parameters)
        {
            instance.GetType().InvokeMember(methodName, BindingFlags.InvokeMethod, null, instance, parameters);
        }

        public static object InvokeStaticMethod(Assembly assembly, string typeName, string methodName, params object[] parameters)
        {
            return assembly.GetType(typeName).InvokeMember(methodName, BindingFlags.InvokeMethod, null, null, parameters);
        }

        public static object GetStaticValue(Assembly assembly, string typeName, string propertyName)
        {
            var type = assembly.GetType(typeName);
            var propertyInfo = type.GetProperty(propertyName);
            if (propertyInfo != null)
                return propertyInfo.GetValue(null, null);

            var fieldInfo = type.GetField(propertyName);
            return fieldInfo.GetValue(null);
        }

        public static void SetProperty(object instance, string propertyName, Assembly assembly, string typeName, params object[] parameters)
        {
            var propertyInfo = instance.GetType().GetProperty(propertyName);
            var propertyValue = CreateInstance(assembly, typeName, parameters);
            propertyInfo.SetValue(instance, propertyValue, null);
        }

        public static void SetProperty(object instance, string propertyName, object value)
        {
            var propertyInfo = instance.GetType().GetProperty(propertyName);
            propertyInfo.SetValue(instance, value, null);
        }

        public static object GetPropertyValue(object instance, string propertyName)
        {
            var propertyInfo = instance.GetType().GetProperty(propertyName);
            return propertyInfo.GetValue(instance, null);
        }

        public static object CreateInstance(Assembly assembly, string typeName)
        {
            return CreateInstance(assembly, typeName, new object[0]);
        }

        public static object CreateInstance(Assembly assembly, string typeName, object[] parameters)
        {
            var pointType = assembly.GetType(typeName);
            var propertyValue = Activator.CreateInstance(pointType, parameters);
            return propertyValue;
        }
    }
	//}

private int _lastError;
Mq4Double GetLastError()
{
	return _lastError;
}

Mq4Double IsTesting()
{
    return IsBacktesting;
}











Mq4String ErrorDescription(int code)
	{
		string error_string;
		switch (code)
			{
				case 0:
				case 1:   return "no error";  
				case 2:   return "common error";                                              
				case 4203: return "unknown object type";                                      
				case 4204: return "no object name";                                           
				case 4205: return "object coordinates error";                                 
				default:   return "unknown error";
			}
		return error_string;
	}

const string GlobalVariablesPath = "Software\\2calgo\\Global Variables\\";






Symbol GetSymbol(string symbolCode)
{
	if (symbolCode == "0" || string.IsNullOrEmpty(symbolCode))
    {
		return Symbol;
    }
	return MarketData.GetSymbol(symbolCode);
}

MarketSeries GetSeries(string symbol, int period)
{
	var timeFrame = PeriodToTimeFrame(period);
	var symbolObject = GetSymbol(symbol);

    if (symbolObject == Symbol && timeFrame == TimeFrame)
        return MarketSeries;

	return MarketData.GetSeries(symbolObject.Code, timeFrame);
}

private DataSeries ToAppliedPrice(string symbol, int timeframe, int constant)
{
	var series = GetSeries(symbol, timeframe);
    switch (constant)
    {
        case PRICE_OPEN:
            return series.Open;
        case PRICE_HIGH:
            return series.High;
        case PRICE_LOW:
            return series.Low;
        case PRICE_CLOSE:
            return series.Close;
        case PRICE_MEDIAN:
            return series.Median;       
        case PRICE_TYPICAL:
            return series.Typical;    
        case PRICE_WEIGHTED:
            return series.WeightedClose;
    }
    throw new NotImplementedException("Converter doesn't support working with this type of AppliedPrice");
}   
const string xArrow = "✖";

public static string GetArrowByCode(int code)
{
    switch (code) 
	{
		case 0:
			return string.Empty;
        case 32:
            return " ";
        case 33:
            return "✏";
        case 34:
            return "✂";
        case 35:
            return "✁";
        case 40:
            return "☎";
        case 41:
            return "✆";
        case 42:
            return "✉";
        case 54:
            return "⌛";
        case 55:
            return "⌨";
        case 62:
            return "✇";
        case 63:
            return "✍";
        case 65:
            return "✌";
        case 69:
            return "☜";
        case 70:
            return "☞";
        case 71:
            return "☝";
        case 72:
            return "☟";
        case 74:
            return "☺";
        case 76:
            return "☹";
        case 78:
            return "☠";
        case 79:
            return "⚐";
        case 81:
            return "✈";
        case 82:
            return "☼";
        case 84:
            return "❄";
        case 86:
            return "✞";
        case 88:
            return "✠";
        case 89:
            return "✡";
        case 90:
            return "☪";
        case 91:
            return "☯";
        case 92:
            return "ॐ";
        case 93:
            return "☸";
        case 94:
            return "♈";
        case 95:
            return "♉";
        case 96:
            return "♊";
        case 97:
            return "♋";
        case 98:
            return "♌";
        case 99:
            return "♍";
        case 100:
            return "♎";
        case 101:
            return "♏";
        case 102:
            return "♐";
        case 103:
            return "♑";
        case 104:
            return "♒";
        case 105:
            return "♓";
        case 106:
            return "&";
        case 107:
            return "&";
        case 108:
            return "●";
        case 109:
            return "❍";
        case 110:
            return "■";
        case 111:
        case 112:
            return "□";
        case 113:
            return "❑";
        case 114:
            return "❒";
        case 115:
        case 116:
            return "⧫";
        case 117:
        case 119:
            return "◆";
        case 118:
            return "❖";
        case 120:
            return "⌧";
        case 121:
            return "⍓";
        case 122:
            return "⌘";
        case 123:
            return "❀";
        case 124:
            return "✿";
        case 125:
            return "❝";
        case 126:
            return "❞";
        case 127:
            return "▯";
        case 128:
            return "⓪";
        case 129:
            return "①";
        case 130:
            return "②";
        case 131:
            return "③";
        case 132:
            return "④";
        case 133:
            return "⑤";
        case 134:
            return "⑥";
        case 135:
            return "⑦";
        case 136:
            return "⑧";
        case 137:
            return "⑨";
        case 138:
            return "⑩";
        case 139:
            return "⓿";
        case 140:
            return "❶";
        case 141:
            return "❷";
        case 142:
            return "❸";
        case 143:
            return "❹";
        case 144:
            return "❺";
        case 145:
            return "❻";
        case 146:
            return "❼";
        case 147:
            return "❽";
        case 148:
            return "❾";
        case 149:
            return "❿";
        case 158:
            return "·";
        case 159:
            return "•";
        case 160:
        case 166:
            return "▪";
        case 161:
            return "○";
        case 162:
        case 164:
            return "⭕";
        case 165:
            return "◎";
        case 167:
            return "✖";
        case 168:
            return "◻";
        case 170:
            return "✦";
        case 171:
            return "★";
        case 172:
            return "✶";
        case 173:
            return "✴";
        case 174:
            return "✹";
        case 175:
            return "✵";
        case 177:
            return "⌖";
        case 178:
            return "⟡";
        case 179:
            return "⌑";
        case 181:
            return "✪";
        case 182:
            return "✰";
        case 195:
        case 197:
        case 215:
        case 219:
        case 223:
        case 231:
            return "◀";
        case 196:
        case 198:
        case 224:
            return "▶";
        case 213:
            return "⌫";
        case 214:
            return "⌦";
        case 216:
            return "➢";
        case 220:
            return "➲";
        case 232:
            return "➔";
        case 233:
        case 199:
        case 200:
        case 217:
        case 221:
        case 225:
            return "◭";
        case 234:
        case 201:
        case 202:
        case 218:
        case 222:
        case 226:
            return "⧨";
        case 239:
            return "⇦";
        case 240:
            return "⇨";
        case 241:
            return "◭";
        case 242:
            return "⧨";
        case 243:
            return "⬄";
        case 244:
            return "⇳";
        case 245:
        case 227:
        case 235:
            return "↖";
        case 246:
        case 228:
        case 236:
            return "↗";
        case 247:
        case 229:
        case 237:
            return "↙";
        case 248:
        case 230:
        case 238:
            return "↘";
        case 249:
            return "▭";
        case 250:
            return "▫";
        case 251:
            return "✗";
        case 252:
            return "✓";
        case 253:
            return "☒";
        case 254:
            return "☑";
        default:
            return xArrow;
    }
}
class Mq4OutputDataSeries : IMq4DoubleArray
{
    public IndicatorDataSeries OutputDataSeries { get; private set; }
    private readonly IndicatorDataSeries _originalValues;
    private int _currentIndex;
    private int _shift;
    private double _emptyValue = EMPTY_VALUE;
    private readonly ChartObjects _chartObjects;
	private readonly int _style;
	private readonly int _bufferIndex;
	private readonly BrainExpert_v1_Robot _indicator;
		
    public Mq4OutputDataSeries(
		BrainExpert_v1_Robot indicator, 
		IndicatorDataSeries outputDataSeries, 
		ChartObjects chartObjects, 
		int style, 
		int bufferIndex,
		Func<IndicatorDataSeries> dataSeriesFactory,
		int lineWidth,
		Colors? color = null)
    {
        OutputDataSeries = outputDataSeries;
        _chartObjects = chartObjects;
		_style = style;
		_bufferIndex = bufferIndex;
		_indicator = indicator;
		Color = color;
		_originalValues = dataSeriesFactory();
		LineWidth = lineWidth;
    }

	public int LineWidth { get; private set; }
	public Colors? Color { get; private set; }

    public int Length
    {
        get 
        {
            return OutputDataSeries.Count;
        }
    }

    public void Resize(int newSize)
    {        
    }

    public void SetCurrentIndex(int index)
    {
        _currentIndex = index;
    }        
        
    public void SetShift(int shift)
    {
        _shift = shift;
    }
        
    public void SetEmptyValue(double emptyValue)
    {
        _emptyValue = emptyValue;
    }

    public Mq4Double this[int index]
    {
        get 
        { 
            var indexToGetFrom = _currentIndex - index + _shift;
            if (indexToGetFrom < 0 || indexToGetFrom > _currentIndex)
                    return 0;
            if (indexToGetFrom >= _originalValues.Count)
                return _emptyValue;

            return _originalValues[indexToGetFrom];
        }
        set 
        { 
            var indexToSet = _currentIndex - index + _shift;  
			if (indexToSet < 0)
				return;

            _originalValues[indexToSet] = value;

            var valueToSet = value;
            if (valueToSet == _emptyValue)
                valueToSet = double.NaN;

            if (indexToSet < 0)
                return;
				
            OutputDataSeries[indexToSet] = valueToSet; 

			switch (_style)
			{
				case DRAW_ARROW:
					var arrowName = GetArrowName(indexToSet);
					if (double.IsNaN(valueToSet))
						_chartObjects.RemoveObject(arrowName);
					else
					{
						var color = Color.HasValue ? Color.Value : Colors.Red;
						_chartObjects.DrawText(arrowName , _indicator.ArrowByIndex[_bufferIndex], indexToSet, valueToSet, VerticalAlignment.Center, HorizontalAlignment.Center, color);
					}
					break;
				case DRAW_HISTOGRAM:
					if (false)
					{
						var anotherLine = _indicator.AllBuffers.FirstOrDefault(b => b.LineWidth == LineWidth && b != this);
						if (anotherLine != null)
						{				
							var name = GetNameOfHistogramLineOnChartWindow(indexToSet);
							Colors color;
							if (this[index] > anotherLine[index])
								color = Color ?? Colors.Green;
							else
								color = anotherLine.Color ?? Colors.Green;
							var lineWidth = LineWidth;
							if (lineWidth != 1 && lineWidth < 5)
								lineWidth = 5;

							_chartObjects.DrawLine(name, indexToSet, this[index], indexToSet, anotherLine[index], color, lineWidth);
						}
					}
					break;
			}
        }
    }
		
	private string GetNameOfHistogramLineOnChartWindow(int index)
    {
		return string.Format("Histogram on chart window {0} {1}", LineWidth, index);
	}

    private string GetArrowName(int index)
    {
        return string.Format("Arrow {0} {1}", GetHashCode(), index);
    }
}
















public Dictionary<int, string> ArrowByIndex = new Dictionary<int, string>{ {0, xArrow},  {1, xArrow},  {2, xArrow},  {3, xArrow},  {4, xArrow},  {5, xArrow},  {6, xArrow},  {7, xArrow}};
    void SetIndexArrow(int index, int code) 
    {
        ArrowByIndex[index] = GetArrowByCode(code);
    }

private int _indicatorCounted;
int FILE_READ = 1;
int FILE_WRITE = 2;
//int FILE_BIN = 8;
int FILE_CSV = 8;

int SEEK_END = 2;

class FileInfo
{
	public int Mode { get; set; }
	public int Handle { get; set; }
	public char Separator { get; set; }
	public string FileName { get; set; }
	public List<string> PendingParts { get; set; }
	public StreamWriter StreamWriter { get; set; }
	public StreamReader StreamReader { get; set; }
}

private Dictionary<int, FileInfo> _openedFiles = new Dictionary<int, FileInfo>();
private int _handleCounter = 1000;







class FolderPaths
{
    public static string _2calgoAppDataFolder
    {
        get
        {
            var result = Path.Combine(SystemAppData, "2calgo");
            if (!Directory.Exists(result))
                Directory.CreateDirectory(result);
            return result;
        }
    }

    public static string _2calgoDesktopFolder
    {
        get
        {
            var result = Path.Combine(Desktop, "2calgo");
            if (!Directory.Exists(result))
                Directory.CreateDirectory(result);
            return result;
        }
    }

    static string SystemAppData
    {
        get 
        { 
            return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); 
        }
    }

    static string Desktop
    {
        get 
        { 
            return Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 
        }
    }
}
const int MODE_TRADES = 0;
const int MODE_HISTORY = 1;
const int SELECT_BY_POS = 0;
const int SELECT_BY_TICKET = 1;

T GetPropertyValue<T>(Func<Position, T> getFromPosition, Func<PendingOrder, T> getFromPendingOrder, Func<HistoricalTrade, T> getFromHistory)
{
	if (_currentOrder == null)
		return default(T);

	return GetPropertyValue<T>(_currentOrder, getFromPosition, getFromPendingOrder, getFromHistory);
}

T GetPropertyValue<T>(object obj, Func<Position, T> getFromPosition, Func<PendingOrder, T> getFromPendingOrder, Func<HistoricalTrade, T> getFromHistory)
{
	if (obj is Position)
		return getFromPosition((Position) obj);
	if (obj is PendingOrder)
		return getFromPendingOrder((PendingOrder) obj);

	return getFromHistory((HistoricalTrade) obj);
} 

private Mq4Double GetTicket(object trade)
{
	return new Mq4Double(GetPropertyValue<int>(trade, _ => _.Id, _ => _.Id, _ => _.ClosingDealId));
}
Mq4Double OrderTicket()
{
	if (_currentOrder == null)
		return 0;

	return GetTicket(_currentOrder);
}
private int GetMagicNumber(string label)
{			
	int magicNumber;
	if (int.TryParse(label, out magicNumber))
		return magicNumber;

	return 0;
}

private int GetMagicNumber(object order)
{	
	var label = GetPropertyValue<string>(order, _ => _.Label, _ => _.Label, _ => _.Label);
	return GetMagicNumber(label);
}
Mq4Double OrderMagicNumber()
{
	if (_currentOrder == null)
		return 0;

	return GetMagicNumber(_currentOrder);
}


Mq4Double OrdersTotal()
{
	return Positions.Count + PendingOrders.Count;
}


object _currentOrder;
bool OrderSelect(int index, int select, int pool = MODE_TRADES)
{
	_currentOrder = null;

	if (pool == MODE_TRADES)
	{
		var allOrders = Positions.OfType<object>()
								.Concat(PendingOrders.OfType<object>())
								.ToArray();

		switch (select)
		{
			case SELECT_BY_POS:	
				if (index < 0 || index >= allOrders.Length)
					return false;

				_currentOrder = allOrders[index];
				return true;
			case SELECT_BY_TICKET:
				_currentOrder = GetOrderByTicket(index);
				return _currentOrder != null;
		}
	}	
	if (pool == MODE_HISTORY)
	{
		switch (select)
		{
			case SELECT_BY_POS:	
				if (index < 0 || index >= History.Count)
					return false;

				_currentOrder = History[index];
				return true;
			case SELECT_BY_TICKET:
				_currentOrder = History.FindLast(index.ToString());
				return _currentOrder != null;
		}
	}

	return false;
}
double GetLots(object order)
{
	var volume = GetPropertyValue<long>(order, _ => _.Volume,  _ => _.Volume, _ => _.Volume);
	var symbolCode = GetPropertyValue<string>(order, _ => _.SymbolCode, _ => _.SymbolCode, _ => _.SymbolCode);
	var symbolObject = MarketData.GetSymbol(symbolCode);
	
	return symbolObject.ToLotsVolume(volume);
}

object GetOrderByTicket(int ticket)
{
	var allOrders = Positions.OfType<object>()
							.Concat(PendingOrders.OfType<object>())
							.ToArray();

	return allOrders.FirstOrDefault(_ => GetTicket(_) == ticket);
}
Mq4Double OrderLots()
{
	if (_currentOrder == null)
		return 0;

	return GetLots(_currentOrder);
}

Mq4Double OrderType()
{
	if (_currentOrder == null)
		return 0;

	var position = _currentOrder as Position;
	if (position != null)
	{
		return position.TradeType == TradeType.Buy ? OP_BUY : OP_SELL;
	}
	var pendingOrder = _currentOrder as PendingOrder;
	if (pendingOrder != null)
	{
		if (pendingOrder.OrderType == PendingOrderType.Limit)
			return pendingOrder.TradeType == TradeType.Buy ? OP_BUYLIMIT : OP_SELLLIMIT;
		return pendingOrder.TradeType == TradeType.Buy ? OP_BUYSTOP : OP_SELLSTOP;
	}

	var historicalTrade = (HistoricalTrade)_currentOrder;

	return historicalTrade.TradeType == TradeType.Buy ? OP_BUY : OP_SELL;
}

Mq4String OrderSymbol()
{
	return GetPropertyValue<string>(_ => _.SymbolCode, _ => _.SymbolCode, _ => _.SymbolCode);
}
double GetOpenPrice(object order)
{
	return GetPropertyValue<double>(order, _ => _.EntryPrice, _ => _.TargetPrice, _ => _.EntryPrice);
}
Mq4Double OrderOpenPrice()
{
	if (_currentOrder == null)
		return 0;

	return GetOpenPrice(_currentOrder);
}

Mq4Double OrderClosePrice()
{
	var historicalTrade = _currentOrder as HistoricalTrade;
	if (historicalTrade != null)
		return historicalTrade.ClosingPrice;

	return 0;
}

private double GetStopLoss(object order)
{
	var nullableValue = GetPropertyValue<double?>(order, _ => _.StopLoss, _ => _.StopLoss, _ => 0);
	return nullableValue ?? 0;
}

private double GetTakeProfit(object order)
{
	var nullableValue = GetPropertyValue<double?>(order, _ => _.TakeProfit, _ => _.TakeProfit, _ => 0);
	return nullableValue ?? 0;
}
Mq4Double OrderStopLoss()
{	
	if (_currentOrder == null)
		return 0;
	return GetStopLoss(_currentOrder);
}

Mq4Double OrderTakeProfit()
{
	if (_currentOrder == null)
		return 0;
	return GetTakeProfit(_currentOrder);
}








Mq4Double AccountFreeMargin()
{
    return Account.FreeMargin;
}














class ParametersKey
{
	private readonly object[] _parameters;
	
	public ParametersKey(params object[] parameters)
	{
		_parameters = parameters;		
	}
	
	public override bool Equals(object obj)
	{
		var other = (ParametersKey)obj;
		for (var i = 0; i < _parameters.Length; i++)
		{
			if (!_parameters[i].Equals(other._parameters[i]))
				return false;
		}
		return true;
	}
	
	public override int GetHashCode()
	{
		unchecked
		{
			var hashCode = 0;
			foreach (var parameter in _parameters)
			{
				hashCode = (hashCode*397) ^ parameter.GetHashCode();
			}
			return hashCode;
		}
	}
}

class Cache<TValue>
{
	private Dictionary<ParametersKey, TValue> _dictionary = new Dictionary<ParametersKey, TValue>();
	
	public bool TryGetValue(out TValue value, params object[] parameters)
	{
		var key = new ParametersKey(parameters);
		return _dictionary.TryGetValue(key, out value);
	}
	
	public void Add(TValue value, params object[] parameters)
	{
		var key = new ParametersKey(parameters);
		_dictionary.Add(key, value);
	}
}


        private static MovingAverageType ToMaType(int constant)
        {
            switch (constant)
            {
                case MODE_SMA:
                    return MovingAverageType.Simple;
                case MODE_EMA:
                    return MovingAverageType.Exponential;
                case MODE_LWMA:
                    return MovingAverageType.Weighted;
                default:
                  throw new ArgumentOutOfRangeException("Not supported moving average type");
            }
        }


















//{
internal class CustomIndicatorParameters
{
    public MarketSeries MarketSeries { get; set; }
    public object[] Parameters { get; set; }

    protected bool Equals(CustomIndicatorParameters other)
    {
        if (Parameters.Length != other.Parameters.Length)
            return false;
        for (var i = 0; i < Parameters.Length; i++)
        {
            if (!Equals(Parameters[i], other.Parameters[i]))
                return false;
        }

        return Equals(MarketSeries, other.MarketSeries);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((CustomIndicatorParameters) obj);
    }

    public override int GetHashCode()
    {
        return (MarketSeries != null ? MarketSeries.GetHashCode() : 0);
    }
}

private List<DataSeries> GetAllOutputDataSeries(object indicatorInstance)
{
	var fieldInfo = indicatorInstance.GetType().GetField("AllOutputDataSeries");
    return (List<DataSeries>)fieldInfo.GetValue(indicatorInstance);
}

private object CastParameter(object parameter)
{
	if (parameter is Mq4Double)
	{
		var mq4Double = (Mq4Double)parameter;
		if (Math.Abs(mq4Double - (int)mq4Double) < Symbol.TickSize)
			return (int)mq4Double;
		return (double)mq4Double;
	}
	if (parameter is string || parameter is Mq4String)
	{
		return (string)parameter;
	}
	return parameter;
}

private object[] CastParameters<T>(object[] parameters)
{
	return parameters
		.Select(CastParameter)
		.ToArray();
}

private static object[] AddEmailParametersIfNeeded<T>(object[] parameters)
{
	var needed = typeof(T)
			.GetProperties()
			.Where(info => info.GetCustomAttributes(typeof (ParameterAttribute), false).Any())
			.Any(p => p.Name == "EmailAddressFrom");

	var result = new List<object>();
	result.AddRange(parameters);
	if (needed)	
	{
		result.Insert(0, string.Empty);
		result.Insert(0, string.Empty);
	}
	return result.ToArray();
}

private readonly Dictionary<CustomIndicatorParameters, List<DataSeries>> _customIndicatorsCache = new Dictionary<CustomIndicatorParameters, List<DataSeries>>();

Mq4Double iCustom<T>(Mq4String symbol, Mq4Double timeframe, Mq4String name, params object[] parameters) where T : Indicator
{
	var marketSeries = GetSeries(symbol, timeframe);
	var indicatorParameters = CastParameters<T>(parameters.Take(parameters.Length - 2).ToArray());	
	indicatorParameters = AddEmailParametersIfNeeded<T>(indicatorParameters);
		
	var customIndicatorParameters = new CustomIndicatorParameters{ MarketSeries = marketSeries, Parameters = indicatorParameters};
	List<DataSeries> outputSeries;
	if (!_customIndicatorsCache.TryGetValue(customIndicatorParameters, out outputSeries))
	{
		var customIndicator = Indicators.GetIndicator<T>(marketSeries, indicatorParameters);	
		outputSeries = GetAllOutputDataSeries(customIndicator);
		_customIndicatorsCache[customIndicatorParameters] = outputSeries;
	}	
		
	var mode = (int)CastParameter(parameters[parameters.Length - 2]);
	var shift = (int)CastParameter(parameters[parameters.Length - 1]);
    return outputSeries[mode].Last(shift);
}
//}








class CachedStandardIndicators
    {
        private readonly IIndicatorsAccessor _indicatorsAccessor;

        public CachedStandardIndicators(IIndicatorsAccessor indicatorsAccessor)
        {
            _indicatorsAccessor = indicatorsAccessor;
        }

}
const bool True = true;
const bool False = false;
const bool TRUE = true;
const bool FALSE = false;                
Mq4Null NULL;
const int EMPTY = -1;
const double EMPTY_VALUE = 2147483647;
public const int WHOLE_ARRAY = 0;

const int MODE_SMA = 0; //Simple moving average
const int MODE_EMA = 1; //Exponential moving average,
const int MODE_SMMA = 2; //Smoothed moving average,
const int MODE_LWMA = 3; //Linear weighted moving average. 

const int PRICE_CLOSE = 0; //Close price. 
const int PRICE_OPEN = 1; //Open price. 
const int PRICE_HIGH = 2; //High price. 
const int PRICE_LOW = 3; //Low price. 
const int PRICE_MEDIAN = 4; //Median price, (high+low)/2. 
const int PRICE_TYPICAL = 5; //Typical price, (high+low+close)/3. 
const int PRICE_WEIGHTED = 6; //Weighted close price, (high+low+close+close)/4. 

const int DRAW_LINE = 0;
const int DRAW_SECTION = 1;
const int DRAW_HISTOGRAM = 2;
const int DRAW_ARROW = 3;
const int DRAW_ZIGZAG = 4;
const int DRAW_NONE = 12;

const int STYLE_SOLID = 0;
const int STYLE_DASH = 1;
const int STYLE_DOT = 2;
const int STYLE_DASHDOT = 3;
const int STYLE_DASHDOTDOT = 4;

const int MODE_OPEN = 0;
const int MODE_LOW = 1;
const int MODE_HIGH = 2;
const int MODE_CLOSE = 3;
const int MODE_VOLUME = 4;
const int MODE_TIME = 5;
const int MODE_BID = 9;
const int MODE_ASK = 10;
const int MODE_POINT = 11;
const int MODE_DIGITS = 12;
const int MODE_SPREAD = 13;
const int MODE_TRADEALLOWED = 22;
const int MODE_PROFITCALCMODE = 27;
const int MODE_MARGINCALCMODE = 28;
const int MODE_SWAPTYPE = 26;
const int MODE_TICKSIZE = 17;	
const int MODE_FREEZELEVEL = 33;
const int MODE_STOPLEVEL = 14;
const int MODE_LOTSIZE = 15;
const int MODE_TICKVALUE = 16;    
/*const int MODE_SWAPLONG = 18;
const int MODE_SWAPSHORT = 19;
const int MODE_STARTING = 20;
const int MODE_EXPIRATION = 21;    
*/
const int MODE_MINLOT = 23;
const int MODE_LOTSTEP = 24;
const int MODE_MAXLOT = 25;
/*const int MODE_MARGININIT = 29;
const int MODE_MARGINMAINTENANCE = 30;
const int MODE_MARGINHEDGED = 31;*/
const int MODE_MARGINREQUIRED = 32;

const int OBJ_VLINE = 0;
    const int OBJ_HLINE = 1;
    const int OBJ_TREND = 2;
    const int OBJ_FIBO = 10;

    /*const int OBJ_TRENDBYANGLE = 3;
    const int OBJ_REGRESSION = 4;
    const int OBJ_CHANNEL = 5;
    const int OBJ_STDDEVCHANNEL = 6;
    const int OBJ_GANNLINE = 7;
    const int OBJ_GANNFAN = 8;
    const int OBJ_GANNGRID = 9;
    const int OBJ_FIBOTIMES = 11;
    const int OBJ_FIBOFAN = 12;
    const int OBJ_FIBOARC = 13;
    const int OBJ_EXPANSION = 14;
    const int OBJ_FIBOCHANNEL = 15;*/
    const int OBJ_RECTANGLE = 16;
    /*const int OBJ_TRIANGLE = 17;
    const int OBJ_ELLIPSE = 18;
    const int OBJ_PITCHFORK = 19;
    const int OBJ_CYCLES = 20;*/
    const int OBJ_TEXT = 21;
    const int OBJ_ARROW = 22;
const int OBJ_LABEL = 23;
    
    const int OBJPROP_TIME1 = 0;
    const int OBJPROP_PRICE1 = 1;
    const int OBJPROP_TIME2 = 2;
    const int OBJPROP_PRICE2 = 3;
    const int OBJPROP_TIME3 = 4;
    const int OBJPROP_PRICE3 = 5;
    const int OBJPROP_COLOR = 6;
    const int OBJPROP_STYLE = 7;
    const int OBJPROP_WIDTH = 8;
    const int OBJPROP_BACK = 9;
    const int OBJPROP_RAY = 10;
    const int OBJPROP_ELLIPSE = 11;
    //const int OBJPROP_SCALE = 12;
    const int OBJPROP_ANGLE = 13;//angle for text rotation
    const int OBJPROP_ARROWCODE = 14;
    const int OBJPROP_TIMEFRAMES = 15;
    //const int OBJPROP_DEVIATION = 16;
    const int OBJPROP_FONTSIZE = 100;
    const int OBJPROP_CORNER = 101;
    const int OBJPROP_XDISTANCE = 102;
    const int OBJPROP_YDISTANCE = 103;
    const int OBJPROP_FIBOLEVELS = 200;
    const int OBJPROP_LEVELCOLOR = 201;
    const int OBJPROP_LEVELSTYLE = 202;
    const int OBJPROP_LEVELWIDTH = 203;
	const int OBJPROP_FIRSTLEVEL = 210;

    const int PERIOD_M1 = 1;
const int PERIOD_M5 = 5;
const int PERIOD_M15 = 15;
const int PERIOD_M30 = 30;
const int PERIOD_H1 = 60;
const int PERIOD_H4 = 240;
const int PERIOD_D1 = 1440;
const int PERIOD_W1 = 10080;
const int PERIOD_MN1 = 43200;

const int TIME_DATE = 1;
const int TIME_MINUTES = 2;
const int TIME_SECONDS = 4;

const int MODE_MAIN = 0;
const int MODE_BASE = 0;
const int MODE_PLUSDI = 1;
const int MODE_MINUSDI = 2;
const int MODE_SIGNAL = 1;

const int MODE_UPPER = 1;
const int MODE_LOWER = 2;

const int MODE_GATORLIPS = 3;
const int MODE_GATORJAW = 1;
const int MODE_GATORTEETH = 2;

const int CLR_NONE = 32768; 

const int White = 16777215;
const int Snow = 16448255;
const int MintCream = 16449525;
const int LavenderBlush = 16118015;
const int AliceBlue = 16775408;
const int Honeydew = 15794160;
const int Ivory = 15794175;
const int Seashell = 15660543;
const int WhiteSmoke = 16119285;
const int OldLace = 15136253;
const int MistyRose = 14804223;
const int Lavender = 16443110;
const int Linen = 15134970;
const int LightCyan = 16777184;
const int LightYellow = 14745599;
const int Cornsilk = 14481663;
const int PapayaWhip = 14020607;
const int AntiqueWhite = 14150650;
const int Beige = 14480885;
const int LemonChiffon = 13499135;
const int BlanchedAlmond = 13495295;
const int LightGoldenrod = 13826810;
const int Bisque = 12903679;
const int Pink = 13353215;
const int PeachPuff = 12180223;
const int Gainsboro = 14474460;
const int LightPink = 12695295;
const int Moccasin = 11920639;
const int NavajoWhite = 11394815;
const int Wheat = 11788021;
const int LightGray = 13882323;
const int PaleTurquoise = 15658671;
const int PaleGoldenrod = 11200750;
const int PowderBlue = 15130800;
const int Thistle = 14204888;
const int PaleGreen = 10025880;
const int LightBlue = 15128749;
const int LightSteelBlue = 14599344;
const int LightSkyBlue = 16436871;
const int Silver = 12632256;
const int Aquamarine = 13959039;
const int LightGreen = 9498256;
const int Khaki = 9234160;
const int Plum = 14524637;
const int LightSalmon = 8036607;
const int SkyBlue = 15453831;
const int LightCoral = 8421616;
const int Violet = 15631086;
const int Salmon = 7504122;
const int HotPink = 11823615;
const int BurlyWood = 8894686;
const int DarkSalmon = 8034025;
const int Tan = 9221330;
const int MediumSlateBlue = 15624315;
const int SandyBrown = 6333684;
const int DarkGray = 11119017;
const int CornflowerBlue = 15570276;
const int Coral = 5275647;
const int PaleVioletRed = 9662683;
const int MediumPurple = 14381203;
const int Orchid = 14053594;
const int RosyBrown = 9408444;
const int Tomato = 4678655;
const int DarkSeaGreen = 9419919;
const int Cyan = 16776960;
const int MediumAquamarine = 11193702;
const int GreenYellow = 3145645;
const int MediumOrchid = 13850042;
const int IndianRed = 6053069;
const int DarkKhaki = 7059389;
const int SlateBlue = 13458026;
const int RoyalBlue = 14772545;
const int Turquoise = 13688896;
const int DodgerBlue = 16748574;
const int MediumTurquoise = 13422920;
const int DeepPink = 9639167;
const int LightSlateGray = 10061943;
const int BlueViolet = 14822282;
const int Peru = 4163021;
const int SlateGray = 9470064;
const int Gray = 8421504;
const int Red = 255;
const int Magenta = 16711935;
const int Blue = 16711680;
const int DeepSkyBlue = 16760576;
const int Aqua = 16776960;
const int SpringGreen = 8388352;
const int Lime = 65280;
const int Chartreuse = 65407;
const int Yellow = 65535;
const int Gold = 55295;
const int Orange = 42495;
const int DarkOrange = 36095;
const int OrangeRed = 17919;
const int LimeGreen = 3329330;
const int YellowGreen = 3329434;
const int DarkOrchid = 13382297;
const int CadetBlue = 10526303;
const int LawnGreen = 64636;
const int MediumSpringGreen = 10156544;
const int Goldenrod = 2139610;
const int SteelBlue = 11829830;
const int Crimson = 3937500;
const int Chocolate = 1993170;
const int MediumSeaGreen = 7451452;
const int MediumVioletRed = 8721863;
const int FireBrick = 2237106;
const int DarkViolet = 13828244;
const int LightSeaGreen = 11186720;
const int DimGray = 6908265;
const int DarkTurquoise = 13749760;
const int Brown = 2763429;
const int MediumBlue = 13434880;
const int Sienna = 2970272;
const int DarkSlateBlue = 9125192;
const int DarkGoldenrod = 755384;
const int SeaGreen = 5737262;
const int OliveDrab = 2330219;
const int ForestGreen = 2263842;
const int SaddleBrown = 1262987;
const int DarkOliveGreen = 3107669;
const int DarkBlue = 9109504;
const int MidnightBlue = 7346457;
const int Indigo = 8519755;
const int Maroon = 128;
const int Purple = 8388736;
const int Navy = 8388608;
const int Teal = 8421376;
const int Green = 32768;
const int Olive = 32896;
const int DarkSlateGray = 5197615;
const int DarkGreen = 25600;
const int Fuchsia = 16711935;
const int Black = 0;  

const int SYMBOL_LEFTPRICE = 5;
const int SYMBOL_RIGHTPRICE = 6;

const int SYMBOL_ARROWUP = 241;
const int SYMBOL_ARROWDOWN = 242;
const int SYMBOL_STOPSIGN = 251;
/*
const int SYMBOL_THUMBSUP = 67;
const int SYMBOL_THUMBSDOWN = 68;	
const int SYMBOL_CHECKSIGN = 25;
*/

public const int MODE_ASCEND = 1;
public const int MODE_DESCEND = 2;

const int MODE_TENKANSEN = 1;
const int MODE_KIJUNSEN = 2;
const int MODE_SENKOUSPANA = 3;
const int MODE_SENKOUSPANB = 4;
const int MODE_CHINKOUSPAN = 5;
	const int OP_BUY = 0;
	const int OP_SELL = 1;
	const int OP_BUYLIMIT = 2;
	const int OP_SELLLIMIT = 3;
	const int OP_BUYSTOP = 4;
	const int OP_SELLSTOP = 5;
const int OBJ_PERIOD_M1 = 0x0001;
const int OBJ_PERIOD_M5 = 0x0002;
const int OBJ_PERIOD_M15 = 0x0004;
const int OBJ_PERIOD_M30 = 0x0008;
const int OBJ_PERIOD_H1 = 0x0010;
const int OBJ_PERIOD_H4 = 0x0020;
const int OBJ_PERIOD_D1 = 0x0040;
const int OBJ_PERIOD_W1 = 0x0080;
const int OBJ_PERIOD_MN1 = 0x0100;
const int OBJ_ALL_PERIODS = 0x01FF;

const int REASON_REMOVE = 1;
const int REASON_RECOMPILE = 2;
const int REASON_CHARTCHANGE = 3;
const int REASON_CHARTCLOSE = 4;
const int REASON_PARAMETERS = 5;
const int REASON_ACCOUNT = 6;
const int ERR_NO_ERROR = 0;
const int ERR_NO_RESULT = 1;
const int ERR_COMMON_ERROR = 2;
const int ERR_INVALID_TRADE_PARAMETERS = 3;
const int ERR_SERVER_BUSY = 4;
const int ERR_OLD_VERSION = 5;
const int ERR_NO_CONNECTION = 6;
const int ERR_NOT_ENOUGH_RIGHTS = 7;
const int ERR_TOO_FREQUENT_REQUESTS = 8;
const int ERR_MALFUNCTIONAL_TRADE = 9;
const int ERR_ACCOUNT_DISABLED = 64;
const int ERR_INVALID_ACCOUNT = 65;
const int ERR_TRADE_TIMEOUT = 128;
const int ERR_INVALID_PRICE = 129;
const int ERR_INVALID_STOPS = 130;
const int ERR_INVALID_TRADE_VOLUME = 131;
const int ERR_MARKET_CLOSED = 132;
const int ERR_TRADE_DISABLED = 133;
const int ERR_NOT_ENOUGH_MONEY = 134;
const int ERR_PRICE_CHANGED = 135;
const int ERR_OFF_QUOTES = 136;
const int ERR_BROKER_BUSY = 137;
const int ERR_REQUOTE = 138;
const int ERR_ORDER_LOCKED = 139;
const int ERR_LONG_POSITIONS_ONLY_ALLOWED = 140;
const int ERR_TOO_MANY_REQUESTS = 141;
const int ERR_TRADE_MODIFY_DENIED = 145;
const int ERR_TRADE_CONTEXT_BUSY = 146;
const int ERR_TRADE_EXPIRATION_DENIED = 147;
const int ERR_TRADE_TOO_MANY_ORDERS = 148;
const int ERR_TRADE_HEDGE_PROHIBITED = 149;
const int ERR_TRADE_PROHIBITED_BY_FIFO = 150;
const int ERR_NO_MQLERROR = 4000;
const int ERR_WRONG_FUNCTION_POINTER = 4001;
const int ERR_ARRAY_INDEX_OUT_OF_RANGE = 4002;
const int ERR_NO_MEMORY_FOR_CALL_STACK = 4003;
const int ERR_RECURSIVE_STACK_OVERFLOW = 4004;
const int ERR_NOT_ENOUGH_STACK_FOR_PARAM = 4005;
const int ERR_NO_MEMORY_FOR_PARAM_STRING = 4006;
const int ERR_NO_MEMORY_FOR_TEMP_STRING = 4007;
const int ERR_NOT_INITIALIZED_STRING = 4008;
const int ERR_NOT_INITIALIZED_ARRAYSTRING = 4009;
const int ERR_NO_MEMORY_FOR_ARRAYSTRING = 4010;
const int ERR_TOO_LONG_STRING = 4011;
const int ERR_REMAINDER_FROM_ZERO_DIVIDE = 4012;
const int ERR_ZERO_DIVIDE = 4013;
const int ERR_UNKNOWN_COMMAND = 4014;
const int ERR_WRONG_JUMP = 4015;
const int ERR_NOT_INITIALIZED_ARRAY = 4016;
const int ERR_DLL_CALLS_NOT_ALLOWED = 4017;
const int ERR_CANNOT_LOAD_LIBRARY = 4018;
const int ERR_CANNOT_CALL_FUNCTION = 4019;
const int ERR_EXTERNAL_CALLS_NOT_ALLOWED = 4020;
const int ERR_NO_MEMORY_FOR_RETURNED_STR = 4021;
const int ERR_SYSTEM_BUSY = 4022;
const int ERR_INVALID_FUNCTION_PARAMSCNT = 4050;
const int ERR_INVALID_FUNCTION_PARAMVALUE = 4051;
const int ERR_STRING_FUNCTION_INTERNAL = 4052;
const int ERR_SOME_ARRAY_ERROR = 4053;
const int ERR_INCORRECT_SERIESARRAY_USING = 4054;
const int ERR_CUSTOM_INDICATOR_ERROR = 4055;
const int ERR_INCOMPATIBLE_ARRAYS = 4056;
const int ERR_GLOBAL_VARIABLES_PROCESSING = 4057;
const int ERR_GLOBAL_VARIABLE_NOT_FOUND = 4058;
const int ERR_FUNC_NOT_ALLOWED_IN_TESTING = 4059;
const int ERR_FUNCTION_NOT_CONFIRMED = 4060;
const int ERR_SEND_MAIL_ERROR = 4061;
const int ERR_STRING_PARAMETER_EXPECTED = 4062;
const int ERR_INTEGER_PARAMETER_EXPECTED = 4063;
const int ERR_DOUBLE_PARAMETER_EXPECTED = 4064;
const int ERR_ARRAY_AS_PARAMETER_EXPECTED = 4065;
const int ERR_HISTORY_WILL_UPDATED = 4066;
const int ERR_TRADE_ERROR = 4067;
const int ERR_END_OF_FILE = 4099;
const int ERR_SOME_FILE_ERROR = 4100;
const int ERR_WRONG_FILE_NAME = 4101;
const int ERR_TOO_MANY_OPENED_FILES = 4102;
const int ERR_CANNOT_OPEN_FILE = 4103;
const int ERR_INCOMPATIBLE_FILEACCESS = 4104;
const int ERR_NO_ORDER_SELECTED = 4105;
const int ERR_UNKNOWN_SYMBOL = 4106;
const int ERR_INVALID_PRICE_PARAM = 4107;
const int ERR_INVALID_TICKET = 4108;
const int ERR_TRADE_NOT_ALLOWED = 4109;
const int ERR_LONGS_NOT_ALLOWED = 4110;
const int ERR_SHORTS_NOT_ALLOWED = 4111;
const int ERR_OBJECT_ALREADY_EXISTS = 4200;
const int ERR_UNKNOWN_OBJECT_PROPERTY = 4201;
const int ERR_OBJECT_DOES_NOT_EXIST = 4202;
const int ERR_UNKNOWN_OBJECT_TYPE = 4203;
const int ERR_NO_OBJECT_NAME = 4204;
const int ERR_OBJECT_COORDINATES_ERROR = 4205;
const int ERR_NO_SPECIFIED_SUBWINDOW = 4206;
const int ERR_SOME_OBJECT_ERROR = 4207;
class Mq4ChartObjects
{
	private readonly ChartObjects _algoChartObjects;
	private readonly TimeSeries _timeSeries;

	private readonly Dictionary<string, Mq4Object> _mq4ObjectByName = new Dictionary<string, Mq4Object>();
	private readonly List<string> _mq4ObjectNameByIndex = new List<string>();

	public Mq4ChartObjects(ChartObjects chartObjects, TimeSeries timeSeries)
	{
		_algoChartObjects = chartObjects;
		_timeSeries = timeSeries;
	}

public void Set(string name, int index, Mq4Double value)
	{
		if (!_mq4ObjectByName.ContainsKey(name))
			return;
		_mq4ObjectByName[name].Set(index, value);
		_mq4ObjectByName[name].Draw();
	}
public void SetText(string name, string text, int font_size, string font, int color)
	{
		if (!_mq4ObjectByName.ContainsKey(name))
			return;

Set(name, OBJPROP_COLOR, color);
	}







private T GetObject<T>(string name) where T : Mq4Object
	{
		Mq4Object mq4Object;
		if (!_mq4ObjectByName.TryGetValue(name, out mq4Object))
			return null;
		return mq4Object as T;
	}

}

abstract class Mq4Object : IDisposable
{   
	private readonly ChartObjects _chartObjects;

    protected Mq4Object(string name, int type, ChartObjects chartObjects)
    {
        Name = name;
        Type = type;
		_chartObjects = chartObjects;
    }
      
    public int Type { get; private set; }

    public string Name { get; private set; }

    protected DateTime Time1
    {
        get
        {
            int seconds = Get(OBJPROP_TIME1);
            return Mq4TimeSeries.ToDateTime(seconds);
        }
    }
            
    protected double Price1
    {
        get
        {
            return Get(OBJPROP_PRICE1);
        }
    }

    protected DateTime Time2
    {
        get
        {
            int seconds = Get(OBJPROP_TIME2);
            return Mq4TimeSeries.ToDateTime(seconds);
        }
    }
            
    protected double Price2
    {
        get
        {
            return Get(OBJPROP_PRICE2);
        }
    }

    protected Colors Color
    {
        get
        {                    
			int intColor = Get(OBJPROP_COLOR);
			if (intColor != CLR_NONE)
				return Mq4Colors.GetColorByInteger(intColor);

			return Colors.Yellow;      
        }
    }

    protected int Width
    {
        get
        {
            return Get(OBJPROP_WIDTH);
        }
    }

    protected int Style
    {
        get
        {
			return Get(OBJPROP_STYLE);
        }
    }

    public abstract void Draw();

    private readonly Dictionary<int, Mq4Double> _properties = new Dictionary<int, Mq4Double>
        {
			{OBJPROP_WIDTH, new Mq4Double(1)},
			{OBJPROP_COLOR, new Mq4Double(CLR_NONE)},
            {OBJPROP_RAY, new Mq4Double(1)},

			{OBJPROP_LEVELCOLOR, new Mq4Double(CLR_NONE)},
			{OBJPROP_LEVELSTYLE, new Mq4Double(0)},
            {OBJPROP_LEVELWIDTH, new Mq4Double(1)},
            {OBJPROP_FIBOLEVELS, new Mq4Double(9)},
			{OBJPROP_FIRSTLEVEL + 0, new Mq4Double(0)},
			{OBJPROP_FIRSTLEVEL + 1, new Mq4Double(0.236)},
			{OBJPROP_FIRSTLEVEL + 2, new Mq4Double(0.382)},
			{OBJPROP_FIRSTLEVEL + 3, new Mq4Double(0.5)},
			{OBJPROP_FIRSTLEVEL + 4, new Mq4Double(0.618)},
			{OBJPROP_FIRSTLEVEL + 5, new Mq4Double(1)},
			{OBJPROP_FIRSTLEVEL + 6, new Mq4Double(1.618)},
			{OBJPROP_FIRSTLEVEL + 7, new Mq4Double(2.618)},
			{OBJPROP_FIRSTLEVEL + 8, new Mq4Double(4.236)},
        };

    public virtual void Set(int index, Mq4Double value)
    {
        _properties[index] = value;
    }

    public Mq4Double Get(int index)
    {
        return _properties.ContainsKey(index) ? _properties[index] : new Mq4Double(0);
    }

	private readonly List<string> _addedAlgoChartObjects = new List<string>();

	protected void DrawText(string objectName, string text, int index, double yValue, VerticalAlignment verticalAlignment = VerticalAlignment.Center, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center, Colors? color = null)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawText(objectName, text, index, yValue, verticalAlignment, horizontalAlignment, color);
	}

	protected void DrawText(string objectName, string text, StaticPosition position, Colors? color = null)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawText(objectName, text, position, color);
	}

	protected void DrawLine(string objectName, int index1, double y1, int index2, double y2, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawLine(objectName, index1, y1, index2, y2, color, thickness, style);
	}

	protected void DrawLine(string objectName, DateTime date1, double y1, DateTime date2, double y2, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawLine(objectName, date1, y1, date2, y2, color, thickness, style);
	}

	protected void DrawVerticalLine(string objectName, DateTime date, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawVerticalLine(objectName, date, color, thickness, style);
	}

	protected void DrawVerticalLine(string objectName, int index, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawVerticalLine(objectName, index, color, thickness, style);
	}

	protected void DrawHorizontalLine(string objectName, double y, Colors color, double thickness = 1.0, cAlgo.API.LineStyle style = cAlgo.API.LineStyle.Solid)
	{
		_addedAlgoChartObjects.Add(objectName);
		_chartObjects.DrawHorizontalLine(objectName, y, color, thickness, style);
	}

	public void Dispose()
	{
		foreach (var name in _addedAlgoChartObjects)
		{
			_chartObjects.RemoveObject(name);
		}
	}
}





class Mq4Arrow : Mq4Object
    {
        private readonly TimeSeries _timeSeries;
		private int _index;

        public Mq4Arrow(string name, int type, ChartObjects chartObjects, TimeSeries timeSeries) 
            : base(name, type, chartObjects)
        {
            _timeSeries = timeSeries;
        }
            
		public override void Set(int index, Mq4Double value)
		{
			base.Set(index, value);
			switch (index)        
			{ 
				case OBJPROP_TIME1:           					
					_index = _timeSeries.GetIndexByTime(Time1);
					break;
			}
		}

		private int ArrowCode
		{
			get
			{
				return Get(OBJPROP_ARROWCODE);
			}
		}

        public override void Draw()
        {
			string arrowString;
			HorizontalAlignment horizontalAlignment;
			switch (ArrowCode)
			{
				case SYMBOL_RIGHTPRICE:
					horizontalAlignment = HorizontalAlignment.Right;
					arrowString = Price1.ToString();
					break;
				case SYMBOL_LEFTPRICE:
					horizontalAlignment = HorizontalAlignment.Left;
					arrowString = Price1.ToString();
					break;
				default:
					arrowString = BrainExpert_v1_Robot.GetArrowByCode(ArrowCode);
					horizontalAlignment = HorizontalAlignment.Center;
					break;
			}				
			DrawText(Name, arrowString, _index, Price1, VerticalAlignment.Center, horizontalAlignment, Color);
        }
    }















Mq4Double OrderSend(Mq4String symbol, int cmd, Mq4Double volume, Mq4Double price, Mq4Double slippagePoints, Mq4Double stoploss, 
    Mq4Double takeprofit, Mq4String comment = null, Mq4Double? magic = null, int expiration = 0, int arrow_color = CLR_NONE)
{
    _lastError = ERR_NO_ERROR;
    if (magic == null)
        magic = 0;    
    var label = magic.Value.ToString();

    var symbolObject = GetSymbol(symbol);
    var volumeInUnits = symbolObject.ToUnitsVolume(volume);

    switch (cmd)
    {
        case OP_BUY:
        case OP_SELL:
            {
                var tradeType = cmd == OP_BUY ? TradeType.Buy : TradeType.Sell;
                var slippageInPrice = symbolObject.TickSize * slippagePoints;
                var slippageInPips = (int)Math.Round((double)slippageInPrice / symbolObject.PipSize);
                double? stopLossPips = null;
                if (stoploss != 0)
                    stopLossPips = tradeType == TradeType.Buy ? (symbolObject.Ask - stoploss) / symbolObject.PipSize : (stoploss - symbolObject.Bid) / symbolObject.PipSize;
                double? takeProfitPips = null;
                if (takeprofit != 0)
                    takeProfitPips = tradeType == TradeType.Buy ? (takeprofit - symbolObject.Ask) / symbolObject.PipSize : (symbolObject.Bid - takeprofit) / symbolObject.PipSize;

                var marketOrderResult = ExecuteMarketOrder(tradeType, symbolObject, volumeInUnits, label, stopLossPips, takeProfitPips, slippageInPips, comment);
                
				if (marketOrderResult.IsSuccessful)
					return GetTicket(marketOrderResult.Position);
				else
				{
					_lastError = ToMq4ErrorCode(marketOrderResult.Error.Value);
					return -1;
				}
            }
        case OP_BUYLIMIT:
        case OP_SELLLIMIT:
        case OP_BUYSTOP:
        case OP_SELLSTOP:
            {
                var tradeType = cmd == OP_BUYLIMIT || cmd == OP_BUYSTOP ? TradeType.Buy : TradeType.Sell;

                double? stopLossPips = null;
                if (stoploss != 0)
                    stopLossPips = tradeType == TradeType.Buy ? (price - stoploss) / symbolObject.PipSize : (stoploss - price) / symbolObject.PipSize;
                double? takeProfitPips = null;
                if (takeprofit != 0)
                    takeProfitPips = tradeType == TradeType.Buy ? (takeprofit - price) / symbolObject.PipSize : (price - takeprofit) / symbolObject.PipSize;

				TradeResult placeOrderResult;
                if (cmd == OP_BUYLIMIT || cmd == OP_SELLLIMIT)
                    placeOrderResult = PlaceLimitOrder(tradeType, symbolObject, volumeInUnits, price, label, stopLossPips, takeProfitPips, expiration.ToNullableDateTime(), comment);
                else
                    placeOrderResult = PlaceStopOrder(tradeType, symbolObject, volumeInUnits, price, label, stopLossPips, takeProfitPips, expiration.ToNullableDateTime(), comment);

				if (placeOrderResult.IsSuccessful)
					return GetTicket(placeOrderResult.PendingOrder);
				else
				{
					_lastError = ToMq4ErrorCode(placeOrderResult.Error.Value);
					return -1;
				}
            }
        default:
            throw new Exception("Not supported by converter");            
    }

    return 0;
}
Mq4Double OrderClose(int ticket, double lots, double price, int slippagePoints, int Color = CLR_NONE)
{
    _lastError = ERR_NO_ERROR;

    var position = GetOrderByTicket(ticket) as Position;
    if (position == null)
    {
        _lastError = ERR_INVALID_TICKET;
        return false;
    }
    var symbolObject = MarketData.GetSymbol(position.SymbolCode);
    
    var volumeInUnits = symbolObject.ToUnitsVolume(lots);    
    ClosePosition(position, volumeInUnits);    

	if (!LastResult.IsSuccessful)
		_lastError = ToMq4ErrorCode(LastResult.Error.Value);

    return LastResult.IsSuccessful;
}

Mq4Double OrderModify(int ticket, double price, double stoploss, double takeprofit, int expiration, int arrow_color=CLR_NONE)
{
    _lastError = ERR_NO_ERROR;

    var order = GetOrderByTicket(ticket);
    if (GetTakeProfit(order) == takeprofit && GetStopLoss(order) == stoploss
        && GetOpenPrice(order) == price)
    {
        _lastError = ERR_NO_RESULT;
        return false;
    }

    var position = order as Position;
    if (position != null)
    {    
        ModifyPosition(position, stoploss.ToNullableDouble(), takeprofit.ToNullableDouble());
		if (!LastResult.IsSuccessful)
			_lastError = ToMq4ErrorCode(LastResult.Error.Value);

        return LastResult.IsSuccessful;
    }
    
    var pendingOrder = (PendingOrder)order;
    var expirationTime = expiration.ToNullableDateTime();
    ModifyPendingOrder(pendingOrder, price, stoploss.ToNullableDouble(), takeprofit.ToNullableDouble(), expirationTime);

	if (!LastResult.IsSuccessful)
		_lastError = ToMq4ErrorCode(LastResult.Error.Value);

    return LastResult.IsSuccessful;
}


}

	//Custom Indicators Place Holder

class Mq4DoubleComparer : IComparer<Mq4Double>
{
    public int Compare(Mq4Double x, Mq4Double y)
    {
        return x.CompareTo(y);
    }
}
class Mq4String
{
	private readonly string _value;
	
	public Mq4String(string value)
	{
		_value = value;
	}

	public static implicit operator Mq4String(string value)
	{
		return new Mq4String(value);
	}
	
	public static implicit operator Mq4String(int value)
	{
		return new Mq4String(value.ToString());
	}
		
	public static implicit operator Mq4String(Mq4Null mq4Null)
	{
		return new Mq4String(null);
	}
	
	public static implicit operator string(Mq4String mq4String)
	{
		if ((object)mq4String == null)
                return null;

		return mq4String._value;
	}
			
	public static implicit operator Mq4String(Mq4Double mq4Double)
	{
		return new Mq4String(mq4Double.ToString());
	}

	public static bool operator <(Mq4String x, Mq4String y)
	{
		return string.Compare(x._value, y._value) == -1;
	}
		
	public static bool operator >(Mq4String x, Mq4String y)
	{
		return string.Compare(x._value, y._value) == 1;
	}
	
	public static bool operator <(Mq4String x, string y)
	{
		return string.Compare(x._value, y) == -1;
	}
		
	public static bool operator >(Mq4String x, string y)
	{
		return string.Compare(x._value, y) == 1;
	}
	public static bool operator <=(Mq4String x, Mq4String y)
	{
		return string.Compare(x._value, y._value) <= 0;
	}
		
	public static bool operator >=(Mq4String x, Mq4String y)
	{
		return string.Compare(x._value, y._value) >= 0;
	}
	
	public static bool operator <=(Mq4String x, string y)
	{
		return string.Compare(x._value, y) <= 0;
	}
		
	public static bool operator >=(Mq4String x, string y)
	{
		return string.Compare(x._value, y) >= 0;
	}
			
	public static bool operator ==(Mq4String x, Mq4String y)
	{
		return string.Compare(x._value, y._value) == 0;
	}
			
	public static bool operator !=(Mq4String x, Mq4String y)
	{
		return string.Compare(x._value, y._value) != 0;
	}
				
	public static bool operator ==(Mq4String x, string y)
	{
		return string.Compare(x._value, y) == 0;
	}
			
	public static bool operator !=(Mq4String x, string y)
	{
		return string.Compare(x._value, y) != 0;
	}
		
	public override string ToString()
	{
		if ((object)this == null)
            return string.Empty;

		return _value.ToString();
	}
	
	public static readonly Mq4String Empty = new Mq4String(string.Empty);

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Mq4String) obj);
    }

	protected bool Equals(Mq4String other)
    {
        return this == other;
    }

    public override int GetHashCode()
    {
        return (_value != null ? _value.GetHashCode() : 0);
    }
}
struct Mq4Char
{
	char _char;
			
	public Mq4Char(byte code)
	{
		_char = Encoding.Unicode.GetString(new byte[]{code, 0})[0];	
	}

	public Mq4Char(char @char)
	{
		_char = @char;
	}

	public static implicit operator char(Mq4Char mq4Char)
	{
		return mq4Char._char;
	}
	
	public static implicit operator Mq4Char(int code)
	{
		return new Mq4Char((byte)code);
	}
	
	public static implicit operator Mq4Char(string str)
	{
		if (string.IsNullOrEmpty(str) || str.Length == 0)
			return new Mq4Char(' ');
		return new Mq4Char(str[0]);
	}
}
struct Mq4Null
{
    public static implicit operator string(Mq4Null mq4Null)
    {
        return (string)null;
    }

    public static implicit operator int(Mq4Null mq4Null)
    {
        return 0;
    }
    
    public static implicit operator double(Mq4Null mq4Null)
    {
        return 0;
    }
}
static class Comparers
{
    public static IComparer<T> GetComparer<T>()
    {
        if (typeof(T) == typeof(Mq4Double))
            return (IComparer<T>)new Mq4DoubleComparer();

        return Comparer<T>.Default;
    }
}
	static class DataSeriesExtensions
	{
		public static int InvertIndex(this DataSeries dataSeries, int index)
		{
			return dataSeries.Count - 1 - index;
		}

		public static Mq4Double Last(this DataSeries dataSeries, int shift, DataSeries sourceDataSeries)
		{
			return dataSeries[sourceDataSeries.Count - 1 - shift];
		}
	}
	static class TimeSeriesExtensions
	{
		public static DateTime Last(this TimeSeries timeSeries, int index)
		{
			return timeSeries[timeSeries.InvertIndex(index)];
		}

		public static int InvertIndex(this TimeSeries timeSeries, int index)
		{
			return timeSeries.Count - 1 - index;
		}

		public static int GetIndexByTime(this TimeSeries timeSeries, DateTime time)
		{
			var index = timeSeries.Count - 1;
			for (var i = timeSeries.Count - 1; i >= 0; i--)
			{
				if (timeSeries[i] < time)
				{
					index = i + 1;
					break;
				}
			}   
			return index;
		}
	}
static class Mq4Colors
{
    public static Colors GetColorByInteger(int integer)
    {
        switch (integer)
        {
            case 16777215: return Colors.White; case 16448255: return Colors.Snow; case 16449525: return Colors.MintCream; case 16118015: return Colors.LavenderBlush; case 16775408: return Colors.AliceBlue; case 15794160: return Colors.Honeydew; case 15794175: return Colors.Ivory; case 16119285: return Colors.WhiteSmoke; case 15136253: return Colors.OldLace; case 14804223: return Colors.MistyRose; case 16443110: return Colors.Lavender; case 15134970: return Colors.Linen; case 16777184: return Colors.LightCyan; case 14745599: return Colors.LightYellow; case 14481663: return Colors.Cornsilk; case 14020607: return Colors.PapayaWhip; case 14150650: return Colors.AntiqueWhite; case 14480885: return Colors.Beige; case 13499135: return Colors.LemonChiffon; case 13495295: return Colors.BlanchedAlmond; case 12903679: return Colors.Bisque; case 13353215: return Colors.Pink; case 12180223: return Colors.PeachPuff; case 14474460: return Colors.Gainsboro; case 12695295: return Colors.LightPink; case 11920639: return Colors.Moccasin; case 11394815: return Colors.NavajoWhite; case 11788021: return Colors.Wheat; case 13882323: return Colors.LightGray; case 15658671: return Colors.PaleTurquoise; case 11200750: return Colors.PaleGoldenrod; case 15130800: return Colors.PowderBlue; case 14204888: return Colors.Thistle; case 10025880: return Colors.PaleGreen; case 15128749: return Colors.LightBlue; case 14599344: return Colors.LightSteelBlue; case 16436871: return Colors.LightSkyBlue; case 12632256: return Colors.Silver; case 13959039: return Colors.Aquamarine; case 9498256: return Colors.LightGreen; case 9234160: return Colors.Khaki; case 14524637: return Colors.Plum; case 8036607: return Colors.LightSalmon; case 15453831: return Colors.SkyBlue; case 8421616: return Colors.LightCoral; case 15631086: return Colors.Violet; case 7504122: return Colors.Salmon; case 11823615: return Colors.HotPink; case 8894686: return Colors.BurlyWood; case 8034025: return Colors.DarkSalmon; case 9221330: return Colors.Tan; case 15624315: return Colors.MediumSlateBlue; case 6333684: return Colors.SandyBrown; case 11119017: return Colors.DarkGray; case 15570276: return Colors.CornflowerBlue; case 5275647: return Colors.Coral; case 9662683: return Colors.PaleVioletRed; case 14381203: return Colors.MediumPurple; case 14053594: return Colors.Orchid; case 9408444: return Colors.RosyBrown; case 4678655: return Colors.Tomato; case 9419919: return Colors.DarkSeaGreen; case 11193702: return Colors.MediumAquamarine; case 3145645: return Colors.GreenYellow; case 13850042: return Colors.MediumOrchid; case 6053069: return Colors.IndianRed; case 7059389: return Colors.DarkKhaki; case 13458026: return Colors.SlateBlue; case 14772545: return Colors.RoyalBlue; case 13688896: return Colors.Turquoise; case 16748574: return Colors.DodgerBlue; case 13422920: return Colors.MediumTurquoise; case 9639167: return Colors.DeepPink; case 10061943: return Colors.LightSlateGray; case 14822282: return Colors.BlueViolet; case 4163021: return Colors.Peru; case 9470064: return Colors.SlateGray; case 8421504: return Colors.Gray; case 255: return Colors.Red; case 16711935: return Colors.Magenta; case 16711680: return Colors.Blue; case 16760576: return Colors.DeepSkyBlue; case 16776960: return Colors.Aqua; case 8388352: return Colors.SpringGreen; case 65280: return Colors.Lime; case 65407: return Colors.Chartreuse; case 65535: return Colors.Yellow; case 55295: return Colors.Gold; case 42495: return Colors.Orange; case 36095: return Colors.DarkOrange; case 17919: return Colors.OrangeRed; case 3329330: return Colors.LimeGreen; case 3329434: return Colors.YellowGreen; case 13382297: return Colors.DarkOrchid; case 10526303: return Colors.CadetBlue; case 64636: return Colors.LawnGreen; case 10156544: return Colors.MediumSpringGreen; case 2139610: return Colors.Goldenrod; case 11829830: return Colors.SteelBlue; case 3937500: return Colors.Crimson; case 1993170: return Colors.Chocolate; case 7451452: return Colors.MediumSeaGreen; case 8721863: return Colors.MediumVioletRed; case 13828244: return Colors.DarkViolet; case 11186720: return Colors.LightSeaGreen; case 6908265: return Colors.DimGray; case 13749760: return Colors.DarkTurquoise; case 2763429: return Colors.Brown; case 13434880: return Colors.MediumBlue; case 2970272: return Colors.Sienna; case 9125192: return Colors.DarkSlateBlue; case 755384: return Colors.DarkGoldenrod; case 5737262: return Colors.SeaGreen; case 2330219: return Colors.OliveDrab; case 2263842: return Colors.ForestGreen; case 1262987: return Colors.SaddleBrown; case 3107669: return Colors.DarkOliveGreen; case 9109504: return Colors.DarkBlue; case 7346457: return Colors.MidnightBlue; case 8519755: return Colors.Indigo; case 128: return Colors.Maroon; case 8388736: return Colors.Purple; case 8388608: return Colors.Navy; case 8421376: return Colors.Teal; case 32768: return Colors.Green; case 32896: return Colors.Olive; case 5197615: return Colors.DarkSlateGray; case 25600: return Colors.DarkGreen; 
            case 0:
            default:
                return Colors.Black;
        }
    }
}
static class EventExtensions
{
	public static void Raise<T1, T2>(this Action<T1, T2> action, T1 arg1, T2 arg2)
	{
		if (action != null)
			action(arg1, arg2);
	}
}	
static class Mq4LineStyles
{
    public static LineStyle ToLineStyle(int style)
    {
		switch (style)
		{
			case 1: 
			return LineStyle.Lines;
			case 2: 
			return LineStyle.Dots;
			case 3: 
			case 4: 
			return LineStyle.LinesDots;
			default:
			return LineStyle.Solid;
		}
	}
}
    class Mq4TimeSeries
    {
        private readonly TimeSeries _timeSeries;
        private static readonly DateTime StartDateTime = new DateTime(1970, 1, 1);

        public Mq4TimeSeries(TimeSeries timeSeries)
        { 
            _timeSeries = timeSeries;
        }

        public static int ToInteger(DateTime dateTime)
        {
          return (int)(dateTime - StartDateTime).TotalSeconds;
        }
            
        public static DateTime ToDateTime(int seconds)
        {
          return StartDateTime.AddSeconds(seconds);
        }
                
        public int this[int index]
        {
            get 
            { 
                if (index < 0 || index >= _timeSeries.Count)
                  return 0;
                  
                DateTime dateTime = _timeSeries[_timeSeries.Count - 1 - index];

                return ToInteger(dateTime); 
            }
        }
    }
static class ConvertExtensions
{
    public static double? ToNullableDouble(this double protection)
    {
        if (protection == 0)
            return null;
        return protection;
    }

    public static DateTime? ToNullableDateTime(this int time)
    {
        if (time == 0)
            return null;

        return Mq4TimeSeries.ToDateTime(time);
    }       

    public static long ToUnitsVolume(this Symbol symbol, double lots) 
    {        
        return symbol.NormalizeVolume(symbol.ToNotNormalizedUnitsVolume(lots));
    }

    public static double ToNotNormalizedUnitsVolume(this Symbol symbol, double lots) 
    {
        if (symbol.Code.Contains("XAU") || symbol.Code.Contains("XAG"))
            return 100 * lots;
            
        return 100000 * lots;
    }

    public static double ToLotsVolume(this Symbol symbol, long volume) 
    {
        if (symbol.Code.Contains("XAU") || symbol.Code.Contains("XAG"))
            return volume * 1.0 / 100;
            
        return volume * 1.0 / 100000;
    }
}
struct Mq4Double : IComparable, IComparable<Mq4Double>
    {
      private readonly double _value;

      public Mq4Double(double value)
      {
        _value = value;
      }
      
      public static implicit operator double(Mq4Double property)
      {
        return property._value;
      }
      
      public static implicit operator int(Mq4Double property)
      {
        return (int)property._value;
      }     

      public static implicit operator bool(Mq4Double property)
      {
        return (int)property._value != 0;
      }

      public static implicit operator Mq4Double(double value)
      {
        return new Mq4Double(value);
      }

      public static implicit operator Mq4Double(int value)
      {
        return new Mq4Double(value);
      }

      public static implicit operator Mq4Double(bool value)
      {
        return new Mq4Double(value ? 1 : 0);
      }

      public static implicit operator Mq4Double(Mq4Null value)
      {
        return new Mq4Double(0);
      }
      
      public static Mq4Double operator +(Mq4Double d1, Mq4Double d2) 
      {
        return new Mq4Double(d1._value + d2._value);
      }
      
      public static Mq4Double operator -(Mq4Double d1, Mq4Double d2) 
      {
        return new Mq4Double(d1._value - d2._value);
      }

      public static Mq4Double operator -(Mq4Double d) 
      {
        return new Mq4Double(-d._value);
      }
      
      public static Mq4Double operator +(Mq4Double d) 
      {
        return new Mq4Double(+d._value);
      }
                  
      public static Mq4Double operator *(Mq4Double d1, Mq4Double d2) 
      {
        return new Mq4Double(d1._value * d2._value);
      }
      
      public static Mq4Double operator /(Mq4Double d1, Mq4Double d2) 
      {
        return new Mq4Double(d1._value / d2._value);
      }
      
      public static bool operator ==(Mq4Double d1, Mq4Double d2) 
      {
        return d1._value == d2._value;
      }
            
      public static bool operator >(Mq4Double d1, Mq4Double d2) 
      {
        return d1._value > d2._value;
      } 
      
      public static bool operator >=(Mq4Double d1, Mq4Double d2) 
      {
        return d1._value >= d2._value;
      }
            
      public static bool operator <(Mq4Double d1, Mq4Double d2) 
      {
        return d1._value < d2._value;
      }
            
      public static bool operator <=(Mq4Double d1, Mq4Double d2) 
      {
        return d1._value <= d2._value;
      }
      
      public static bool operator !=(Mq4Double d1, Mq4Double d2) 
      {
		return d1._value != d2._value;
      }
          
      public override string ToString()
      {
		return _value.ToString();
      }

      public int CompareTo(object obj)
      {
          return _value.CompareTo(obj);
      }

      public int CompareTo(Mq4Double obj)
      {
          return _value.CompareTo(obj);
      }
}   
	class Mq4DoubleTwoDimensionalArray
	{
		private List<Mq4Double> _data = new List<Mq4Double>();
		private List<Mq4DoubleArray> _arrays = new List<Mq4DoubleArray>();
		private readonly Mq4Double _defaultValue;
		private readonly int _size2;
		      
		public Mq4DoubleTwoDimensionalArray(int size2)
        {
			_defaultValue = 0;
			_size2 = size2;
		}

        public void Add(Mq4Double value)
        {
			_data.Add(value);
        }

		private void EnsureCountIsEnough(int index)
		{
			while (_arrays.Count <= index)
				_arrays.Add(new Mq4DoubleArray());
		}

		public void Initialize(Mq4Double value)
		{
			for (var i = 0; i < _data.Count; i++)
				_data[i] = value;
		}

		public int Range(int index)
		{
			if (index == 0)
				return _data.Count;
			return this[0].Length;
		}
				     
		public Mq4DoubleArray this[int index]
		{       
			get
			{
				if (index < 0)
					return new Mq4DoubleArray();

				EnsureCountIsEnough(index);         

				return _arrays[index];
			}       
		}	

		public Mq4Double this[int index1, int index2]
		{       
			get
			{
				if (index1 < 0)
					return 0;

				EnsureCountIsEnough(index1);         

				return _arrays[index1][index2];
			}    
			set
			{
				if (index1 < 0)
					return;

				EnsureCountIsEnough(index1);         

				_arrays[index1][index2] = value;
			}   
		}	
	}
	class Mq4DoubleArray : IMq4DoubleArray, IEnumerable
	{
		private List<Mq4Double> _data = new List<Mq4Double>();
		private readonly Mq4Double _defaultValue;
		      
		public Mq4DoubleArray(int size = 0)
        {
			_defaultValue = 0;
		}

		public IEnumerator GetEnumerator()
		{
            return _data.GetEnumerator();
        }

		private bool _isInverted;
		public bool IsInverted
		{
			get { return _isInverted; }
			set { _isInverted = value; }
		}

        public void Add(Mq4Double value)
        {
			_data.Add(value);
        }

		private void EnsureCountIsEnough(int index)
		{
			while (_data.Count <= index)
				_data.Add(_defaultValue);
		}

		public int Length 
		{
			get { return _data.Count; }
		}

		public void Resize(int newSize)
		{ 
			while (newSize < _data.Count)
				_data.RemoveAt(_data.Count - 1);

			while (newSize > _data.Count)
				_data.Add(_defaultValue);
		}
				     
		public Mq4Double this[int index]
		{       
			get
			{
				if (index < 0)
					return _defaultValue;    
            
				EnsureCountIsEnough(index);         

				return _data[index];
			}       
			set
			{
				if (index < 0)
					return;
            
				EnsureCountIsEnough(index);
          
				_data[index] = value;
				Changed.Raise(index, value);
			}
		}
public event Action<int, Mq4Double> Changed;
	}
	class Mq4MarketDataSeries : IMq4DoubleArray
    {
        private DataSeries _dataSeries;

        public Mq4MarketDataSeries(DataSeries dataSeries)
        {
            _dataSeries = dataSeries;
        }

        public Mq4Double this[int index]
        {
            get { return _dataSeries.Last(index); }
			set { }
        }

		public int Length 
		{
			get { return _dataSeries.Count; }
		}

        public void Resize(int newSize)
        {        
        }
    }
	class Mq4StringArray : IEnumerable
	{
		private List<Mq4String> _data = new List<Mq4String>();
		private readonly Mq4String _defaultValue;
		      
		public Mq4StringArray(int size = 0)
		{
			_defaultValue = "";
		}

		public IEnumerator GetEnumerator()
		{
            return _data.GetEnumerator();
        }

		private bool _isInverted;
		public bool IsInverted
		{
			get { return _isInverted; }
			set { _isInverted = value; }
		}

        public void Add(Mq4String value)
        {
			_data.Add(value);
        }

		private void EnsureCountIsEnough(int index)
		{
			while (_data.Count <= index)
				_data.Add(_defaultValue);
		}

		public int Length 
		{
			get { return _data.Count; }
		}

		public void Resize(int newSize)
		{ 
			while (newSize < _data.Count)
				_data.RemoveAt(_data.Count - 1);

			while (newSize > _data.Count)
				_data.Add(_defaultValue);
		}
				     
		public Mq4String this[int index]
		{       
			get
			{
				if (index < 0)
					return _defaultValue;    
            
				EnsureCountIsEnough(index);         
          
				return _data[index];
			}       
			set
			{
				if (index < 0)
					return;
            
				EnsureCountIsEnough(index);
          
				_data[index] = value;
			}
		}	
	}
	interface IMq4DoubleArray
	{		
		Mq4Double this[int index] { get; set; }
		int Length { get; }
		void Resize(int newSize);
	}
	class Mq4ArrayToDataSeriesConverter
	{
		private readonly Mq4DoubleArray _mq4Array;
		private readonly IndicatorDataSeries _dataSeries;

		public Mq4ArrayToDataSeriesConverter(Mq4DoubleArray mq4Array, IndicatorDataSeries dataSeries)
		{
			_mq4Array = mq4Array;
			_dataSeries = dataSeries;
			_mq4Array.Changed += OnValueChanged;
			CopyAllValues();
		}

		private void CopyAllValues()
		{
			for (var i = 0; i < _mq4Array.Length; i++)
			{
				if (_mq4Array.IsInverted)
					_dataSeries[_mq4Array.Length - i] = _mq4Array[i];
				else
					_dataSeries[i] = _mq4Array[i];
			}
		}

		private void OnValueChanged(int index, Mq4Double value)
		{			
			int indexToSet;
			if (_mq4Array.IsInverted)
				indexToSet = _mq4Array.Length - index;
			else
				indexToSet = index;

			if (indexToSet < 0)
				return;

			_dataSeries[indexToSet] = value;
		}
	}
	class Mq4ArrayToDataSeriesConverterFactory
	{
		private readonly Dictionary<Mq4DoubleArray, IndicatorDataSeries> _cachedAdapters = new Dictionary<Mq4DoubleArray, IndicatorDataSeries>();
		private Func<IndicatorDataSeries> _dataSeriesFactory;

		public Mq4ArrayToDataSeriesConverterFactory(Func<IndicatorDataSeries> dataSeriesFactory)
		{
			_dataSeriesFactory = dataSeriesFactory;
		}

		public DataSeries Create(Mq4DoubleArray mq4Array)
		{
			IndicatorDataSeries dataSeries;

			if (_cachedAdapters.TryGetValue(mq4Array, out dataSeries))
				return dataSeries;

			dataSeries = _dataSeriesFactory();
			new Mq4ArrayToDataSeriesConverter(mq4Array, dataSeries);
			_cachedAdapters[mq4Array] = dataSeries;

			return dataSeries;
		}
	}

}

 


@tgjobscv

genappsforex
19 Dec 2019, 09:07

What's the problem except using an MT4 proxy thus clogging up everything and not writing the code as one should!

Suggested Fix:
1. Extract the logic
2. Rewrite the stuff fitted to cTrader without all that MT4 rubbish

And last but not least If you do not understand the logic, don't use the bot

 


@genappsforex