Amibroker. Скользящий стоп

Nov 26, 2013 09:47

Точнее - QUIK'овский take profit.
Давно уже написал обычным циклом, а тут вдруг решил оптимизировать по скорости.
В результате ускорил, как обычно, в 60 раз :)
Амиброкеровский тестер пишет, что метод выполняется 1.2 ms
Работает только последовательно (используются статические поля), потому что амиброкер всё-равно их последовательно запускает во время тестирования или оптимизации.
Кто заметит ошибку, пишите.


using System;
using AmiBroker;
using AmiBroker.PlugIn;
using AmiBroker.Utils;

namespace VGnAmiBrokerPlugIn
{
    public static class TrailingStopUnsafe
    {
        private static ATArray _trailArray;

private static ATArray _close;
        private static ATArray _low;
        private static ATArray _high;

private static ATArray _buy;
        private static ATArray _sell;
        private static ATArray _short;
        private static ATArray _cover;
        private static ATArray _sellPrice;
        private static ATArray _coverPrice;

//todo: только long или только short

///
        ///        Подтягивание стопа с фиксированным начальным размером
        ///
        ///
        [ABMethod(Name = "VGnTprof")]
        [ABParameter(0, Type = ABParameterType.Array, Description = "startStop")]
        [ABParameter(1, Type = ABParameterType.Array, Description = "stopVal")]
        [ABParameter(2, Type = ABParameterType.Array, Description = "profitVal")]
        public static unsafe ATVar VGnTprof(int argNum, ATVar* argList)
        {
            try
            {
                var startStop = argList[0].GetArray();
                var stopVal = argList[1].GetArray();
                var profitVal = argList[2].GetArray();

_trailArray = new ATArray(0);

_close = ABHost.GetStockArray(StockField.Close);
                _low = ABHost.GetStockArray(StockField.Low);
                _high = ABHost.GetStockArray(StockField.High);

_buy = ABVars.Buy.GetArray();
                _sell = ABVars.Sell.GetArray();
                _short = ABVars.Short.GetArray();
                _cover = ABVars.Cover.GetArray();
                _sellPrice = ABVars.SellPrice.GetArray();
                _coverPrice = ABVars.CoverPrice.GetArray();

DoLongTrail(startStop, stopVal, profitVal);
                DoShortTrail(startStop, stopVal, profitVal);
            }
            catch (Exception e)
            {
                // present error message on indicator panel and the Log-Trace window
                YException.Show("Error while executing indicator.", e);
            }
            return new ATVar(_trailArray);
        }

///
        ///      
        ///
        ///

///

///

///
Использовать startStop как значение цены или как размер стопа
        private static unsafe void DoLongTrail(
            ATArray startStop,
            ATArray stopVal,
            ATArray profitVal,
            bool asPrice = false)
        {
            unchecked
            {
                var trailing = false;
                float trail = 0;
                float profit = 0;

// позиционирование на начало массивов

var pTrail = _trailArray.Array;

var pStopVal = stopVal.Array;
                var pStartStop = startStop.Array;
                var pProfitVal = profitVal.Array;

var pClose = _close.Array;
                var pLow = _low.Array;
                var pHigh = _high.Array;

var pBuy = _buy.Array;
                var pSell = _sell.Array;
                var pShort = _short.Array;
                var pSellPrice = _sellPrice.Array;

for (var pTrailEnd = _trailArray.Array + _trailArray.Length;
                    pTrail < pTrailEnd;
                    pTrail++, pStopVal++, pStartStop++, pProfitVal++, pClose++, pLow++, pHigh++, pBuy++, pSell++, pShort++, pSellPrice++)
                {
                    if (trailing)
                    {
                        *pBuy = ATFloat.False; // удаление лишнего сигнала открытия позиции
                        if (ATFloat.IsTrue(*pSell) || ATFloat.IsTrue(*pShort))
                            // прекращение отслеживания при получении обратного сигнала
                        {
                            trailing = false;
                            continue;
                        }
                        if (*pLow < trail) // срабатывание стопа
                        {
                            *pSell = ATFloat.True;
                            *pSellPrice = trail;
                            trailing = false;
                            continue;
                        }
                        if (*pHigh > profit)
                            trail = Math.Max(*pHigh - *pStopVal, trail); // слежение
                    }
                    else
                    {
                        *pSell = ATFloat.False; // удаление лишнего сигнала закрытия позиции
                        if (ATFloat.IsTrue(*pBuy)) // запуск отслеживания при открытии позиции
                        {
                            trail = asPrice ? *pStartStop : *pHigh - *pStartStop;
                            profit = *pHigh + *pProfitVal;
                            trailing = true;
                        }
                    }

if (trailing)
                        *pTrail = trail;
                }
            }
        }

///
        ///      
        ///
        ///

///

///

///
Использовать startStop как значение цены или как размер стопа
        private static unsafe void DoShortTrail(
            ATArray startStop,
            ATArray stopVal,
            ATArray profitVal,
            bool asPrice = false)
        {
            unchecked
            {
                var trailing = false;
                float trail = 0;
                float profit = 0;

var pTrail = _trailArray.Array;

var pStopVal = stopVal.Array;
                var pStartStop = startStop.Array;
                var pProfitVal = profitVal.Array;

var pClose = _close.Array;
                var pLow = _low.Array;
                var pHigh = _high.Array;

var pBuy = _buy.Array;
                var pShort = _short.Array;
                var pCover = _cover.Array;
                var pCoverPrice = _coverPrice.Array;

for (var pTrailEnd = _trailArray.Array + _trailArray.Length;
                    pTrail < pTrailEnd;
                    pTrail++, pStopVal++, pStartStop++, pProfitVal++, pClose++, pLow++, pHigh++, pBuy++, pCover++, pShort++, pCoverPrice++)
                {
                    if (trailing)
                    {
                        *pShort = ATFloat.False; // remove excess buy signals
                        if (ATFloat.IsTrue(*pCover) || ATFloat.IsTrue(*pBuy))
                        {
                            trailing = false;
                            continue;
                        }
                        if (*pHigh > trail)
                        {
                            *pCover = ATFloat.True;
                            *pCoverPrice = trail;
                            trailing = false;
                            continue;
                        }
                        if (*pLow < profit)
                            trail = Math.Min(*pLow + *pStopVal, trail);
                    }
                    else
                    {
                        *pCover = ATFloat.False;
                        if (ATFloat.IsTrue(*pShort))
                        {
                            trail = asPrice ? *pStartStop : *pLow + *pStartStop;
                            profit = *pLow - *pProfitVal;
                            trailing = true;
                        }
                    }

if (trailing)
                        *pTrail = trail;
                }
            }

}

}
}

программирование, amibroker, c#, dotnetforab, алготрейдинг, quik

Previous post Next post
Up