Собственно скрипт:
package.cpath = package.cpath .. ";" .. getScriptPath() .. [[\?51.dll]]
--require"QL"
require"zmq"
local json=require("dkjson")
--require"zhelpers"
is_run=false
itosend={}
postosend={}
new_postosend={}
acctosend={}
quottosend={}
candlestosend={}
tradestosend={}
orderstosend={}
stop_orderstosend={}
alltrades_tosend={}
filter_acc=''
instruments={}
accounts={}
positions={}
positions_keys={}
last50CandlesAsString = ""
last_tradedate = ''
session={}
--accounts_list=""
publisher_binding="tcp://127.0.0.1:5563"
subscriber_binding="tcp://127.0.0.1:5562"
accounts_keys={}
is_connected=false
local sfind=string.find
FUT_OPT_CLASSES="SPBFUT"
INSTRUMENT="SiH6"
local nLastNumTrade = 0
local function _bitset(flags, index)
local n = 1
n = bit.lshift(1, index)
if bit.band(flags, n) == 0 then
return false
else
return true
end
end
function onTradeDate()
local t={}
last_tradedate = getInfoParam("TRADEDATE")
local openbal = getItem("money_limits",0).openbal
--local varmargin = getItem("futures_client_holding",0).varmargin
--local positionvalue = getItem("futures_client_holding",0).positionvalue
--local total_varmargin = getItem("futures_client_holding",0).total_varmargin
t = {
sess_date = last_tradedate;
open_balance = openbal;
}
session[#session+1] = json.encode(t)
end
function OnTrade(data)
if is_run and is_connected then
tradestosend[#tradestosend+1]=json.encode(data)
end
end
function OnOrder(data)
if is_run and is_connected then
orderstosend[#orderstosend+1]=json.encode(data)
end
end
function OnStopOrder(data)
if is_run and is_connected then
stop_orderstosend[#stop_orderstosend+1]=json.encode(data)
end
end
function ds_getCandlesByIndex(ds,count)
local size=ds:Size()
local t={}
local first_candle = size - count+1
local end_candle = size
if end_candle>size then
end_candle=size
end
if first_candle < 0 then
first_candle = 0
end
--message("in func: " .. string.format("%d, %d, %d\n", first_candle, end_candle, count), 1)
local s = ""
for i=first_candle,end_candle do
j = i-first_candle
t[j]={
open=ds:O(i);
high=ds:H(i);
low=ds:L(i);
close=ds:C(i);
volume=ds:V(i);
datetime=string.format("%04d%02d%02d;%02d%02d%02d", ds:T(i).year, ds:T(i).month, ds:T(i).day, ds:T(i).hour, ds:T(i).min, ds:T(i).sec);
}
s = s .. string.format("%s;%1.2f;%1.2f;%1.2f;%1.2f;%1.2f\n", t[j].datetime, t[j].open, t[j].high, t[j].low, t[j].close, t[j].volume)
end
--message("in func: " .. string.format("%d, %d, %d\n", first_candle, end_candle, count) .. s, 1)
return s
end
function OnQuote(class, sec )
if is_run and is_connected and (class=='SPBFUT') and (sec==INSTRUMENT) then
local ql2 = getQuoteLevel2(class, sec)
quottosend[#quottosend+1]=json.encode(ql2)
end
end
function cb( index )
last50CandlesAsString = ds_getCandlesByIndex(ds1, 2500)
candlestosend[#candlestosend+1]=last50CandlesAsString
end
function OnParam(class,sec)
if is_run and is_connected and (class=='SPBFUT') and (sec==INSTRUMENT) then
--local st=os.clock()
-- or class=='OPTUX' class=='SPBOPT' or
local i=instruments[sec].Dynamic
i.LastPrice=tonumber(getParamEx(class,sec,"Last").param_value)
i.Volatility=tonumber(getParamEx(class,sec,"Volatility").param_value)
i.TheorPrice=tonumber(getParamEx(class,sec,"theorprice").param_value)
i.Bid=tonumber(getParamEx(class,sec,'BID').param_value)
i.Ask=tonumber(getParamEx(class,sec,'OFFER').param_value)
i.BidVol=tonumber(getParamEx(class,sec,'BIDDEPTH').param_value)
i.AskVol=tonumber(getParamEx(class,sec,'OFFERDEPTH').param_value)
i.MaxPrice=tonumber(getParamEx(class,sec,'pricemax').param_value)
i.MinPrice=tonumber(getParamEx(class,sec,'pricemin').param_value)
i.PriceStep=tonumber(getParamEx(class,sec,'sec_price_step').param_value)
i.TradeDate=(getParamEx(class,sec,'trade_date_code').param_value)
if class=='FUTUX' or class=='SPBFUT' then
i.SettlePrice=tonumber(getParamEx(class,sec,'settleprice').param_value)
else
-- i.SettlePrice=tonumber(getParamEx(instruments[sec].Static.BaseContractClass,static.BaseContract,'last').param_value)
end
itosend[#itosend+1]=json.encode(i)
end
end
function OnFuturesClientHolding(hold)
if is_run and is_connected and hold~=nil and (filter_acc=='' or string.find(filter_acc,hold.trdaccid)~=nil) then
--toLog(log,'New holding update')
--table.insert(acctosend,jsonhold)
local key=positions_keys[hold.trdaccid..hold.sec_code]
if key==nil then
positions[#positions+1]={
['AccountName']=hold.trdaccid,
['SecurityCode']=hold.sec_code,
['TotalNet']=hold.totalnet,
['BuyQty']=hold.openbuys,
['SellQty']=hold.opensells,
['VarMargin']=hold.varmargin
}
positions_keys[hold.trdaccid..hold.sec_code]=#positions
new_postosend[#new_postosend+1]=json.encode(positions[#positions])
else
local t=positions[key]
t.TotalNet=hold.totalnet
t.BuyQty=hold.openbuys
t.SellQty=hold.opensells
t.VarMargin=hold.varmargin
postosend[#postosend+1]=json.encode(t)
end
end
end
function OnStop()
is_run=false
--ds1:close()
--publisher:close()
--context:term()
end
function OnInitDo()
--context=zmq.init(1)
--publisher=context:socket(zmq.PUB)
--publisher:bind("tcp://127.0.0.1:5563")
local id=1
ds1 = CreateDataSource("SPBFUT", INSTRUMENT, INTERVAL_M10)
ds1:SetUpdateCallback(cb)
for cl in string.gmatch(FUT_OPT_CLASSES,"%a+") do
local sec_list=getClassSecurities(cl)
for sec in string.gmatch(sec_list,"%w+%.?%w+") do
if cl=='SPBFUT' then
instruments[sec]={}
instruments[sec].Static={}
instruments[sec].Dynamic={}
local static=instruments[sec].Static
local dynamic=instruments[sec].Dynamic
static.Class=cl
static.Code=sec
static.FullName=getParamEx(cl,sec,'LONGNAME').param_image
static.Id=id
if cl=='FUTUX' or cl=='SPBFUT' then
static.InstrumentType='Futures'
static.BaseContractClass='RTSIND'
static.BaseContract=getParamEx(cl,sec,"OPTIONBASE").param_image..'I'
else
static.InstrumentType='Option'
static.BaseContractClass=getSecurityInfo('',sec).class_code
static.BaseContract=getParamEx(cl,sec,"OPTIONBASE").param_image
end
static.OptionType=getParamEx(cl,sec,"OPTIONTYPE").param_image
static.Strike=tonumber(getParamEx(cl,sec,"STRIKE").param_value)
static.DaysToMate=getParamEx(cl,sec,"DAYS_TO_MAT_DATE").param_image
static.MaturityDate=getParamEx(cl,sec,"MAT_DATE").param_image
dynamic.LastPrice=tonumber(getParamEx(cl,sec,'last').param_value)
dynamic.Volatility=tonumber(getParamEx(cl,sec,'volatility').param_value)
dynamic.TheorPrice=tonumber(getParamEx(cl,sec,'theorprice').param_value)
if cl=='FUTUX' or cl=='SPBFUT' then
dynamic.SettlePrice=tonumber(getParamEx(cl,sec,'settleprice').param_value)
else
dynamic.SettlePrice=tonumber(getParamEx(static.BaseContractClass,static.BaseContract,'last').param_value)
end
dynamic.Bid=tonumber(getParamEx(cl,sec,'BID').param_value)
dynamic.Ask=tonumber(getParamEx(cl,sec,'OFFER').param_value)
dynamic.BidVol=tonumber(getParamEx(cl,sec,'BIDDEPTH').param_value)
dynamic.AskVol=tonumber(getParamEx(cl,sec,'OFFERDEPTH').param_value)
dynamic.MaxPrice=tonumber(getParamEx(cl,sec,'pricemax').param_value)
dynamic.MinPrice=tonumber(getParamEx(cl,sec,'pricemin').param_value)
dynamic.PriceStep=tonumber(getParamEx(cl,sec,'sec_price_step').param_value)
dynamic.TradeDate=(getParamEx(cl,sec,'trade_date_code').param_value)
dynamic.Id=id
--dynamic.MsgType='INSTRUMENT'
id=id+1
end
end
end
local sf=string.find
return true
--is_run=true
end
function OnConnected(rep,pub)
--reply:recv()
-- message('Connected',3)
if rep~=nil then
rep:send('CONNECTED')
end
for k,v in pairs(instruments) do
if v.Static~=nil then
pub:send('NEWINSTRUMENT',zmq.SNDMORE)
pub:send(json.encode(v.Static))
end
if v.Dynamic~=nil then
pub:send('INSTRUMENT',zmq.SNDMORE)
pub:send(json.encode(v.Dynamic))
end
end
for k,v in ipairs(accounts) do
pub:send('NEWACCOUNT',zmq.SNDMORE)
pub:send(json.encode(v))
end
for k,v in ipairs(positions) do
pub:send('NEWPOSITION',zmq.SNDMORE)
pub:send(json.encode(v))
end
trades={}
for i=0,getNumberOf('trades')-1 do
trades=getItem('trades',i)
pub:send('TRADES',zmq.SNDMORE)
pub:send(json.encode(trades))
end
orders={}
for i=0,getNumberOf('orders')-1 do
orders=getItem('orders',i)
pub:send('ORDERS',zmq.SNDMORE)
pub:send(json.encode(orders))
end
stop_orders={}
for i=0,getNumberOf('stop_orders')-1 do
stop_orders=getItem('stop_orders',i)
pub:send('STOP_ORDERS',zmq.SNDMORE)
pub:send(json.encode(stop_orders))
end
t={}
last_tradedate = getInfoParam("TRADEDATE")
local openbal = getItem("money_limits",0).openbal
--local varmargin = getItem("futures_client_holding",0).varmargin
--local positionvalue = getItem("futures_client_holding",0).positionvalue
--local total_varmargin = getItem("futures_client_holding",0).total_varmargin
t = {
sess_date = last_tradedate;
open_balance = openbal;
}
pub:send('SESSION',zmq.SNDMORE)
pub:send(json.encode(t))
local init_candles = ds_getCandlesByIndex(ds1, 1600)
pub:send('CANDLES',zmq.SNDMORE)
pub:send(init_candles)
pub:send('COMMON',zmq.SNDMORE)
pub:send('INITIALSYNCEND')
-- message('INITIALSYNCEND',3)
return true
end
function main()
is_run=OnInitDo()
local context=zmq.init(1)
local publisher=context:socket(zmq.PUB)
local reply=context:socket(zmq.REP)
publisher:bind(publisher_binding)
reply:bind(subscriber_binding)
while is_run do
msg=reply:recv(zmq.NOBLOCK)
if msg~=nil then
-- send info for new connections
is_connected=OnConnected(reply,publisher)
-- message('end onconnect '..tostring(is_connected),3)
end
if #itosend~=0 then
for i=1,#itosend do
local msg=table.remove(itosend,i)
if msg~=nil then
publisher:send("INSTRUMENT",zmq.SNDMORE)
res=publisher:send(msg)
end
end
--message("#"..#tosend,)2zmq
end
if #postosend~=0 then
for i=1,#postosend do
local msg=table.remove(postosend,i)
if msg~=nil then
publisher:send("POSITION",zmq.SNDMORE)
res=publisher:send(msg)
end
end
--message("#"..#tosend,2)
end
if #new_postosend~=0 then
for i=1,#new_postosend do
local msg=table.remove(new_postosend,i)
if msg~=nil then
publisher:send("NEWPOSITION",zmq.SNDMORE)
res=publisher:send(msg)
end
end
--message("#"..#tosend,2)
end
if #quottosend~=0 then
for i=1,#quottosend do
local msg=table.remove(quottosend,i)
if msg~=nil then
publisher:send("NEWQUOTES",zmq.SNDMORE)
res=publisher:send(msg)
end
end
--message("#"..#tosend,2)
end
if #candlestosend~=0 then
for i=1,#candlestosend do
local msg=table.remove(candlestosend,i)
if msg~=nil then
publisher:send("CANDLES",zmq.SNDMORE)
res=publisher:send(msg)
end
end
--message("#"..#tosend,2)
end
if #tradestosend~=0 then
for i=1,#tradestosend do
local msg=table.remove(tradestosend,i)
if msg~=nil then
publisher:send("TRADES",zmq.SNDMORE)
res=publisher:send(msg)
end
end
end
if #orderstosend~=0 then
for i=1,#orderstosend do
local msg=table.remove(orderstosend,i)
if msg~=nil then
publisher:send("ORDERS",zmq.SNDMORE)
res=publisher:send(msg)
end
end
end
if #stop_orderstosend~=0 then
for i=1,#stop_orderstosend do
local msg=table.remove(stop_orderstosend,i)
if msg~=nil then
publisher:send("STOP_ORDERS",zmq.SNDMORE)
res=publisher:send(msg)
end
end
end
sleep (500)
end
publisher:close()
reply:close()
context:term()
end