// Downloaded From https://www.WiseStockTrader.com
_SECTION_BEGIN("Manual Tester");
// Manual Tester.afl
// Ручной тестер для AmiBroker

if(TickSize == 0)
{
    PopupWindow("\nУкажите в свойствах символа (Symbol -> Information) параметр TickSize!", "Error");
}
else
{
    // параметры
    StartX = Param("Buttons X", 30, 0, 1000, 5);
    StartY = Param("Buttons Y", 20, 0, 1000, 5);
    Spread = Param("Spread (pips)", 0, 0, 1000) * TickSize;
    ScanMode = ParamList("Scan Mode", "Test|Clear all signals|Save to file|Load from file", 0);
    fileName = ParamStr("File path", "E://Программы/AmiBroker/Tester/Trades.txt");

    // инициализация
    BarDateTime = DateTime();
    Buy = Sell = Short = Cover = 0;
    BuyPrice = SellPrice = ShortPrice = CoverPrice = C;

    // режим выполнения кода
    formulaAction = Status("ActionEx");

    // -------------- РЕЖИМ ИНДИКАТОРА ---------------

    if(formulaAction == actionIndicator)
    {
        // парамеры графика
        RequestTimedRefresh(1);
        GfxSetOverlayMode(0); 
        GfxSetBkMode(1);

        // размер кнопок и расстояние между ними
        CellHeight = 24; 
        CellWidth = 70;
        CellXSpace = 10;

        // цвета кнопок
        BorderColor = colorBlack;
        InactiveButtonColor = colorCustom6;
        ActiveButtonColor = colorRed;

        // номер активной кнопки
        ActiveButton = StaticVarGet("ActiveButton");

        // парамеры рисования кнопок
        GfxSelectPen(BorderColor, 2);
        GfxSelectFont( "Tahoma", 11 , 700);

        // отрисовка кнопок
        for(btn = 1; btn <= 6; btn++)
        {
            if(ActiveButton == btn)
            {
                GfxSelectSolidBrush(ActiveButtonColor);
                GfxSetTextColor(colorWhite);
            }
            else
            {
                GfxSelectSolidBrush(InactiveButtonColor);
                GfxSetTextColor(ColorRGB(40,40,40));
            }

            CellX = StartX + (btn - 1) * (CellWidth + CellXSpace);
            GfxRectangle(CellX, StartY, CellX + CellWidth, StartY + CellHeight);

            switch(btn)
            {
            case 1:
                BtnText = "Buy";
                break;
            case 2:
                BtnText = "Sell";
                break;
            case 3:
                BtnText = "Short";
                break;
            case 4:
                BtnText = "Cover";
                break;
            case 5:
                BtnText = "Clear";
                break;
            case 6:
                BtnText = "Clear All";
                break;
            }

            GfxDrawText(BtnText, CellX, StartY, CellX + CellWidth, StartY + CellHeight, 32+1+4);
        }

        // обработка нажатия левой кнопки
        if(GetCursorMouseButtons() & 8)
        {
            // координаты курсора в пикселах 
            px = GetCursorXPosition(1); 
            py = GetCursorYPosition(1);

            buttonPressed = False;

            if(py >= StartY AND py <= StartY + CellHeight)
            {
                for(btn = 1; btn <= 6; btn++)
                {
                    CellX = StartX + (btn - 1) * (CellWidth + CellXSpace);
                    if(px >= CellX AND px <= CellX + CellWidth)
                    {
                        // активация или деактивация кнопки
                        if(ActiveButton == btn)
                            StaticVarSet("ActiveButton", 0);
                        else
                            StaticVarSet("ActiveButton", btn);

                        buttonPressed = True;

                        break;
                    }
                }
            }

            // нажата кнопка "Clear All"
            if(buttonPressed == True AND StaticVarGet("ActiveButton") == 6)
            {
                for(i = 0; i < BarCount; i++)
                {
                    StaticVarRemove(Name() + "Buy"   + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "Sell"  + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "Short" + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "Cover" + DateTimeToStr(BarDateTime[i]));

                    StaticVarRemove(Name() + "BuyPrice"   + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "SellPrice"  + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "ShortPrice" + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "CoverPrice" + DateTimeToStr(BarDateTime[i]));
                }

                StaticVarSet("ActiveButton", 0);
            } 

            // запись сделки в статическую переменную
            if(buttonPressed == False)
            {
                // координаты курсора цена/дата 
                x = GetCursorXPosition(0); 
                y = GetCursorYPosition(0);
                y = round(y / TickSize) * TickSize;    // округление до TickSize

                // Buy
                if(ActiveButton == 1)
                {
                    VarBuy = Name() + "Buy" + DateTimeToStr(x);
                    VarBuyPrice = Name() + "BuyPrice" + DateTimeToStr(x);

                    StaticVarSet(VarBuy, 1);
                    StaticVarSet(VarBuyPrice, y);
                }

                // Sell
                if(ActiveButton == 2)
                {
                    VarSell = Name() + "Sell" + DateTimeToStr(x);
                    VarSellPrice   = Name() + "SellPrice" + DateTimeToStr(x);

                    StaticVarSet(VarSell, 1);
                    StaticVarSet(VarSellPrice, y);
                }

                // Short
                if(ActiveButton == 3)
                {
                    VarShort = Name() + "Short" + DateTimeToStr(x);
                    VarShortPrice = Name() + "ShortPrice" + DateTimeToStr(x);

                    StaticVarSet(VarShort, 1);
                    StaticVarSet(VarShortPrice, y);
                }

                // Cover
                if(ActiveButton == 4)
                {
                    VarCover   = Name() + "Cover" + DateTimeToStr(x);
                    VarCoverPrice = Name() + "CoverPrice" + DateTimeToStr(x);

                    StaticVarSet(VarCover, 1);
                    StaticVarSet(VarCoverPrice, y);
                }

                // Clear
                if(ActiveButton == 5)
                {
                    VarBuy = Name() + "Buy" + DateTimeToStr(x);
                    VarBuyPrice = Name() + "BuyPrice" + DateTimeToStr(x);

                    VarSell = Name() + "Sell" + DateTimeToStr(x);
                    VarSellPrice = Name() + "SellPrice" + DateTimeToStr(x);

                    VarShort = Name() + "Short" + DateTimeToStr(x);
                    VarShortPrice = Name() + "ShortPrice" + DateTimeToStr(x);

                    VarCover = Name() + "Cover" + DateTimeToStr(x);
                    VarCoverPrice = Name() + "CoverPrice" + DateTimeToStr(x);

                    StaticVarRemove(VarBuy);
                    StaticVarRemove(VarSell);
                    StaticVarRemove(VarShort);
                    StaticVarRemove(VarCover);

                    StaticVarRemove(VarBuyPrice);
                    StaticVarRemove(VarSellPrice);
                    StaticVarRemove(VarShortPrice);
                    StaticVarRemove(VarCoverPrice);        
                }

                StaticVarSet("ActiveButton", 0);    // деактивация кнопки после выполнения действия
            }
        }

        // копирование сделок из статических переменных в торговые массивы
        for(i = 0; i < BarCount; i++)
        {
            BuySig   = StaticVarGet(Name() + "Buy"   + DateTimeToStr(BarDateTime[i]));
            SellSig  = StaticVarGet(Name() + "Sell"  + DateTimeToStr(BarDateTime[i]));
            ShortSig = StaticVarGet(Name() + "Short" + DateTimeToStr(BarDateTime[i]));
            CoverSig = StaticVarGet(Name() + "Cover" + DateTimeToStr(BarDateTime[i]));

            if(BuySig)
            {
                Buy[i] = 1;
                BuyPrice[i] = StaticVarGet(Name() + "BuyPrice" + DateTimeToStr(BarDateTime[i])) + spread;
            }

            if(SellSig)
            {
                Sell[i] = 1;
                SellPrice[i]  = StaticVarGet(Name() + "SellPrice"  + DateTimeToStr(BarDateTime[i]));
            }

            if(ShortSig)
            {
                Short[i] = 1;
                ShortPrice[i] = StaticVarGet(Name() + "ShortPrice" + DateTimeToStr(BarDateTime[i]));
            }

            if(CoverSig)
            {
                Cover[i] = 1;
                CoverPrice[i] = StaticVarGet(Name() + "CoverPrice" + DateTimeToStr(BarDateTime[i])) + spread;
            }
        }

        // ------ Отрисовка стрелок
        PlotShapes(Buy * shapeUpArrow, colorLime, 0, BuyPrice, -8);
        PlotShapes(Sell * shapeDownArrow, colorCustom12, 0, SellPrice, -8);
        PlotShapes(Short * shapeHollowDownArrow, colorCustom12, 0, ShortPrice, -8);
        PlotShapes(Cover * shapeHollowUpArrow, colorLime, 0, CoverPrice, -8);
    }

    // -------------- РЕЖИМ ТЕСТИРОВАНИЯ ИЛИ СКАНИРОВАНИЯ ---------------

    if(formulaAction == actionScan OR formulaAction == actionBacktest)
    {
        // тестирование
        if(ScanMode == "Test")
        {
            // настройки тестера
            SetOption("InitialEquity", 10000);
            SetOption("AllowPositionShrinking", False);
            SetOption("ReverseSignalForcesExit", True);
            SetOption("AllowSameBarExit", True);
            SetOption("ActivateStopsImmediately", True);
            SetOption("MaxOpenPositions", 100);
            SetOption("PriceBoundChecking", False);
            SetOption("FuturesMode", True);
            SetOption("CommissionMode", 2);
            SetOption("CommissionAmount", 0);
            SetTradeDelays(0, 0, 0, 0);

            PositionSize = 100;
            MarginDeposit = 100;
            RoundLotSize = 1;
            PointValue = 1/TickSize;

            // чтение сделок из статических переменных
            for(i = 0; i < BarCount; i++)
            {
                BuySig   = StaticVarGet(Name() + "Buy"   + DateTimeToStr(BarDateTime[i]));
                SellSig  = StaticVarGet(Name() + "Sell"  + DateTimeToStr(BarDateTime[i]));
                ShortSig = StaticVarGet(Name() + "Short" + DateTimeToStr(BarDateTime[i]));
                CoverSig = StaticVarGet(Name() + "Cover" + DateTimeToStr(BarDateTime[i]));

                if(BuySig)
                {
                    Buy[i] = 1;
                    BuyPrice[i] = StaticVarGet(Name() + "BuyPrice" + DateTimeToStr(BarDateTime[i])) + spread;
                }

                if(SellSig)
                {
                    Sell[i] = 1;
                    SellPrice[i]  = StaticVarGet(Name() + "SellPrice"  + DateTimeToStr(BarDateTime[i]));
                }

                if(ShortSig)
                {
                    Short[i] = 1;
                    ShortPrice[i] = StaticVarGet(Name() + "ShortPrice" + DateTimeToStr(BarDateTime[i]));
                }

                if(CoverSig)
                {
                    Cover[i] = 1;
                    CoverPrice[i] = StaticVarGet(Name() + "CoverPrice" + DateTimeToStr(BarDateTime[i])) + spread;
                }
            }
        }

        // очистка статических переменных
        if(ScanMode == "Clear all signals")
        {
            for(i = 0; i < BarCount; i++)
            {
                StaticVarRemove(Name() + "Buy"   + DateTimeToStr(BarDateTime[i]));
                StaticVarRemove(Name() + "Sell"  + DateTimeToStr(BarDateTime[i]));
                StaticVarRemove(Name() + "Short" + DateTimeToStr(BarDateTime[i]));
                StaticVarRemove(Name() + "Cover" + DateTimeToStr(BarDateTime[i]));

                StaticVarRemove(Name() + "BuyPrice"   + DateTimeToStr(BarDateTime[i]));
                StaticVarRemove(Name() + "SellPrice"  + DateTimeToStr(BarDateTime[i]));
                StaticVarRemove(Name() + "ShortPrice" + DateTimeToStr(BarDateTime[i]));
                StaticVarRemove(Name() + "CoverPrice" + DateTimeToStr(BarDateTime[i]));
            }

            StaticVarSet("ActiveButton", 0); 
        }

        // сохранение сделок в файл
        if(ScanMode == "Save to file")
        {
            // количество цифр после запятой
            digits = Max(log10(1/TickSize), 0);

            // открытие файла для записи
            fh = fopen(fileName, "w");
        
            if(fh)
            {
                for(i = 0; i < BarCount; i++)
                {
                    BuySig   = StaticVarGet(Name() + "Buy"   + DateTimeToStr(BarDateTime[i]));
                    SellSig  = StaticVarGet(Name() + "Sell"  + DateTimeToStr(BarDateTime[i]));
                    ShortSig = StaticVarGet(Name() + "Short" + DateTimeToStr(BarDateTime[i]));
                    CoverSig = StaticVarGet(Name() + "Cover" + DateTimeToStr(BarDateTime[i]));

                    if(BuySig)
                    {
                        Price  = StaticVarGet(Name() + "BuyPrice"  + DateTimeToStr(BarDateTime[i]));
                        fputs(Name() + "Buy," + DateTimeToStr(BarDateTime[i]) + "," + NumToStr(Price, digits/10, False) + "\n", fh);
                    }

                    if(SellSig)
                    {
                        Price  = StaticVarGet(Name() + "SellPrice"  + DateTimeToStr(BarDateTime[i]));
                        fputs(Name() + "Sell," + DateTimeToStr(BarDateTime[i]) + "," + NumToStr(Price, digits/10, False) + "\n", fh);
                    }

                    if(ShortSig)
                    {
                        Price = StaticVarGet(Name() + "ShortPrice" + DateTimeToStr(BarDateTime[i]));
                        fputs(Name() + "Short," + DateTimeToStr(BarDateTime[i]) + "," + NumToStr(Price, digits/10, False) + "\n", fh);
                    }

                    if(CoverSig)
                    {
                        Price = StaticVarGet(Name() + "CoverPrice" + DateTimeToStr(BarDateTime[i]));
                        fputs(Name() + "Cover," + DateTimeToStr(BarDateTime[i]) + "," + NumToStr(Price, digits/10, False) + "\n", fh);
                    }
                }

                fclose(fh);
            }
            else
                PopupWindow("\n\nОшибка открытия или создания файла " + fileName + "\n\nСоздайте указанный каталог", "Export Error", 60);
        }

        // загрузка сделок из файла
        if(ScanMode == "Load from file")
        {
            // открытие файла для чтения
            fh = fopen(fileName, "r");

            if(fh)
            {
                // очистка графика от сигналов
                for(i = 0; i < BarCount; i++)
                {
                    StaticVarRemove(Name() + "Buy"   + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "Sell"  + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "Short" + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "Cover" + DateTimeToStr(BarDateTime[i]));

                    StaticVarRemove(Name() + "BuyPrice"   + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "SellPrice"  + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "ShortPrice" + DateTimeToStr(BarDateTime[i]));
                    StaticVarRemove(Name() + "CoverPrice" + DateTimeToStr(BarDateTime[i]));
                }

                StaticVarSet("ActiveButton", 0);

                // чтение сигналов из файла
                while(! feof(fh))
                {
                    // чтение строки из файла
                    stringTrade = fgets(fh);
                    
                    // парсинг
                    sName = StrExtract(stringTrade, 0);
                    sSig = StrExtract(stringTrade, 1);
                    sDate = StrExtract(stringTrade, 2);
                    sPrice = StrExtract(stringTrade, 3);

                    VarSig = sName + sSig + sDate;
                    VarPrice = sName + sSig + "Price" + sDate;

                    // запись в статические переменные
                    StaticVarSet(VarSig, 1);
                    StaticVarSet(VarPrice, StrToNum(sPrice));
                }

                fclose(fh);
            }
            else
                PopupWindow("\n\nОшибка открытия файла " + fileName + "\n\nУказанный файл не существует.", "Import error", 60);
        }
    }
}
_SECTION_END();