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 и читается АТС из базы данных.
Не далее как вчера опубликовал топик "Смена x86 Quik 7.27.2.1 на x64 Quik 8.4.1.6. Пляски вокруг DLL", где кратко рассказывалось как перекомпилировать проект С++ с платформы х86 на х64. Надеюсь, что у вас все уже получилось или получится.
Но я «крутой» программист, и, естественно, у меня вначале вообще ничего и никак не получалось. А так как проект большой, да еще и непонятно в чем дело, а своими экспериментами я могу вообще все испортить, то решил сделать маленькую простенькую DLL LuaProba.dll, на ней отработать переход на х64, и потом перенести это в большой проект.
Привожу код С++ DLL целиком:
// LuaProba.cpp: определяет экспортированные функции для приложения DLL.
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
//=== Необходимые для Lua константы ============================================================================//
#define LUA_LIB
#define LUA_BUILD_AS_DLL
//=== Заголовочные файлы LUA ===================================================================================//
extern "C" {
#include "Lua\lua.h"
#include "Lua/lauxlib.h"
}
static int forLua_TestFunc(lua_State *L) // Возвращает заданный текст
{
const char *cc = "Привет из C/C++ и от меня 2 раза"; //str.c_str();
lua_pushstring(L, cc);
return(1);
}
//= == Регистрация реализованных в dll функций, чтобы они стали "видимы" для Lua == == == == == == == == == == == == == == == ==//
static struct luaL_reg ls_lib[] =
{
{ "TestFunc", forLua_TestFunc },
{ NULL, NULL }
};
//=== Регистрация названия библиотеки, видимого в скрипте Lua ==================================================//
extern "C" LUALIB_API int luaopen_LuaProba(lua_State *L)
{
luaL_openlib(L, "LuaProba", ls_lib, 0);
return 0;
}
Весь проект DLL для VS 2015 можно скачать по ссылке - Признаться уже достал этот 32-битный Quik 7. Работать стало почти невозможно, начал подвисать практически на пустом месте. А если повесить на Quik Lua, а к Lua прицепить DLL, то вообще все эпизодически вставало. DLL-ки, вообще-то, многопоточные и освобождают вызывающие потоки (события) Lua практически за миллисекунды, но если таких событий много Quik встает. Хотя, он и без Lua и DLL тоже регулярно встает.)
Были и другие причины ухода от 32-бит Quik, но это уже связано с брокером и другими факторами.
Итак, новый брокер — новый 64-битный Quik 8.4.1.6. Наконец сбылась мечта идиота!
Что можно сказать, — х64 Quik работает гораздо лучше, все равно временами немного подвисает, но, вроде, некритично. После логин-пароля, прежде чем работать надо подождать, — потоки обезличенных сделок начинают работать только через 3-4 минуты после старта. В общем, с этим все более-менее ОК.
Следующий этап — надо переводить весь подключаемый к Quik софт с х86 на х64, и если есть исходники, то никаких проблем не должно появиться. Если вы не используете в своем софте каких либо дополнительных DLL, то все должно ограничиваться двумя действиями.
1. Меняете в проекте С++ в разделе Файлы ресурсов 32-битную версию файла Lua5.1.lib на 64-битную версию Lua5.1.lib,
2. Выставляете в свой свойствах проекта компиляцию в x64. Можно даже так: