Это мой первый робот.
Суть стратегии заключается в мониторинге текущей цены по выбранному инструменту и при значительном изменении цены в противоположном направлении, при подъёме или падении осуществляется ввод заявки на покупку или продажу соответственно.
Код ещё «сырой». Кому не сложно прошу выявить ошибки и предложить советы, рекомендации по оптимизации кода.
Отправка транзакций заменена на сообщения для отладки алгоритма без последствий для счёта.
На данном этапе условия для покупки и продажи не корректны, так как покупает и продаёт с не всегда указанным local Procent, уже голову себе сломал как это исправить.
Интересуют следующие вопросы:
1)Как сделать, чтобы не покупал пока есть открытая позиция?
2)Если возможно, как рассчитать издержки комиссий, чтобы при вычитании их не быть в минусе?
3)Правильная ли структура кода?
CLASSCODE="TQBR" SECCODE="YNDX" QUANTITY="1" tB = { ["CLASSCODE"]=CLASSCODE, ["SECCODE"]=SECCODE, ["ACTION"]="NEW_ORDER", ["ACCOUNT"]="СЧЕТ", ["CLIENT_CODE"]="КОД КЛИЕНТА", ["TYPE"]="M", ["OPERATION"]="B", ["QUANTITY"]=QUANTITY, ["PRICE"]="0", ["TRANS_ID"]="1" } tS = { ["CLASSCODE"]=CLASSCODE, ["SECCODE"]=SECCODE, ["ACTION"]="NEW_ORDER", ["ACCOUNT"]="СЧЕТ", ["CLIENT_CODE"]="КОД КЛИЕНТА", ["TYPE"]="M", ["OPERATION"]="S", ["QUANTITY"]=QUANTITY, ["PRICE"]="0", ["TRANS_ID"]="1" } run=true function main() local Price="0" local Procent=0.005 while run do --Получение текущей цены по инструменту local lastPriceT = getParamEx(CLASSCODE, SECCODE, "LAST");--Обращение к ячейке таблицы с ценой local lastPrice = tonumber(lastPriceT.param_value);--Значение текущей цены --Текущая цена получена в переменной - "lastPrice" ---------------------------------------------------- --Преобразование Price в строчное значение Price=tonumber(Price) if Price==0 then Price=lastPrice --Если Price=0, то к Price присваивается lastPrice end Proc=(lastPrice-Price)/Price*100 --Процент изменения в переменной Proc ---------------------------------------------------- --Покупка if Price < lastPrice then Price = lastPrice --Если Price больше lastPrice то, к Price присваивается lastPrice elseif Proc>-Procent then message("Произведена покупка по цене="..tostring(lastPrice)) --sendTransaction(tB)-- --Иначе, если Proc>-0.005 то отправляется заявка на покупку --Покупка произведена ---------------------------------------------------- end --Продажа if Price > lastPrice then Price = lastPrice elseif Proc>Procent then message("Произведена продажа по цене="..tostring(lastPrice)) --Продажа произведена end sleep(5000) --Прерывание скрипта на 5 секунд end end function OnStop() run=false end
-- -- Выполнение действий с массивами. -- local pairs = pairs local type = type module(...) --- Создать копию массива (таблицы) -- @return копию массива (таблицы) function copy(array) local copy_array = {} if type(array) ~= "table" then return array end for k, v in pairs(array) do if type(v) == "table" then copy_array[k] = copy(v) else copy_array[k] = v end end return copy_array end --- Узнать, начинается ли индексация в массиве с нуля или с единицы. -- @return 0 или 1 function base(array) if array[0] ~= nil then return 0 else return 1 end end --- Вычислить число элементов в массиве. -- @return число элементов в массиве function size(array) local n = 0 for _, _ in pairs(array) do n = n + 1 end return n end --- Проверить пустой или нет массив. -- @return true/false function isEmpty(array) for _, _ in pairs(array) do return false end return true end --- Получить первый индекс массива, где ничего не записано. Поиск начинается с 1. -- @return первый индекс массива, где ничего не записано function firstEmptyIndex(array) local i = 1 while array[i] ~= nil do i = i + 1 end return i end
— Складывает Value графиков GraphId1 и GraphId2
— При запуске на загрузке Quik'а работает код предыдущей загрузки
— с последними свойствами, полученными из кода или интерактивно.
— При запуске старые бары графика данных сканируются дважды,
— только если есть подключение к серверу.
— При смене тайм-фрейма старые бары сканируются только единожды.
— При загрузке Quik'а первый скан до подключения к серверу.
CandlesOK = true
Settings = { — После смены тайм-фрейма нужно интерактивное подтверждение
Name = "_Add"
,GraphId1 = «Tag-1» — Перезадать оба после первой загрузки.
,GraphId2 = «Tag-2» — Сохраняются при последующих запусках.
,Factor1 = 1 — Для GraphId1
,Factor2 = 1 — Для GraphId2
,Base1 = 0 — Для GraphId1
,Base2 = 0 — Для GraphId2
,Value = «close»
,line = { — Исчезает прогррамный доступ после 1-го интерактивного изменения
{Name = «close»
,Color = RGB(255,255,0) — Жёлтый
,Type = TYPE_HISTOGRAM — POINT, LINE, DASH, DOT, HISTOGRAM,
,Width = 2} — TRIANGLE_UP, TRIANGLE_DOWN.
}
}
function Init()
local s = «Indicator _Add:»
if 0 == getNumCandles (Settings.GraphId1) then
CandlesOK = false
s = s .."\n invalid GraphId1"
end
if 0 == getNumCandles (Settings.GraphId2) then
CandlesOK = false
s = s .."\n invalid GraphId2"
end
if not CandlesOK then message (s) end
return #Settings.line
end — Init()
function OnCalculate (index)
if index == 1 then
CandlesOK = true
if 0 == getNumCandles (Settings.GraphId1) or
0 == getNumCandles (Settings.GraphId2) then
CandlesOK = false
end
--[[message («Settings.Value »… tostring (Settings.Value)
.."\nSettings.line "… tostring (Settings.line)
.."\nCandlesOK "… tostring (CandlesOK))--]]
if Settings.Value ~= «open» and Settings.Value ~= «high» and
Settings.Value ~= «low» and Settings.Value ~= «close» then
Settings.Value = «close»
message («Indicator _Add: Value must be open/high/low/close»)
end
end
if not CandlesOK then return nil end
local candle1 = (getCandlesByIndex (Settings.GraphId1, 0, index-1, 1))[0]
local candle2 = (getCandlesByIndex (Settings.GraphId2, 0, index-1, 1))[0]
local val1 = candle1[Settings.Value]
local val2 = candle2[Settings.Value]
— Результат return res == 0 and nil or res всегда 0 при res == 0
if val1 == 0 or val2 == 0 then return nil end
return (val1 + Settings.Base1) * Settings.Factor1
+ (val2 + Settings.Base2) * Settings.Factor2
end — OnCalculate()
за последние 15 лет было два серьезных пролива акций: 2008 и 2014
в 2008 был великий исход инвесторов с рынка акций, фактически это было обнуление рынка.
логично предположить, что новое дно не может быть сильно ниже предыдущего за счет обесценения рублей.
на случай очередного пролива у меня припасен скрипт- Светофор.
суть скрипта- отслеживать дистанцию до дна, которое представляет собой лои 2008 года+накопленная инфляция.
как пользоваться скриптом:
1. укажите инфляцию с 2008 года (накопленная инфляция 2009-2019= 107.8%)
2. добавьте нужные тикеры по аналогии с предыдущими.
подсветка строк:
зеленым- цена ниже уровня инфляции
желтым — до дна менее 50%
красным — до дна более 80%
сортировка колонок по ctrl+клик
что должно получиться:
пролив 2014 года: