Блог им. 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
--+------------------------------------------------------------------+
--| |
--+------------------------------------------------------------------+

    769 | ★7
    14 комментариев
    Низкая доходность (меньше 1% в день)
    меня устраивает вполне и 0,5% от всего депо в день.....
    и даже 0,25% тоже устраивает....
    avatar
    wistopus,  вы, батенька, истинный дауншифтер!
    avatar
    wistopus, 
    Извиняюсь, процент не от всего депозита, а от рассчитанного на робота объема, 4 лота. Начинает с 1 лота. Запускался сразу на двух, трех бумагах параллельно, на каждого по 4 лота блокировалось. при таком раскладе и получалось та копейка, в среднем. Точно не скажу сколько, контрольная цифра была 1% от блокированного объема, до нее недотягивало.
    Если депозит до 100 000р, то 0,5% можно за полчаса, в 10 утра сделать в ручную.
    Алексей Овечкин, 
    0,5% можно за полчаса, в 10 утра сделать
    можно...
    основной рывок, как правило, утром… днем провал… к вечеру половина от утреннего гэпа… (некоторые утром  деньги тока и делают… а потом весь день свободны....)…
    avatar
    истинный даун......шифтер....!

    bocha,

    Тимофей Тимофеевич строго настрого... запретил на его сайте ругаться Матом....
    avatar
    wistopus,   дык я матом и не ругаюсь.  Разговариваю!
    Для поругаться мне и обыденного лексикона в избытке хватает ))
    avatar
    А руками слабо?) Не там храаль лежит.
    avatar
    Vladimir N., 
    Руками жаба душит, как попрет так и уходить не хочешь, день просидишь, другой, третий, а после месяца скальпинга таблетки пить приходится, а то сон пропадает.
    Алексей Овечкин, Понятно, ну да, это верно. А как же средне/долгосрок? 

    avatar
    Vladimir N., 
    Туда и ушел, на часовые графики. 
    Но 10% в день, манят и зовут!
    Даже пытался статистического робота сделать для 5 минуток, но счастье не настало.
    Алексей Овечкин, у меня настало даже на минутках и вообще любом ТФ. Я не программист, хоть все пытаюсь изучать сам это дело, все вручную торгую.
    avatar
    Vladimir N., 
    Согласен, человек гибче программы.
    Но у него есть один недостаток, время его жизни ограничено, и тратить большую часть на биржу не хочется.
    Алексей Овечкин, да, гибче, но медленее. Поэтому и пытаюсь. 
    avatar
    Добрый день.
    А рабочий вариант не выкладывали? полный
    avatar

    Читайте на SMART-LAB:
    Фото
    USD/CAD: военная разрядка подкосила нефть, но поддерживает канадца
    Канадский доллар продолжил заметно укрепляться за прошедший период и достиг локальных максимумов, полностью нивелировав слабость в течение марта....
    В Accent разработали сервис для оценки влияния недвижимости на портфель инвестора
    Группа Accent запустила интерактивный инструмент для анализа инвестиционного портфеля. Сервис, доступный на сайте компании, позволяет оценить,...
    Фото
    Итоги первичных размещений ВДО и некоторых розничных выпусков на 28 апреля 2026 г.
    Следите за нашими новостями в удобном формате:  Telegram ,  Youtube ,  RuTube,   Smart-lab ,  ВКонтакте ,  Сайт
    Фото
    Какой убыток мог быть у Магнита в 2025 году?
    На этой неделе, вероятно, под занавес сезона годовых отчетов, свои результаты должен опубликовать Магнит. Что ждать и насколько все плохо?

    теги блога Алексей Овечкин

    ....все тэги



    UPDONW
    Новый дизайн