выкладываю модуль расчета индикаторов EMA написал очень давно, результаты должны быть как в квике
Код
local modname = ...
--автор Николай Камынин kamnik@mail.ru www.kamynin.ru
local M = {}
_G[modname] = M
package.loaded[modname] = M
local _G=_G -- глобальная таблица
setfenv(1, M)
function EMAt(y,x,m,i,n) --x- таблица
if m>=i then local s=0; for j=0,i-1 do s=s+x[i-j] end y[i]=s/i;
else if n==nil then y[i]=(y[i-1]*(m-1)+2*x[i])/(m+1); else y[i]=y[i-1] -(x[i-m] -x[i])/m; end
end
end
function EMAf(y,x,m,i,n) --x- функция
if m>=i then local s=0; for j=0,i-1 do s=s+x(i-j) end y[i]=s/i;
else if n==nil then y[i]=(y[i-1]*(m-1)+2*x(i))/(m+1); else y[i]=y[i-1]-(x(i-m)-x(i))/m; end
end
end
function sEMA(y,x,m,i)
local s=y;
if m>=i then s=((m-1)*s+x)/m; else s=(s*(m-1)+2*x)/(m+1); end
return s;
end --скользящее среднее x период m n если не задано то ехпонента или простое сглаживание
Для справки: Реализовал открытие источников без графиков для индикаторов. ------------------- алгоритм следующий: 1) сделал библиотеку для запуска функций любого скрипта из других скриптов 2) Написал скрипт, который отвечает за открытие источников и находится в спящем потоке. 3) Если индикатору или скрипту нужны данные по истории, то он обращается за данными к спящему скрипту, который возвращает индикатору требуемые данные. --------------------
Поясню еще раз. ----------------------- 1) Железо можно взять любое, лишь бы памяти не менее 2 Гб. На этом сервере у Вас 1.5 а пик более 1.5 т е бывает выгрузка на диск - это плохо. Поэтому памяти не менее 2. -------------------------- 2) сейчас у Вас квик у брокера в дата центре. сделайте в работающем КВИКЕ во 10:00, 12:00 и 21:00 информационное окно в расширенном варианте и покажите, тогда можно будет сказать конкретно на сколько хуже.
для начала читаем документацию: OnOrder Функция вызывается терминалом QUIK при получении новой заявки или при изменении параметров существующей заявки. Черным по белому написано: придет onOrder, так как произошло изменение позиции, т е изменились параметры выставленной заявки. Т е у заявки на бирже изменились параметры. Новая не выставлялась.
Андрей Мурга написал: Ви не поняли,Смотрите if aaa>bbb then buy end if aaa<bbb then закрить бай и открить селл,Как ето записать кодом? тоесть банальний реверс просто увиличить контракт не поможет робот потом запутается
if aaa<bbb then sell end ---------------------------------------- если продать столько же сколько в позиции, то она закроется, если продать больше, чем есть (если бумага маржируемая), то откроется short.
На указанном железе будет плохо. Если хотите очень хорошо, то робот надо ставить на удаленном выделенном железном сервере, в крайнем случае виртуальном, возможно как сейчас у Вас.
Вячеслав, Все что я написал - есть правда. Но причину ошибки я указал неверно. Вы тоже неверно указали причину ошибки. ------------------- Ошибка в том, что переменная order не содержит элемента order_num Поэтому вызов функции onOrder с параметрами или без не спасает от этой ошибки.
программа на луа делает один цикл купить-продать, программу скачал с интернета. работает. или сам переделал. она купила или продала по индикатору и встала.
еще надо (я отслеживаю) заявки, которые выставляет человек, от заявок робота; заявки, которые являются стопами от заявок которые являются условными для открытия позиции. это до кучи
--shares -- список инструментов local oldt_si,oldt_eu,flag=0,0,0; local ds={}; function main() local i = 1 for sec,v in pairs(shares) do local t=ds[i] if t==false then t,er= CreateDataSource(v.classcode,sec, INTERVAL_H1) if er==nil then t.clas=v.classcode; t.sec=sec; t:SetUpdateCallback(function(index) cb(index,ds[i]) end) toLog(log,"ds added i="..i.." classcode:"..v.classcode.." seccode:"..sec) ds[i]=t; else Log(log,"er="..er) end end i=i+1 end
while is_run do sleep(1000) end
end
function cb(ind,t) local Ti = t:T(ind-1) local h = Ti.hour local curhms = h*10 if flag==2 and (curhms~=oldt_si or curhms~=oldt_si) then flag=0 end if flag==2 then return end if curhms==oldt_si then flag=flag+1; oldt_si=curhms end if curhms==oldt_eu then flag=flag+1; oldt_eu=curhms end
Я уже писал как решать данную проблему. Повторю еще раз. Надо контролировать изменение лимитов. И при их изменении шевелиться с заявками. тогда будет по ... сколько раз у вас сработает OnOrder
нет, взламывать не надо. Так как мы имеем встроенную в основной поток VMLUA , следовательно все dll, которые мы подключаем к ней являются родными для процесса info.exe (терминала КВИК) ------------------------- Проблема лишь в отсутствии документации. Но хорошей документацией QUIK никогда не славился. Поэтому простейший реинженеринг софта потребуется ----------------------------- Раньше, когда требовался взлом (до времен VM Lua) подобную задачу я делал даже без СИ, на скриптовом языке Autoit. ------------------ Но, правда, не вижу практической надобности этого мероприятия.
можно делать так: -------------------------------- руками в квике 1) нажать в меню "Очистить все и начать новый сеанс"' ------------------------------- автоматом: 2) батник прописать сценарий удалить файлы 3) п 1 сделать автоматом 4) написать скрипт в батник для запуска квика и прочего. Например: у меня уже лет ...надцать квик по расписанию запускается скриптом и вводит пароли. запускает все, что еще надо, можно удалять все, что не надо .
Нельзя колбек вставлять в main попробуйте разобраться с назначением колбеков и main. Так НЕЛЬЗЯ: function main() while is_run do OnOrder() sleep(50) end end
function OnInit (path) -- инициализация функции main lenT_old=getNumberOf("trades") flag=false; end
function OnTrade(trade) lenT=getNumberOf("trades") if lenT==lenT_old then flag=true end lenT=lenT_old; if flag then --.... -- обработка колбека end end
вопрос скорее будет в том, как быстро Вы сможете отреагировать на изменение данных. Полагаю, что это время составит в среднем не менее 100 мс. Поэтому разницы нет, если Вам не имеет значения очередь берите из ТТП
можно использовать: 1) getParamEx – значения всех параметров биржевой информации из Таблицы текущих значений параметров, 2) getQuoteLevel2 – стакан по указанному классу и бумаге, 3) getItem – для таблицы all_trades
local acc="...." --- это Ваш счет депо --------------------------------- function LB(sec) local n = getNumberOf("depo_limits") for y = 0, n-1 do local trade = getItem("depo_limits", y) if trade.sec_code==sec and trade.trdaccid==acc then return trade.currentbal end end return 0 end
function OnQuote(CLASS, SEC) --..... local Limit=LB( SEC) -- получим лимит --.... end
function main() message("_________________________________") local class_code0="TQBR" local hm=#sec_code if ds~=true then ds={}; for h=1,hm do ds[n]=nil end end for h=1,hm do if ds[h]~=true then ds[h],error=CreateDataSource(class_code0,sec_code[h],INTERVAL_M1) if ds[h] then text=string.format("%-2d %-5s created",h,sec_code[h]) else text=string.format("%-2d %-5s error: %s",h,sec_code[h],error) end message(text) end end message("---------------------------------") end
function main() message("_________________________________") local class_code0="TQBR" local hm=#sec_code if ds~=true then ds={}; for h=1,hm do ds[n]=nil end end for h=1,hm do if ds[h]~=true then ds[h],error=CreateDataSource(class_code0,sec_code[h],INTERVAL_M1) if ds[h] then text=string.format("%-2d %-5s created",h,sec_code[h]) else text=string.format("%-2d %-5s error: %s",h,sec_code[h],error) end message(text) end end message("---------------------------------") sleep(1000) for h=1,hm do if ds[h] then text=string.format("%-2d %-5s size: %d",h,sec_code[h],ds[h]:Size()) if ds[h]:Close() then text=text.." closed" else text=text.." error" end else text=string.format("%-2d %-5s empty",h,sec_code[h]) end message(text) end message("=================================") end
swerg, так как текст программы не приведен, то Ваше замечание тоже не верно. Например, если обработка данных от колбека делается в main. Тогда очередной вызов колбека может изменить данные в таблице, через которую они передаются в функцию в майн. Т е теоретически указанная выше ситуация возможна. Но, повторюсь, из приведенного рассказа автора это явно не следует.