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

по

Торговая система своими руками. Часть 4. Локальная маркет-дата. Семафоры.

    • 11 сентября 2017, 14:23
    • |
    • k100
  • Еще

     Привет всем! В предыдущий раз я описал, как стратегии выставляют заявки. Сегодня будет ещё более интересная тема: получение маркет-даты. Для упрощения, под маркет-датой, буду иметь в виду тиковые данные (время, цена, объём).

     Я уже рассказывал про классы стратегий,  про то, что они используют интерфейс, который отвечает за получение маркет-даты – IMarketDataGate. Внутри себя, стратегии подписываются на событие AddTick из IMarketDataGate – т.е. на каждый тик стратегия проводит свой анализ данных, расчеты, и, при определённых условиях, выставляет заявки. Стратегии не важно, как генерируются тики – она просто реагирует на это событие. IMarketDataGate, имеет два варианта реализации. Первый – это обёрткой над COM библиотекой брокера (в моём случае – смартком). Тут всё просто – каждый день, кроме праздников и выходных, с 10 часов, магическим образом, начинают литься тики – их мне посылает система брокера. А вот для организации локальных бэктестов, нужен какой-то иной источник данных – некая имитация брокера по части генерации тиков. И тут-то и появляется наш герой – ITickGenerator.

interface ITickGenerator
{
   event EventHandler<StockTickEventArgs> OnTick;
   event Action OnEnd;
   void Start(string symbol);
}


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

система Романа Андреева: Вы тоже пробовали тестить?

Моцарт
.....
   Из Моцарта нам что-нибудь!

Старик играет арию из Дон-Жуана; Моцарт хохочет.

Сальери

И ты смеяться можешь?

Я долго пытался понять как работает система Романа Андреева. Потом доооооолго мурыжил тслаб, пока слепил скелет (не менее 2 -х лет ушло, правда не напролет).
Если входить идеально (как в табличке) -  то результаты всегда 20-70% в год, гарантированно, при очень малой просадке.
Дело в том, что на пробой — будет много потерь на ложные входы, при входе после подтверждения — по цене входа дают как назло если это пила, а если хороший тренд цена не доходит до идеального входа (это вы знаете и без меня).
У Романа есть оговорка, что перевороты внутри дня делает бот, есть ссылки на ЕМА для ботов, все это можно прочитать в блоге в разделе фак, внутри дневную часть системы я пока не вставлял, но это будет попроще, наверное...
теперь скрины тестов при переворотах по 30 мин на пробой, без прочих фильтров. Разумеется, это только интерпретация системы Романа Андреева, в том виде, как у меня получилось.

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

Справочник Lua для Quik

    • 09 сентября 2017, 22:26
    • |
    • Dzam
  • Еще

Справочник Lua для Quik

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


( Читать дальше )
  • обсудить на форуме:
  • Quik Lua

мой прогноз по неликвиду -3

Много тут пишут про психологию, про то, что нужно ставить стопы или не нужно, разбирают дедушкин метод, модельный подход… короче всякого хватает. Не буду много разглагольствовать на эту тему. Просто сделаю прогноз по акции. 
Коротко и ясно.
 ЗВЕЗДА ао  !!!
    Завтра, в первый час торгов, будет стоит около  5,15-5,30, сегодня акция стоила на закрытии 4,60
Всем успешных торгов. Готовьтесь к ЛЧИ — оно неизбежно приближается… осталось 2 недели...


Торговая система своими руками. Часть 3. Выставление заявок.

    • 05 сентября 2017, 14:48
    • |
    • k100
  • Еще

     Добрый день. В предыдущем посте были описаны базовые компоненты – классы обёртки над API брокера. Не хотелось нагружать их дополнительной логикой, поэтому оставим их как есть, и перейдём к чуть более сложному объекту. На сцене появляется IOrderManager, который отвечает за заявки и сделки по ним.

interface IOrderManager
{
   List<Order> GetOrders(string symbol, int strategyID);
   void PlaceOrder(string symbol, int strategyID, OrderAction action, OrderType type, double price, double amount, double stopPrice);
} 

     Всего два метода – выставить заявку и получить их список. Но, у реализации IOrderManager’а непростая задача – надо не просто выставлять заявки, но также хранить какая стратегия это сделала и какие прошли сделки. Получается, у OrderManager’а есть некое состояние – список заявок/сделок, поэтому этот объект относится больше к модели, чем к сервисному слою программы. Перед этим я описывал IPortfolioGate – класс-обёртка для работы с портфелем, вот у него нет состояния, он просто транслирует вызов методов внешней COM библиотеки, а вот OrderManager это некий дополнительный уровень над всем этим – у него появляются «знания» о предметной области, и именно он используется в классах стратегий.
     Также, появляются две сущности – заявка (Order) и сделка (Trade). Класс Order имеет список сделок прошедших по данной заявке.

class Order
{
   public string Symbol { get; set; }
   public OrderAction Action { get; set; }
   public double Price { get; set; }
   …
   public List<Trade> Trades { get; set; }
}


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

Робот по скользяшкам

    • 02 сентября 2017, 08:03
    • |
    • Albus
  • Еще
Написал для всех желающих робота-советника. Он автоматически анализирует множество акций по следующим индикаторам:
Мувинг с долгим периодом.
Мувинг с коротким периодом.
Робот по скользяшкам
Робот не торгует, только анализирует рынок.
В КВИКе он выглядит так:
Робот по скользяшкам

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

Торговая система своими руками. Часть 2. Базовые компоненты.

    • 01 сентября 2017, 11:36
    • |
    • k100
  • Еще

     Приветствую! В предыдущем посте была теория, теперь к делу. Кое-что буду упрощать, чтобы представить картинку в целом.

     Итак, чтобы проект не зависел от API внешней com библиотеки (SmartCom или д.р.), чтобы в коде стратегий  не использовались специфические типы, разработку я начала с обёрток над смарткомом. Я определил три базовых интерфейса: IConnectGate, IMarketDataGate и IPortfolioGate. Соответственно для подключения, для получения маркет-даты и для выставления заявок и работы с портфелем. Причём каждый из этих трёх интерфейсов мне надо было реализовать минимум дважды – для смарткома и для локального тестера.

     В случае со смарткомом, это некий адаптер-обёртка, благодаря которому, я оперирую собственными типами и не завишу от com библиотеки. Т.е. у меня есть свои типы (например, направление заявки, тайм-фрейм), которые используются в коде, а адаптер-обёртка конвертирует их в специфические, понятные внешней библиотеке. Также, желательно, чтобы у каждого объекта, в программе, была только одна обязанность, поэтому никакой дополнительной логики эти обёртки не несут.



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

Просто о сложных процентах: фьючерс «на все»

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

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

Обозначу свой капитал как G, цену соответствующего актива P, а M – величина плеча или другими словами P/M – это ГО. Например, у Si M около 17, а у Ri около 10. Очевидно, что при таком вложении «на все» у меня контрактов MG/P, а прибыль ΔG при каждом малом изменении цены на ΔP рассчитывается по формуле: ΔG= (MG/P) ΔP. Считая M постоянной, получаем дифференциальное уравнение для G(P), которое легко решается (а как именно – пусть будет ДЗ для читателя) и в результате получаем:

G/G0 = (P/P0)M.

Здесь — G0 начальный капитал, а P0 – начальная цена. Это и есть сложные проценты в действии – относительное изменение капитала равно относительному изменению цены, возведенному в немалую степень M. Так для Si при изменении цены на 10% начальный капитал увеличится в 5 раз, на 20% в 22 раза, а на 30% аж в 87 раз! 


Таблица "Портфель" в QUIKе


    Представляю таблицу для портфельных инвестиций. В квике до сих пор такого нет. Цвет строки меняется если Прибыль%<>5%. Обновление каждые 5 сек.
Таблица "Портфель" в QUIKе

Для её создания необходимо:
1. Создать файл «tablePortfolio.txt» в папке «C:\QUIK\Scripts». Если папки нет, создать её.
2. Скопировать туда код скрипта
3. Сохранить, выбрав кодировку «ANSI», иначе вместо русских букв могут быть кракозябры.
4. Сменить расширение файла с ".txt" на ".lua"
5. Запустить скрипт командой Сервисы->Lua  скрипты->Добавить (выбрать файл tablePortfolio.lua) ->Запустить

Код скрипта:
IsRun = true
class_code="TQBR"

function main()
   -- Получает доступный id для создания
   t_id = AllocTable()   
   
   -- добавить столбцы
   AddColumn(t_id, 1, "Бумага",       true, QTABLE_STRING_TYPE, 20)
   AddColumn(t_id, 2, "Кол-во",       true, QTABLE_INT_TYPE,     7)
   AddColumn(t_id, 3, "Цена покупки", true, QTABLE_DOUBLE_TYPE, 14)
   AddColumn(t_id, 4, "Цена текущая", true, QTABLE_DOUBLE_TYPE,   14)
   AddColumn(t_id, 5, "Прибыль, р",   true, QTABLE_DOUBLE_TYPE,   14)
   AddColumn(t_id, 6, "Прибыль, %",   true, QTABLE_DOUBLE_TYPE, 14)
   t = CreateWindow(t_id)

   for iRow=1, getNumberOf("depo_limits")-1, 1 do
      rowInPortfolioTable = getItem("depo_limits", iRow) -- получить текущую строку из таблицы "Лимиты по бумагам"            
      qtyBoughtLots  = tonumber(rowInPortfolioTable.currentbal)         
      limitKind = rowInPortfolioTable.limit_kind          
      if qtyBoughtLots>0 and limitKind<1 then      
         InsertRow(t_id, iRow)-- добавить новую строку вниз таблицы   
      end
   end
   local rows, columns = GetTableSize (t_id)
   InsertRow(t_id, rows+1) -- добавить новую строку вниз таблицы для "Итого"
   
   SetWindowCaption(t_id, "Портфель: прибыли и убытки    © ramirzaev@mail.ru") 

   -- исполнять цикл, пока пользователь не остановит скрипт или не закроет окно таблицы
   while IsRun do 
      if IsWindowClosed(t_id)==true then
         IsRun=false
      end

      local currentPrice=0
      local qtyBoughtLots=0
      local profitAbs = 0
      local profitPerc = 0
      local currentSecCode= ""
      local fullNameOfInstrument = ""
      local limitKind = 0
      local rowInPortfolioTable = {}    -- строка из таблицы "Лимиты по бумагам"
      local tableInstrument = {}    -- данные "Таблицы текущих торгов"
      local iRowInOutTable = 1
	  local totalInvest = 0
	  local totalPortfolio = 0
	  local totalProfit = 0
	  local totalPercent = 0

      for iRow=0, getNumberOf("depo_limits")-1, 1 do
         rowInPortfolioTable = getItem("depo_limits", iRow) -- получить текущую строку из таблицы "Лимиты по бумагам"         
         
         qtyBoughtLots  = tonumber(rowInPortfolioTable.currentbal)
         
         limitKind = rowInPortfolioTable.limit_kind 
         
         if qtyBoughtLots>0 and limitKind<1    then      -- если кол-во лотов >0 и тип лимита T0
            currentSecCode = rowInPortfolioTable.sec_code
            fullNameOfInstrument =  tostring(getParamEx(class_code, currentSecCode, "SHORTNAME").param_image or "0") --"LONGNAME"
            avgPrice       = tonumber(rowInPortfolioTable.awg_position_price)                  
            currentPrice = GetAskPrice(currentSecCode)   
            profitAbs = (currentPrice-avgPrice)*qtyBoughtLots      
            profitPerc    = 100*currentPrice/avgPrice   - 100
			
			totalInvest = totalInvest + avgPrice*qtyBoughtLots  
			totalPortfolio = totalPortfolio + currentPrice*qtyBoughtLots   
            
            SetCell(t_id, iRowInOutTable, 1, fullNameOfInstrument) -- "Бумага"
            SetCell(t_id, iRowInOutTable, 2, tostring(qtyBoughtLots)) -- "Кол-во"RemoveZero(tostring(qtyBoughtLots)))
            SetCell(t_id, iRowInOutTable, 3, tostring( math_round(avgPrice, 3) ))  -- tostring(avgPrice))   -- "Цена покупки"
            SetCell(t_id, iRowInOutTable, 4, RemoveZero(tostring(currentPrice)))   -- "Цена текущая"
            SetCell(t_id, iRowInOutTable, 5, tostring( math_round( profitAbs, 0)) ) -- "Прибыль, р"
            SetCell(t_id, iRowInOutTable, 6, tostring(math_round(profitPerc, 1)) .."%") -- "Прибыль, %"
            
            if profitPerc >5 then       -- окрашиваем
               ColourRowInGreen(iRowInOutTable)
            elseif profitPerc<-5 then 
               ColourRowInRed(iRowInOutTable)
            else 
               ColourRowInYellow(iRowInOutTable)
            end   
            iRowInOutTable = iRowInOutTable+1
         end
      end
      totalProfit = totalPortfolio - totalInvest 
      totalPercent   = 100*totalProfit/totalInvest  
	  SetCell(t_id, iRowInOutTable, 1, "Итого") 
      SetCell(t_id, iRowInOutTable, 3, tostring( math_round(totalInvest, 0) ))  
      SetCell(t_id, iRowInOutTable, 4, tostring( math_round(totalPortfolio, 0)))  
      SetCell(t_id, iRowInOutTable, 5, tostring( math_round( totalProfit, 0)) ) 
      SetCell(t_id, iRowInOutTable, 6, tostring(math_round(totalPercent, 1)) .."%") 
	  
	  if profitPerc >5 then       -- окрашиваем
               ColourRowInGreen(iRowInOutTable)
            elseif profitPerc<-5 then 
               ColourRowInRed(iRowInOutTable)
            else 
               ColourRowInYellow(iRowInOutTable)
            end   
            iRowInOutTable = iRowInOutTable+1
      sleep(5000) -- пауза 5 сек.
      end
   --message("script table portfolio finished")
end


function ColourRowInRed(num_row)
   SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(255,150,150), RGB(0,0,0), RGB(255,150,150), RGB(0,0,0))
end
function ColourRowInYellow(num_row)
   SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(255,255,200), RGB(0,0,0), RGB(255,255,200), RGB(0,0,0))
end
function ColourRowInGreen(num_row)
   SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(150,255,150), RGB(0,0,0), RGB(150,255,150), RGB(0,0,0))
end
function GetAskPrice(inp_Sec_Code )
   local ask = tostring(getParamEx(class_code, inp_Sec_Code, "OFFER").param_value or 0)
   return ask
end
-- Округляет число до указанной точности
function math_round (num, idp)
   local mult = 10^(idp or 0)
   return math.floor(num * mult + 0.5) / mult
end
-- удаление точки и нулей после нее
function RemoveZero(str)
   while (string.sub(str,-1) == "0" and str ~= "0") do
      str = string.sub(str,1,-2)
   end
   if (string.sub(str,-1) == ".") then 
      str = string.sub(str,1,-2)
   end   
   return str
end
function OnStop()
   DestroyTable(t_id)
   IsRun = false   
end
  • обсудить на форуме:
  • QUIK

Склееные фьючерсы

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

В моей практике постоянно приходится сталкиваться с торговыми стратегиями на срочном рынке.

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

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

F=N*S*(1+r1) — N*div*(1+r2),

где

N – объем фьючерсного конт­ракта (количество акций),

F – цена фьючерса;

S – спот-цена акции;

r1 – процентная ставка на срок со дня заключения сделки по фьючерсному контракту до его исполнения;

div – размер дивидендов по базовой акции;

r2 – процентная ставка на срок со дня закрытия реестра акционеров («отсечки») до исполнения фьючерсного контракта.

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



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

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