Блог им. AlekseyOvechkin
Нашел интересный алгоритм.
https://www.youtube.com/watch?v=inJ8zuSoJTM
Показалась Грааль.
Написал робота под квик. Счастье не наступило.
Гонял на сбере, сишки, Евро-рубль.
Низкая доходность (меньше 1% в день) и все время разворачивается на откатах, из-за чего пытается задействовать большую часть депозита. В основном 2-4 разворота за цикл, но однажды 15 раз крутанулся, торговлю я ему конечно на 6 развороте отключил (в робота зашито).
Поменял алгоритм, сделал, чтоб торговал по тренду без начальной проверке, на втором цикле, и далее. Стало по лучше, но не существенно, необходимых 2% не добрал.
Если бы не попытки задействовать весь депозит, сгодился бы для разнообразия. А так блокирует пол депозита, а доходность маленькая.
Народ, если есть у кого интересные алгоритмы пиши, обкатаем.
Код робота: LUA, под 8 квик
Здесь только основной алгоритм, в нем задействованы библиотеке работы с окном, отчетность, общение с биржей, …
Если кому интересно выложу для скачивания рабочий вариант, необходимо умение подключать внешние функции.
--[[
Робот-2021-2 — Зигзаг
]]
--+------------------------------------------------------------------+
--| Глобальные переменные |
--+------------------------------------------------------------------+
— Инструмент фьчей
ACCOUNT = '00000'; — Идентификатор счета (для фьчей, счет депо)
CLIENT_CODE = '00000'; — Код клинта, для фьчей ACCOUNT и CLIENT_CODE совпадают
CLASS_CODE = 'SPBFUT'; — Код класса (биржа) — TQBR — Акции, SPBFUT — Фьючерсы
SEC_CODE = 'EuM1'; — Код бумаги
SEC_NAME = 'Евро-рубль'; — Имя бумаги
PRICE_STEP = 1; — Шаг цены
PRICE_X = 1; — Шаг цены
QUIK_CODE = 0; — Инициализационный код терминала QUIK — НЕИСПОЛЬЗУЕТСЯ
— Имя файла отчета
vReportsName = «C:\\R\\Reports-011-»; — к имени файла добавляется дата и время. Исли файл уже существует, то запись идет в него.
— Файл отчета создается с расширением ".txt2". Читаем блокнотом или Notepad++.
--+------------------------------------------------------------------+
--| Настройки цикла |
--+------------------------------------------------------------------+
vLOTS = 1; — Количество лотов в шаге
vPROFIT = 96*PRICE_STEP; — Количество пунктов профита, после которого выходим
vPRICE_SEGMENT = 3; — Отрезок цены для анализа направления движения
--+------------------------------------------------------------------+
--| Рабочии переменные |
--+------------------------------------------------------------------+
vID = 1; — Номер следующей заявки
vIntervalID1 = 1;
vIntervalID1 = 10000;
vTrend = 0; — Тренд, направление движения: 1 — вверх, -1 — вниз
— Переменные для определения тренда
vPrice = {}; — Текущая цена, раз в секунду, из стакана, таблица из 25 ячеек, от 0 до 24
vPriceIndex = -1; — Индекс текущей ячейки vPrice
— Таблица цикла
vSTATUS = nil; — nil — Нет открытых сделок, и vTrend == 0, Таблица не активна
— 0 — Ожидание Входа в сделку —
— 1 — Вход совершен
— 7 — Выход
is_run = true; — Флаг безконечного цикла в main
vTrendFlag = 0; — Показывает направление предыдущего цикла, что бы что бы следующий цикл начинался со сделки.
--+------------------------------------------------------------------+
--| Внешние модули |
--+------------------------------------------------------------------+
package.path = «C:\\R\\Robot-2020-07\\?.lua»; — Каталог где лежат дополнительные модули. Скрипт лежит там же.
require «Reports-2020»; — Модуль печати отчета
require «Data-2020»; — Модуль Запроса данных
require «Trade-2020»; — Модуль торговых заявок
require «CrabWin-2020»; — Модуль окна
--+------------------------------------------------------------------+
--| Функция инициализации. |
--| ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK в самом начале, один раз. |
--+------------------------------------------------------------------+
function OnInit()
— —
— Открываем файл отчета
FunOpenFile();
— —
— Создаем и инициализируем окно
vTableName = «Зигзаг-02 — »… SEC_NAME;
QTable.__index = QTable;
vWinLink = QTable:new();
InitTable();
— --------------------------------------------------------------------------
end;
--+------------------------------------------------------------------+
--| Функция проверки потери связи с сервером QUIK |
--+------------------------------------------------------------------+
function OnDisconnected()
local DateTime = os.date("*t"); — таблица
FunSetMessege(«Потеря связи с сервером QUIK!», vErorrColour);
— Отчет ------------------------------------------------------------
vFileReportsStr = "->"… DateTime.day… "."… DateTime.month… "."… DateTime.year… " "… DateTime.hour… ":"… DateTime.min… ":"… DateTime.sec… " — "… os.clock()… " ";
vFileReportsStr = vFileReportsStr… «Потеря связи с сервером QUIK!»… "\n";
FunWriteFile();
message('Потеря связи с сервером QUIK!');
is_run = false
end
--+------------------------------------------------------------------+
--| Функция проверки ошибки заявки |
--+------------------------------------------------------------------+
function OnTransReply (vtrans_reply)
end
--+------------------------------------------------------------------+
--| Функция проверки таблицы сделок |
--+------------------------------------------------------------------+
function OnOrder(vOrder)
— Набор позиции
if vSTATUS ~= nil then — Таблица активна
--if vOrder.trans_id == vCycleTab.TRANS_ID and vOrder.sec_code == SEC_CODE and vOrder.uid == QUIK_CODE then — Проверка, наша ли это транзакции.
--vCycleTab.BALANCE = vOrder.balance; — Остаток
--vCycleTab.ORDER = vOrder.order_num; — Номер заявки в торговои? системе
--end
end
end
--+------------------------------------------------------------------+
--| Функция параллельной обработки. |
--+------------------------------------------------------------------+
function main()
— --------------------------------------------------------------------------
local i = 0;
local mm = 0;
local xx = 0;
local yy = 0;
local zz = 0;
local vSTATUS = nil;
local vTREND = 0;
local vOPENPRICE = 0;
local vOPENPRICE1 = 0;
local vOPENPRICE2 = 0;
local vQUANTITY = 0;
local vvProfit = 0;
local vDateTime = os.time(); — Текущая дата в секундах
— --------------------------------------------------------------------------
— Начало работы
— —
while is_run do
vDateTime = os.date("*t"); — таблица времени
if vDateTime.hour >= 7 and vDateTime.hour <= 23 then
— Запрос последней цены —
for i = 0, 10 do
xx = getParamEx(CLASS_CODE, SEC_CODE, 'LAST');
if xx.result == «1» and param_image ~= "" and param_type ~= «0» then break; end
end
if xx.result == «0» or xx.result == «0.0» or xx.param_value == 0 or xx.param_value == «0» then — Обаротка ошибки запроса
FunSetMessege(«Ошибка запроса цены покупки », vErorrColour, «Цена »… xx.param_value);
is_run = false;
else
— Цена получена
vPriceIndex = vPriceIndex + 1;
vPrice[vPriceIndex] = tonumber(xx.param_value); — Текущая цена, раз в секунду,
xx = nil;
end
— Экономия памяти
if vPriceIndex > 200 then
for i = 0, 100 do vPrice[i] = vPrice[100+i]; end
vPriceIndex = 100;
end
end — Время
--if vSTATUS ~= nil then FunSetMessege(" >> "… vSTATUS… " vPrice >> " ..vPrice[vPriceIndex]… " vTrendFlag >> "… vTrendFlag… " vOPENPRICE1 >> "… vOPENPRICE1… " vOPENPRICE2 >> "… vOPENPRICE2); end
— Начало —
if vPriceIndex >= 2 and vSTATUS == nil then — Начало цикла
vSTATUS = 0; — 0 — Вход в сделку
vTREND = 0;
vOPENPRICE = vPrice[vPriceIndex];
vOPENPRICE1 = vPrice[vPriceIndex] + vPROFIT/2; — Цена точки входа
vOPENPRICE2 = vPrice[vPriceIndex] — vPROFIT/2; — Цена точки входа
vQUANTITY = vLOTS; — Рабочий объем цикла (в лотах):
— Второй и следующии циклы идут как продолжение предыдущего цикла
if vTrendFlag == 1 then
vTREND = 1;
vOPENPRICE1 = vPrice[vPriceIndex]; — Цена точки входа
vOPENPRICE2 = vPrice[vPriceIndex] — vPROFIT; — Цена точки входа
end
if vTrendFlag == -1 then
vTREND = -1;
vOPENPRICE1 = vPrice[vPriceIndex] + vPROFIT; — Цена точки входа
vOPENPRICE2 = vPrice[vPriceIndex]; — Цена точки входа
end
FunSetMessege(«Начало: Цена: »… vOPENPRICE1… " <> "… vOPENPRICE2… " Лотов: "… vQUANTITY);
end
— Вход в сделку —
if vSTATUS ~= nil and vSTATUS == 0 and is_run == true then —
xx = 0;
if vPriceIndex > vPRICE_SEGMENT then xx = vPrice[vPriceIndex] — vPrice[vPriceIndex-vPRICE_SEGMENT]; end
if vPrice[vPriceIndex] >= vOPENPRICE1 and xx >= 0 then
vResult = FunTrans(vQUANTITY, «M», vPrice[vPriceIndex]); — Покупаем, отложенный ордер
vOPENPRICE1 = vPrice[vPriceIndex];
vOPENPRICE2 = vOPENPRICE1 — vPROFIT;
if vResult == -1 then is_run = false; end — Ошибка в функции FunTrans, конец работы
vSTATUS = 2;
end
if vPrice[vPriceIndex] <= vOPENPRICE2 and xx <= 0 then
vResult = FunTrans(-vQUANTITY, «M», vPrice[vPriceIndex]); — Покупаем, отложенный ордер
vOPENPRICE2 = vPrice[vPriceIndex];
vOPENPRICE1 = vOPENPRICE2 + vPROFIT;
if vResult == -1 then is_run = false; end — Ошибка в функции FunTrans, конец работы
vSTATUS = 2;
end
end
— Проверка входа в сделку -------------------------------------------------------------------------------------
if vSTATUS ~= nil and vSTATUS == 2 and is_run == true then —
FunChecklots();
if BuyVol ~= 0 then
vTREND = 1;
vProfit = vOPENPRICE1 + vPROFIT;
FunCloseAllOrder();
vResult = FunTrans(-vQUANTITY, «L», vProfit); — Продаем, отложенный ордер
if vResult == -1 then is_run = false; end — Ошибка в функции FunTrans, конец работы
FunSetMessege(«Вход: тренд Растущий: Цена: »… vOPENPRICE1… " Лотов: "… vQUANTITY, vUpColour);
vSTATUS = 1;
end
if SellVol ~= 0 then
vTREND = -1;
vProfit = vOPENPRICE2 — vPROFIT;
FunCloseAllOrder();
vResult = FunTrans(vQUANTITY, «L», vProfit); — Покупаем, отложенный ордер
if vResult == -1 then is_run = false; end — Ошибка в функции FunTrans, конец работы
FunSetMessege(«Вход: тренд Падающий: Цена: »… vOPENPRICE2… " Лотов: "… vQUANTITY, vDownColour);
vSTATUS = 1;
end
end
— Разворот ---------------------------------------------------------------------------------------------------
if vSTATUS ~= nil and vSTATUS == 1 and is_run == true then —
xx = 0;
if vPriceIndex > vPRICE_SEGMENT then xx = vPrice[vPriceIndex] — vPrice[vPriceIndex-vPRICE_SEGMENT]; end
if vTREND == 1 and vPrice[vPriceIndex] <= vOPENPRICE2 and xx <= 0 then
xx = 3*vQUANTITY;
vResult = FunTrans(-xx, «M», vOPENPRICE2); — Продаем, отложенный ордер
if vResult == -1 then is_run = false; end — Ошибка в функции FunTrans, конец работы
vSTATUS = 3;
end
if vTREND == -1 and vPrice[vPriceIndex] >= vOPENPRICE1 and xx >= 0 then
xx = 3*vQUANTITY;
vResult = FunTrans(xx, «M», vOPENPRICE1); — Покупаем, отложенный ордер
if vResult == -1 then is_run = false; end — Ошибка в функции FunTrans, конец работы
vSTATUS = 3;
end
end
— Проверка разворота —
if vSTATUS ~= nil and vSTATUS == 3 and is_run == true then —
FunChecklots();
if vTREND == 1 then
if SellVol ~= 0 then — Разворот
FunCloseAllOrderID();
vQUANTITY = vQUANTITY + vQUANTITY;
vTREND = -1;
FunSetMessege(«Разворот »… vOPENPRICE2);
vSTATUS = 2;
end
end
if vTREND == -1 then
if BuyVol ~= 0 then — Разворот
FunCloseAllOrderID();
vQUANTITY = vQUANTITY + vQUANTITY;
vTREND = 1;
FunSetMessege(«Разворот »… vOPENPRICE1);
vSTATUS = 2;
end
end
end
— Проверка выхода из сделки ------------------------------------------------------------------------------------------
if vSTATUS ~= nil and vSTATUS == 1 and is_run == true then —
FunChecklots();
if BuyVol == 0 and SellVol == 0 then — Профит
vSTATUS = 7;
end
end
— Выход из сделки ------------------------------------------------------------------------------------------
if vSTATUS ~= nil and vSTATUS == 7 and is_run == true then
FunChecklots();
if BuyVol == 0 and SellVol == 0 then
if vTREND == 1 then
xx = vProfit — vOPENPRICE1;
xx = xx * vQUANTITY;
FunSetMessege(«Профит = »… vProfit… " — "… vOPENPRICE1… " = "… xx);
vTrendFlag = 1;
end
if vTREND == -1 then
xx = vOPENPRICE2 — vProfit;
xx = xx * vQUANTITY;
FunSetMessege(«Профит = »… vOPENPRICE2… " — "… vProfit… " = "… xx);
vTrendFlag = -1;
end
vSTATUS = nil;
— снять все активные заявки
FunCloseAllOrderID();
end
end
—
sleep (1000); — приостановка (1000 = на 1 секунда)
--end;
end;
— --------------------------------------------------------------------------
FunCloseFile(); — Закрываем файл отчета
— --------------------------------------------------------------------------
end
--+------------------------------------------------------------------+
--| Функция при нажатии кнопки «Остановить». |
--+------------------------------------------------------------------+
function OnStop()
is_run = false
end
--+------------------------------------------------------------------+
--| |
--+------------------------------------------------------------------+
и даже 0,25% тоже устраивает....
Извиняюсь, процент не от всего депозита, а от рассчитанного на робота объема, 4 лота. Начинает с 1 лота. Запускался сразу на двух, трех бумагах параллельно, на каждого по 4 лота блокировалось. при таком раскладе и получалось та копейка, в среднем. Точно не скажу сколько, контрольная цифра была 1% от блокированного объема, до нее недотягивало.
Если депозит до 100 000р, то 0,5% можно за полчаса, в 10 утра сделать в ручную.
основной рывок, как правило, утром… днем провал… к вечеру половина от утреннего гэпа… (некоторые утром деньги тока и делают… а потом весь день свободны....)…
bocha,
Тимофей Тимофеевич строго настрого... запретил на его сайте ругаться Матом....
Для поругаться мне и обыденного лексикона в избытке хватает ))
Руками жаба душит, как попрет так и уходить не хочешь, день просидишь, другой, третий, а после месяца скальпинга таблетки пить приходится, а то сон пропадает.
Туда и ушел, на часовые графики.
Но 10% в день, манят и зовут!
Даже пытался статистического робота сделать для 5 минуток, но счастье не настало.
Согласен, человек гибче программы.
Но у него есть один недостаток, время его жизни ограничено, и тратить большую часть на биржу не хочется.
А рабочий вариант не выкладывали? полный