Избранное трейдера Aleksey

по

алго - мои мультитикеры

Всем привет, что-то маловато мотивации в последнее время улучшать ботов, итак всё неплохо.
А как можно улучшить мотивацию? Спалить пару своих фишек, тогда придётся придумывать новые. Вроде неплохой метод, да?
Не секрет что я использую в алготрейдинге 4 тикера. Си, еу, ртс, сбер. Маловато, да?
Основная причина это эффективность рынков, то что слишком много торгуется западными фондами — там меньше неэффективностей.
Поэтому я бросил попытки торговать золотом, брентом, евробаксом и перестал искать системы для них.
Из той же оперы вся Америка, все исследования квантов в основном про Америку, конкуренция жёсткая...
Я всегда это понимал интуитивно, и впоследствии тесты это подтвердили.
Также я бросил торговать малоликвидными тикерами, поэтому осталось 4 тикера, но не всё так плохо.


( Читать дальше )

Модель инвестиций в акции с опционным привкусом.

          Нет, нет. Я не планирую становиться инвестором в акции, мне по прежнему больше по нраву деятельность опционного спекулянта. В этом топике я попробую показать, как простые нелинейные приемы могут сэкономить нервы (и, в конечном счете, принести дополнительные деньги) последователям стратегии купил/держи. Все нижеизложенное представляет собой не более чем шаблон, однако, после некоторой дополнительной обработки, вполне может быть применено (и применялось) на практике. На оригинальность идеи тоже претендовать не приходится. Подобные подходы применяются часто. Однако, систематизация и визуализация применяемого подхода никогда никому не мешала.
          Итак. Допустим, мы находимся на идеальном рынке. Ликвидность абсолютна, торги непрерывны, никаких проскальзываний и комиссий в природе не существует. Что такое позиция «шорт» мы не слышали и слышать не хотим. Из каких то соображений мы решили инвестировать сумму в 1 000 000 рублей в акции с текущей стомостью 100 рублей. (Здесь и далее все числовые значения условны, легко заменяются переменными и используются для построения конкретных примеров). 

( Читать дальше )

Торговая система "купи-продай".

    • 16 октября 2017, 08:10
    • |
    • XXM
  • Еще

Представляю торговую систему «купи-продай».

Суть ее очень проста: Покупаем некоторое количество бумаг (start_qty), и выставляем заявки по лесенке на продажу через определенное количество пунктов.
Шаг лесенки назовем step. Да, бумаги следует продавать одинаковыми пачками, по qty_in_step лотов.
(Оставляем пока за бортом поста тему — а что делать, если купили, выставили заявки на продажу, а бумага пошла вниз?)
Поведение Equity при разных start_qty приведено на рисунке.
Супер-система, купи-продай. Многие знают, но стесняются говорить ;)


Индикаторы можете скачать со страницы www.xsharp.ru/indikators  файл StockTest.zip, два индикатора:
1. StockTest.lua — проставляет метки сделок. Ее следует добавить на график бумаги;
2. StockEquity.lua — строит кривую Equity, следует добавить на отдельное окно.

Успешной игры по тренду!


Как получить дивиденд по фьючерсу, и сколько стоит фьючерсное плечо

    • 03 октября 2017, 13:00
    • |
    • rtsi
  • Еще

Я заметил, что бытует мнение, что по фьючерсам не платится дивиденд.

Так обычно и говорят: фьючерс на индекс RTS отслеживает только индекс RTS, и не учитывает выплачиваемый по этому индексу дивиденд. То же самое говорят и об акциях.

В крайних случаях брокерские компании в рекламных буклетах могут даже рассказывать, что плечо во фьючерсах — бесплатное.

Это, конечно, не так.

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

  • если это акции, то он получает по этим акциям дивиденды;

  • если это фьючерс на индекс акций, то он купил акции, входящие в индекс, и получает по ним дивиденды;

  • если это фьючерс на ОФЗ, то он получает по ним купонный доход;

  • если это фьючерс на доллар, то он получает доход, разместив доллары на депозите под безрисковую ставку;



( Читать дальше )

Управление капиталом портфеля алгоритмических стратегий.

Изначально, была мысль написать большую статью, с множеством забавных эпизодов, прекрасно иллюстрированную. Но, честно, не осилил. Не нашел как верно отобразить графическую информацию. Поэтому, полагаюсь на то, что заинтересованные — сами проверят все описанные методы и оставят один-два комментария. 

Рассмотрим разные варианты управления капиталом при торговле портфелем стратегий.

Для простоты, можно рассматривать портфель из двух стратегий, на отрезке где одна стратегия стабильно зарабатывает, а вторая работает неустойчиво. 

1. Фиксированный лот без реинвестирования. Просто суммируем две кривые прироста капитала. В данном случае все просто, одна стратегия делает прибыль, другая добавляет просадки. При раздельном тестировании этот метод позволяет наиболее точно оценить стратегию. Минус метода в том, что при значительном изменении капитала (вывод или занос денег) нужно править рабочий обьем. 

2. Каждой стратегии выделяется равный процент депозита, прибыль реинвестируется, либо уменьшается обьем при просадке счета
Тут вроде все понятно, этот подход все любят. На прибыль добавляемся, при убытке сокращаем лот. Если одна стратегия сильно льет, а вторая немного зарабатывает, то рабочий обьем режется на всех стратегиях, так как общий размер депозита сокращается. И тут возникает вариант 3, про который почему-то никто не говорит. 

3. Создаем условия, когда каждая стратегия работает независимо (одна стратегия — один счет, стартовая сумма для счетов одинаковая), прибыль реинвестируется, либо уменьшается обьем при просадке счета. При этом каждое направление входа системы (лонг или шорт) рассматривается как отдельно взятая стратегия. Почему так? Возьмем простую трендследящую стратегию. На тренде вверх имеем хорошие сделки от лонга, но на резких и коротких коррекциях тренда шорт как правило не зарабатывает. И наоборот для тренда вниз. В этом случае мы будем резать лот на убыточном направлении стратегии и добавлять на прибыльном. 

4. Доработка варианта 3. К каждой отдельно взятой стратегии добавляем элемент equity-trading. В коде стратегии отслеживаем изменение капитала (start_deposit +- netprofit), параллельно заполняем массив финансового результата при торговле 1 лотом, вводим порог допустимой просадки и при ее достижении выключаем стратегию (торгуем минимально возможным обьемом — 1 контракт или 1 акция). При восстановлении теоретической кривой капитала выше порога просадки — возобновляем работу полным обьемом. Порог просадки задается исходя из прошлых данных бэктеста, либо на глаз. Сильно зажимать порог нельзя. На глаз у меня получилось, что максимальная просадка стратегии с учетом процента капитала выделяемого на стратегию примерно равняется 3% на весь капитал. То есть, если стратегия торгует на 30% капитала, то пороговое значение должно быть примерно 10%. Здесь возможны исключения, например для стратегий с малой просадкой можно задавать пороговое значение чуть больше максимальной исторической просадки.  
Мои тесты показывают, что при применении варианта 4 общая прибыль незначительно снижается, но так же снижается и просадка. Соотношение профит-просадка увеличивается примерно на 20%, для некоторых стратегий соотношение увеличивается в два раза. 


Апдейт

Для примера equity-trading я рассмотрю трендовую стратегию на сбербанк.
Входные условия — только шорт, 100 контрактов фиксированный лот, без пирамидинга. С лонгом все понятно, последние пару лет стратегия зарабатывает без значительных просадок. 
Эквити с фиксированным лотом, 100 контратктов.
Управление капиталом портфеля алгоритмических стратегий.



( Читать дальше )

Код робота на LUA для QUIK

В двух словах: робот анализирует спот, выставляет лимитные и стоп-лимитные заявки по фьючерсу. Делает пересчет сигналов по выбранному тайм-фрейму, снятие выставленных заявок, запись в файл текущего состояния, ведение логов, сообщения, запрос текущей позиции и пр. Из робота удалена алгоритмика вычисления сигнала и в текущем виде скрипт будет иметь сигнал на покупку на каждом баре.

Предназначается для новичков в алготрейдинге, что-то типа болванки.

Важно: выставление заявок я закомментировал, поэтому можете смело запускать этот скрит, он не натворит ужаса по счету.

require"QL"

log = "sbrf.log"
seccode = "SRM6"
lots_in_trade = 80
accnt = ""
better = -5
chart = "sberbankxxx"
is_run = true
prev_datetime = {}
len = 100
basis = 9
k_bal = {0,1,2,3}
sell = false
buy = false
id = 0
first = true

function trade_signal(shift)
        number_of_candles = getNumCandles(chart)
        bars_temp,res,legend = getCandlesByIndex(chart,0,number_of_candles-2*len-shift,2*len)
        bars={}

        i=len
        j=2*len
        while i>=1 do
                if bars_temp[j-1].datetime.hour>=10 then
                        sk=true
                        if bars_temp[j-1].datetime.hour==18 and bars_temp[j-1].datetime.min==45 then
                                sk=false
                        end
                        if sk then
                                bars[i]=bars_temp[j-1]
                                i=i-1
                        end
                end
                j=j-1
        end

        t = len+1

        do_sell = false
        do_buy = true

        value = 0
        if do_sell then value = 1 end
        if do_buy then value = -1 end
        toLog(log,"value="..value.." on candle: "..bars[len].datetime.year.."-"..bars[len].datetime.month.."-"..bars[len].datetime.day.." "..bars[len].datetime.hour..":"..bars[len].datetime.min.."   O="..bars[len].open.." H="..bars[len].high.." L="..bars[len].low.." C="..bars[len].close.." V="..bars[len].volume)
        return value
end

function mysplit(inputstr, sep)
        if sep == nil then
                sep = "%s"
        end
        local t={} ; i=1
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                t[i] = str
                i = i + 1
        end
        return t
end

function OnInit(path)
        log=getScriptPath()..'\\'..log
        toLog(log,"==========OnInit: START")
        toLog(log,"==========OnInit: FINISH")
end

function OnStop()
        is_run = false
        toLog(log,"==========OnStop: script finished manually")
end

function CheckBit(flags, bit)
   -- Проверяет, что переданные аргументы являются числами
   if type(flags) ~= "number" then error("Ошибка!!! Checkbit: 1-й аргумент не число!"); end;
   if type(bit) ~= "number" then error("Ошибка!!! Checkbit: 2-й аргумент не число!"); end;
   local RevBitsStr  = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags)
   local Fmod = 0; -- Остаток от деления
   local Go = true; -- Флаг работы цикла
   while Go do
      Fmod = math.fmod(flags, 2); -- Остаток от деления
      flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления
      RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления
      if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл
   end;
   -- Возвращает значение бита
   local Result = RevBitsStr :sub(bit+1,bit+1);
   if Result == "0" then return 0;
   elseif Result == "1" then return 1;
   else return nil;
   end;
end;

function killorders(ccode,scode)
    for i=0,getNumberOf("orders")-1,1 do
        local t=getItem("orders", i)
        if t ~= nil and type(t) == "table" then
            if( t.seccode == scode and CheckBit(t.flags, 0) == 1) then
                local transaction={
                    ["TRANS_ID"]=tostring(math.random(2000000000)),
                    ["ACTION"]="KILL_ORDER",
                    ["CLASSCODE"]=ccode,
                    ["SECCODE"]=scode,
                                        ["ACCOUNT"] = accnt,
                    ["ORDER_KEY"]=tostring(t.ordernum),
                }
                                res=sendTransaction(transaction)
            end
        end
    end
end

function killstoporders(ccode,scode)
    for i=0,getNumberOf("stop_orders")-1,1 do
        local t=getItem("stop_orders", i)
        if t ~= nil and type(t) == "table" then
            if( t.seccode == scode and CheckBit(t.flags, 0) == 1) then
                local transaction={
                    ["TRANS_ID"]=tostring(math.random(2000000000)),
                    ["ACTION"]="KILL_STOP_ORDER",
                    ["CLASSCODE"]=ccode,
                    ["SECCODE"]=scode,
                                        ["ACCOUNT"] = accnt,
                    ["STOP_ORDER_KEY"]=tostring(t.ordernum),
                }
                                res=sendTransaction(transaction)
            end
        end
    end
end


function main()
        toLog(log,"==========main: START")
        while is_run do
                if isConnected() == 1 then
                        ss = getInfoParam("SERVERTIME")
                        if string.len(ss) >= 5 then
                                hh = mysplit(ss,":")
                                str=hh[1]..hh[2]
                                h = tonumber(str)
                                if (h>=1000 and h<1400) or (h>=1405 and h<1845) or (h>=1905 and h<2350) then
                                        if first then
                                                for ti = 50,2,-1 do     trade_signal(ti) end
                                                if buy and not sell then message(seccode.." Current state: green and buy",1) end
                                                if sell and not buy then message(seccode.." Current state: red and sell",1) end
                                                if buy and sell then message(seccode.." ERROR: green and red",1) end
                                                if not buy and not sell then message(seccode.." WARNING: nothing",1) end
                                                first = false
                                        end
                                        prev_candle = getPrevCandle(chart,0)
                                        if not isEqual(prev_candle.datetime,prev_datetime) then
                                                current_value = trade_signal(1)

                                                if current_value ~= 0 then
                                                        optn = "B"
                                                        if current_value==1 then optn = "S" end
                                                        curvol=0
                                                        no=getNumberOf("FUTURES_CLIENT_HOLDING")
                                                        if no>0 then
                                                                for i=0,no-1,1 do
                                                                        im=getItem("FUTURES_CLIENT_HOLDING", i)
                                                                        if im.sec_code==seccode then
                                                                        curvol=im.totalnet
                                                                        end
                                                                end
                                                        end
                                                        trvol = -current_value*lots_in_trade-curvol
                                                        if trvol ~= 0 then
                                                                killorders("SPBFUT",seccode)
                                                                killstoporders("SPBFUT",seccode)
                                                                f = io.open(getScriptPath().."\\sbrf2_pos.txt","r")
                                                                sbrf2_pos=f:read("*n")
                                                                f:close()
                                                                f = io.open(getScriptPath().."\\sbrf3_pos.txt","r")
                                                                sbrf3_pos=f:read("*n")
                                                                f:close()
                                                                pr,n,l = getCandlesByIndex ("futsber", 0, getNumCandles("futsber")-1, 1)
                                                                local trans =
                                                                {
                                                                        ["ACTION"] = "NEW_ORDER",
                                                                        ["CLASSCODE"] = "SPBFUT",
                                                                        ["SECCODE"] = seccode,
                                                                        ["ACCOUNT"] = accnt,
                                                                        ["OPERATION"] = optn,
                                                                        ["PRICE"] = toPrice(seccode,pr[0].close+current_value*better),
                                                                        ["QUANTITY"] = tostring(math.abs(curvol-sbrf2_pos-sbrf3_pos)),
                                                                        ["TRANS_ID"] = tostring(getTradeDate().month*100+getTradeDate().day+id)
                                                                }
                                                                id = id+1
                                                                --res = sendTransaction(trans)
                                                                message(seccode.." Send : " .. res, 2)
                                                                toLog(log,"Send: ".. res)
                                                                for btr=0,200,5 do
                                                                        local trans =
                                                                        {
                                                                                ["ACTION"] = "NEW_STOP_ORDER",
                                                                                ["CLASSCODE"] = "SPBFUT",
                                                                                ["SECCODE"] = seccode,
                                                                                ["ACCOUNT"] = accnt,
                                                                                ["OPERATION"] = optn,
                                                                                ["PRICE"] = toPrice(seccode,pr[0].close-current_value*btr),
                                                                                ["STOPPRICE"] = toPrice(seccode,pr[0].close-current_value*(btr+better)),
                                                                                ["QUANTITY"] = tostring(6),
                                                                                ["TRANS_ID"] = tostring(getTradeDate().month*100+getTradeDate().day+id),
                                                                                ["EXPIRY_DATE"] = "GTC"
                                                                        }
                                                                        id = id+1
                                                                        --res = sendTransaction(trans)
                                                                        message(seccode.." Send : " .. res, 2)
                                                                        toLog(log,"Send: ".. res)
                                                                end
                                                                if current_value == 1 then
                                                                        message(seccode..' RED: buy->sell',1)
                                                                        toLog(log,"RED signal")
                                                                else
                                                                        message(seccode..' GREEN: sell->buy',1)
                                                                        toLog(log,"GREEN signal")
                                                                end
                                                        else
                                                                if current_value == 1 then
                                                                        message(seccode..' RED: buy->sell',1)
                                                                        toLog(log,"RED signal, but nothing to do")
                                                                else
                                                                        message(seccode..' GREEN: sell->buy',1)
                                                                        toLog(log,"GREEN signal, but nothing to do")
                                                                end
                                                        end
                                                else
                                                        if buy and not sell then toLog(log,"Nothing to do. Current state: green and buy",1) end
                                                        if sell and not buy then toLog(log,"Nothing to do. Current state: red and sell",1) end
                                                        if buy and sell then toLog(log,"Nothing to do. ERROR: green and red",1) end
                                                        if not buy and not sell then toLog(log,"Nothing to do. WARNING: nothing",1) end
                                                end
                                                prev_datetime = prev_candle.datetime
                                        end
                                end
                        end
                end
                sleep(5*1000)
        end
        toLog(log,"==========main: FINISH")
end
  • обсудить на форуме:
  • Quik Lua

текущая стратегия на РИ

текущая стратегия на РИ
Нравится мне такая стратегия — волатильность позы отрицательная, гамма положительная, тета около нуля. Это конечно же календарь — август куплен, сентябрь продан (посредине). если будем двигаться вправо/влево примерно с такой же невысокой волатильностью как последний месяц —  то нарежем на дельте. Если пойдем резко влево, то волатильность в какой-то момент начнет расти, но за счет гаммы хорошо подпрыгнем, так что в худшем случае останемся при своих, но вместе с нарезкой на гамме при таком рынке вола может и упасть, так что будет двойной профит. 

Как создаются красивые трендовые эквити.

Самая обычная и распространенная ошибка в построении трендовых систем, это когда вы получаете сигнал в конце периода, но открываете/закрываете позицию в этом же периоде. Этот пост об этом.

Скачаем данные и создадим скользящую среднюю по месячным данным SP500

require(quantmod)
require(xts)
require(TTR)
require(PerformanceAnalytics)

getSymbols('^GSPC', src='yahoo', from = '1900-01-01')
monthlyGSPC <- Ad(GSPC)[endpoints(GSPC, on = 'months')]

movAvg <- SMA(monthlyGSPC, 10)

signal <- monthlyGSPC > movAvg
gspcRets <- Return.calculate(monthlyGSPC)
Далее построим две системы одна с ошибкой заглядывания, вторая корректная. Суть системы простая, месячная SMA с периодом 10, выше покупаем, ниже продаем.

lookahead <- signal * gspcRets
correct <- lag(signal) * gspcRets

И построим результаты систем, на обычной шкале, и на логарифмической.

compare <- na.omit(cbind(gspcRets, lookahead, correct))
colnames(compare) <- c("S&P 500", "Lookahead", "Correct")
charts.PerformanceSummary(compare)
rbind(table.AnnualizedReturns(compare), maxDrawdown(compare), CalmarRatio(compare))
logRets <- log(cumprod(1+compare))
chart.TimeSeries(logRets, legend.loc='topleft')

Как создаются красивые трендовые эквити.


( Читать дальше )

Стратегия "скальп стопов"

    • 26 февраля 2016, 15:54
    • |
    • noTrust
  • Еще

Этот эффект я назвал «скальп стопов». Он носит очень краткосрочный характер и непременно работает уже много лет. Хотя здесь дело далеко не в одних стопах. Просто в один конкретный момент происходит очень большой перекос ордеров на покупку/продажу, и цена зачастую краткосрочно улетает и дальше по направлению перекоса. Затем возвращается обратно.

Суть такая: берем уровни максимума и минимума за предыдущий час (час значит не 60 последних минут, а временной интервал с 10:00 по 11:00 и т.д.), далее ставим стоп-лимит на покупку по цене максимума и стоп-лимит на продажу по минимуму. Ордер может сработать только 1 раз в текущем часу. Кроем сразу же на открытии следующего минутного бара. Больше никаких условий.

Пример сделки:
Стратегия "скальп стопов"

Кривая доходности и параметры с 2009 по 2016 годы (сделок на гэпе первой минуты нет, вечерняя сессия также не включена). Фактор восстановления впечатляет.



( Читать дальше )

....все тэги
UPDONW
Новый дизайн