Избранное трейдера DvF
TICER = "SBER"; CLASS_CODE = "TQBR"; FilePath = getScriptPath() .. "\\export.txt";--путь к файлу save = false;--сохранять данные в файл если false нет, true да f = nil; stopped = false; t_id = nil H = -1; M = -1; VSELL = 0; VBUY = 0; CDelta = 0; CountTrans = 0; PriceTrans = 0.0; t = ""; function OnInit() CountTrans = 0; if save then f = io.open(FilePath,"w"); end CreateTable(); end function main() while not stopped do if IsWindowClosed(t_id) then stopped = true; end sleep(10); end end function CreateTable() t_id = AllocTable(); AddColumn(t_id, 0, "Время", true, QTABLE_STRING_TYPE, 10); AddColumn(t_id, 1, "BUY", true, QTABLE_INT_TYPE, 10); AddColumn(t_id, 2, "SELL", true, QTABLE_INT_TYPE, 10); AddColumn(t_id, 3, "Дельта V", true, QTABLE_INT_TYPE, 10); AddColumn(t_id, 4, "AVG Цена", true, QTABLE_DOUBLE_TYPE, 15); AddColumn(t_id, 5, "Накопленная Дельта", true, QTABLE_INT_TYPE, 15); AddColumn(t_id, 6, "Кол-во сделок", true, QTABLE_DOUBLE_TYPE, 12); tab = CreateWindow(t_id); local NAME = tostring(getParamEx(CLASS_CODE,TICER,"LONGNAME").param_image); SetWindowCaption(t_id, TICER.." ("..NAME..") Баланс покупок/продаж"); SetTableNotificationCallback(t_id, EventCallBack); end function Calc(alltrade) if bit.test(alltrade.flags, 0) then VSELL = VSELL+alltrade.qty; --Продажа else VBUY = VBUY+alltrade.qty; end CountTrans = CountTrans+1; PriceTrans = PriceTrans+alltrade.price; end function OnAllTrade(alltrade) if alltrade.sec_code == TICER then local Rows, Col = GetTableSize(t_id); if H==-1 or H~= alltrade.datetime.hour then H = alltrade.datetime.hour; M = alltrade.datetime.min; t = tostring(alltrade.datetime.hour)..":"..tostring(alltrade.datetime.min); end if M==alltrade.datetime.min then Calc(alltrade); else M=alltrade.datetime.min; InsertRow(t_id, -1); local Delta = VBUY-VSELL; Price = PriceTrans/CountTrans; SetCell(t_id, Rows, 6, tostring(CountTrans)); SetCell(t_id, Rows, 0, t); SetCell(t_id, Rows, 1, tostring(VBUY)); SetCell(t_id, Rows, 2, tostring(VSELL)); SetCell(t_id, Rows, 3, tostring(Delta)); local SEC_SCALE = tostring(getParamEx(CLASS_CODE,TICER,"SEC_SCALE").param_value); SEC_SCALE = string.format("%.0f",SEC_SCALE); SetCell(t_id, Rows, 4, string.format("%."..SEC_SCALE.."f", tostring(Price))); if Rows>=2 then local OldPrice = tonumber(GetCell(t_id,Rows-1,4).image); if OldPrice>Price then Red(Rows,4); else Green(Rows,4); end CDelta = tonumber(GetCell(t_id,Rows-1,5).image); CDelta = CDelta + Delta; else CDelta = Delta; end SetCell(t_id, Rows, 5, tostring(CDelta)); if Delta<0 then Red(Rows,3); end if Delta>0 then Green(Rows,3); end if CDelta<0 then Red(Rows,5); end if CDelta>0 then Green(Rows,5); end if save then local Str = tostring(H)..";"..tostring(M)..";"..tostring(VBUY)..";"..tostring(VSELL)..";" ..tostring(Delta)..";"..tostring(Price)..";"..tostring(CDelta); Str=Str.."\n"; SaveFile(Str); end t = tostring(alltrade.datetime.hour)..":"..tostring(alltrade.datetime.min); VBUY = 0;VSELL = 0; PriceTrans = 0; CountTrans = 0; Calc(alltrade); end end --if alltrade.sec_code == TICER then end function SaveFile(Str) if f ~= nil then f:write(Str); f:flush(); end end function Red(row,col) SetColor(t_id, row, col, RGB(255,0,0), RGB(0,0,0), RGB(255,0,0), RGB(0,0,0)); end function Yellow(row,col) SetColor(t_id, row, col, RGB(240,240,0), RGB(0,0,0), RGB(240,240,0), RGB(0,0,0)); end function Green(row,col) SetColor(t_id, row, col, RGB(0,200,0), RGB(0,0,0), RGB(0,200,0), RGB(0,0,0)); end function EventCallBack(t_id, msg, par1, par2) if msg==QTABLE_CLOSE then OnStop(); end; end function OnStop(s) if f ~= nil then f:close(); end if t_id ~= nil then DestroyTable (t_id); end; stopped = true; end
Я уже писал, что у меня сделана C++ DLL, которая получает данные из Lua и пишет их в БД SQLite. Уже писал также, что DLL под Lua делается на раз, и даже приводил коды и шаблон проекта простенькой C++ DLL. Посмотрело несколько тысяч, скачало, аж 12 человек, применят от силы двое. КПД постов, прямо скажем, оч низкий.)
В DLL реализована как связь с Lua, и будет реализована сама стратегия, вот только не решил какая из них. Повторять старые стратегии на новой для меня платформе Quik уже неинтересно, а новых моделей АТС отработано уже несколько. Все моделируется в Python. Часть стратегий не требует сложной математики, и могут быть легко перенесены непосредственно на С++. Другие непосредственно в DLL перенесены быть не могут, т.к. используют пакеты Python — всяческие регрессии и машинное обучение.
В общем, получилось, что DLL является шаблоном для любой стратегии. Все необходимые для АТС данные доступны АТС — реал-тайм данные поступают в DLL непосредственно из терминала, а необходимая история пишется DLL в БД SQLite и читается АТС из базы данных.
Рассказываю о полезных инструментах, которые используют долгосрочные инвесторы. Эти инструменты дают дополнительную информацию и помогают прогнозировать рынок.
Purchasing Managers' Index (PMI)
PMI — это индекс деловой активности, который рассчитывается на основе опроса менеджеров по закупкам из различных компаний. Ежемесячно сотрудников снабжения спрашивают про экономическую ситуацию в стране, а ответы обрабатывают специальным алгоритмом.
Затем формируется «индекс оптимизма». Если большинство менеджеров считают, что все хорошо, и экономика улучшается, то индекс растет. Если они говорят, что все плохо, то индекс падает. При этом обычно формируются два индекса — один для сферы промышленности (основной), а другой — для сферы услуг (дополнительный).
Нейтральное значение индекса составляет 50 пунктов. Значения выше говорят о росте деловой активности. Значения ниже предупреждают о падении. Если индекс опускается ниже 40 пунктов, то наступает рецессия.
PMI опережает максимумы и минимумы деловой активности на 2-6 месяцев. Рыночные экстремумы он опережает не всегда, но тоже часто. В целом, PMI хорошо подходит, чтобы прогнозировать окончания крупных кризисов и рецессий.
Индикатор удобно смотреть на площадке TradingView. Для этого нужно:
Settings={ Name="abs_over_vol", period=20, line= { { Name = "cur1", Type =TYPE_LINE, Width = 2, Color = RGB(255,0, 0) } } } --[[ описание свойств: period - период, за каротрый делается расчет назначение: построение поглащения и перехая с использованием объемов --]] function Init() y = 0 return 1 end function OnCalculate(index) sz = Size() n = Settings.period if index == 1 then y = 0 end i = index if index-n > 0 then if (C(i) < C(i-1)) and (C(i-1) > O(i-1)) and (C(i) < O(i)) and (C(i-1) - O(i-1) < O(i) - C(i)) then y = y - 1*V(i) end if (C(i) > C(i-1)) and (C(i-1) < O(i-1)) and (C(i) > O(i)) and (O(i-1) - C(i-1) < C(i) - O(i)) then y = y + 1*V(i) end if (H(i) > H(i-1)) and (L(i) > L(i-1)) then y = y + 1*V(i) end if (H(i) < H(i-1)) and (L(i) < L(i-1)) then y = y - 1*V(i) end end return y end