void IBClient::realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, long volume, double wap, int count) { auto dict = createDictionary(std::map<std::string, K> { { "reqId", kj(reqId) }, { "time", kj(time) }, // TODO: Convert { "open", kf(open) }, { "high", kf(high) }, { "low", kf(low) }, { "close", kf(close) }, { "volume", kj(volume) }, { "wap", kf(wap) }, { "count", ki(count) } }); receiveData("realtimeBar", dict); }
void IBClient::position(const IBString &account, const Contract &contract, int position, double avgCost) { receiveData("position", knk(4, ks((S)account.c_str()), kj(contract.conId), ki(position), kf(avgCost))); }
void IBClient::updateMktDepth(TickerId id, int position, int operation, int side, double price, int size) { receiveData("updateMktDepth", knk(6, kj(id), ki(position), ki(operation), ki(side), kf(price), ki(size))); }
TDF_API K K_DECL TDF_subscribe(K servers, K markets, K windCodes, K msgTypes, K startTime) { ::TDF_OPEN_SETTING_EXT settings = TDF::SETTINGS; std::vector<char> mkts, tiks; try { settings.nServerNum = TDF::util::setServerInfos(servers, settings.siServer); std::string const mktList = TDF::util::join(';', q::qList2String(markets)); mkts.assign(mktList.begin(), mktList.end()); mkts.push_back('\0'); settings.szMarkets = &mkts[0]; std::string const codeList = TDF::util::join(';', q::qList2String(windCodes)); tiks.assign(codeList.begin(), codeList.end()); tiks.push_back('\0'); settings.szSubScriptions = &tiks[0]; std::vector<std::string> const typeList = q::qList2String(msgTypes); settings.nTypeFlags = 0; for (auto t = typeList.cbegin(); t != typeList.cend(); ++t) { if (!t->empty()) { ::DATA_TYPE_FLAG const flag = TDF::DataTypeFlag::fromString(*t); if (flag == 0) throw *t; settings.nTypeFlags |= flag; } } settings.nTime = TDF::util::q2time(startTime); } catch (std::string const& error) { return q::error2q(error); } # ifndef NDEBUG std::cerr << ">>> TDF_OpenExt(" << settings << ')' << std::endl; # endif assert(settings.pfnMsgHandler != NULL); assert(settings.pfnSysMsgNotify != NULL); TDF::ResetMsgHandlers(); ::TDF_ERR result = TDF_ERR_UNKOWN; ::THANDLE tdf = ::TDF_OpenExt(&settings, &result); if (result == TDF_ERR_SUCCESS) { std::cerr << "<TDF> connecting as ["; for (std::size_t i = 0; i < settings.nServerNum; ++i) { std::cerr << settings.siServer[i].szUser; if (i + 1 < settings.nServerNum) std::wcerr << ';'; } std::cerr << "] (0x" << util::hexBytes(tdf) << ")..." << std::endl; static_assert(sizeof(J) >= sizeof(::THANDLE), "J is smaller than THANDLE"); return kj(reinterpret_cast<J>(tdf)); } else { return q::error2q(TDF::getError(result)); } }
void IBClient::updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation, int side, double price, int size) { receiveData("updateMktDepthL2", knk(7, kj(id), ki(position), ks((S)marketMaker.c_str()), ki(operation), ki(side), kf(price), ki(size))); }
void IBClient::execDetails(int reqId, const Contract &contract, const Execution &execution) { auto exec = createDictionary(std::map<std::string, K> { { "execId", ks((S)execution.execId.c_str()) }, { "time", kp((S)execution.time.c_str()) }, // TODO: Convert { "acctNumber", ks((S)execution.acctNumber.c_str()) }, { "exchange", ks((S)execution.exchange.c_str()) }, { "side", ks((S)execution.side.c_str()) }, { "shares", ki(execution.shares) }, { "price", kf(execution.price) }, { "permId", ki(execution.permId) }, { "clientId", kj(execution.clientId) }, { "orderId", kj(execution.orderId) }, { "liquidation", ki(execution.liquidation) }, { "cumQty", ki(execution.cumQty) }, { "avgPrice", kf(execution.avgPrice) }, { "evRule", kp((S)execution.evRule.c_str()) }, { "evMultiplier", kf(execution.evMultiplier) } }); receiveData("execDetails", knk(3, ki(reqId), kj(contract.conId), exec)); }
// Data processor (executed within q's main thread) K invokeCallback(I socket) { static_assert(sizeof(::SOCKET) == sizeof(I), "SOCKET vs I: type mismatch!"); ::SOCKET sock = socket; assert(sock != INVALID_SOCKET); // Receive (WQID, len, serialized_K) from subscription thread # define RECV_CHECK(expectedSize, errorMsg) \ if (recvd != (expectedSize)) { \ std::cerr << "<recv> " << (errorMsg) << ": " << recvd << " < " << (expectedSize) << std::endl; \ return K_NIL; \ } ::WQID qid = 0; int recvd = ::recv(sock, reinterpret_cast<char*>(&qid), sizeof(::WQID), 0); RECV_CHECK(sizeof(::WQID), "WQID incomplete"); std::size_t len = 0; recvd = ::recv(sock, reinterpret_cast<char*>(&len), sizeof(len), 0); RECV_CHECK(sizeof(len), "size incomplete"); if (len > static_cast<std::size_t>(std::numeric_limits<int>::max())) { std::cerr << "<recv> serialized data (" << len << ") > 2G" << std::endl; return K_NIL; } q::K_ptr serialized(ktn(KB, len)); std::memset(kG(serialized.get()), 0, len); recvd = ::recv(sock, reinterpret_cast<char*>(kG(serialized.get())), len, 0); RECV_CHECK(len, "data incomplete"); # undef RECV_CHECK // Deserialize K object # if KX_USE_OKX //@ref https://groups.google.com/forum/#!topic/personal-kdbplus/pjsugT7590A if (!okx(serialized.get())) { std::cerr << "<recv> bad data: [" << util::hexBytes(kG(serialized.get()), static_cast<std::size_t>(serialized->n)) << ']' << std::endl; return K_NIL; } # endif q::K_ptr result(d9(serialized.get())); // Identify the origial query and callback std::string const callback = REGISTRY[qid]; if (callback.empty()) { std::cerr << "unknown WQID: " << qid << std::endl; return K_NIL; } static_assert(std::is_same<::WQID, J>::value, "WQID data type mismatch"); q::K_ptr output(k(0, const_cast<S>(callback.c_str()), kj(qid), result.release(), K_NIL)); if (output->t == -128) { std::cerr << "<q> '" << output->s << std::endl; } return output.release(); }
TDB_API K K_DECL TDB_login(K host, K port, K username, K password) { std::string h, uid, pwd; long long p; try { h = q::q2String(host); p = q::q2Dec(port); uid = q::q2String(username); pwd = q::q2String(password); } catch (std::string const& error) { return q::error2q(error); } ::OPEN_SETTINGS settings = ::TDB::SETTINGS; std::memset(settings.szIP, '\0', _countof(settings.szIP)); std::memset(settings.szPort, '\0', _countof(settings.szPort)); std::memset(settings.szUser, '\0', _countof(settings.szUser)); std::memset(settings.szPassword, '\0', _countof(settings.szPassword)); if (h.size() >= _countof(settings.szIP)) return q::error2q("host/IP too long"); if (p >= std::pow(10, _countof(settings.szPort))) return q::error2q("port number too long"); if (uid.size() >= _countof(settings.szUser)) return q::error2q("username too long"); if (pwd.size() >= _countof(settings.szPassword)) return q::error2q("password too long"); # ifdef _MSC_VER ::strncpy_s(settings.szIP, h.c_str(), h.size()); ::strncpy_s(settings.szUser, uid.c_str(), uid.size()); ::strncpy_s(settings.szPassword, pwd.c_str(), pwd.size()); # else std::strncpy(settings.szIP, h.c_str(), _countof(settings.szIP)); std::strncpy(settings.szUser, uid.c_str(), _countof(settings.szUser)); std::strncpy(settings.szPassword, pwd.c_str(), _countof(settings.szPassword)); # endif std::snprintf(settings.szPort, _countof(settings.szPort), "%ld", p); # ifndef NDEBUG std::cerr << ">>> TDB_Open({\"" << settings.szIP << "\", \"" << settings.szPort << "\", \"" << settings.szUser << "\", \"" << settings.szPassword << "\"})" << std::endl; # endif ::TDBDefine_ResLogin result = { 0 }; ::THANDLE tdb = ::TDB_Open(&settings, &result); if (tdb) { std::cerr << "<TDB> logged in as " << uid << " (0x" << util::hexBytes(tdb) << ')' << std::endl; static_assert(sizeof(J) >= sizeof(::THANDLE), "J is smaller than THANDLE"); return kj(reinterpret_cast<J>(tdb)); } else { return q::error2q(result.szInfo); } }
void IBClient::updatePortfolio(const Contract &contract, int position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, const IBString &accountName) { auto dict = createDictionary(std::map<std::string, K> { { "contract", kj(contract.conId) }, { "position", ki(position) }, { "marketPrice", kf(marketPrice) }, { "marketValue", kf(marketValue) }, { "averageCost", kf(averageCost) }, { "unrealizedPNL", kf(unrealizedPNL) }, { "realizedPNL", kf(realizedPNL) }, { "accountName", kp((S)accountName.c_str()) } }); receiveData("updatePortfolio", dict); }
void IBClient::tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const IBString &formattedBasisPoints, double totalDividends, int holdDays, const IBString &futureExpiry, double dividendImpact, double dividendsToExpiry) { auto dict = createDictionary(std::map<std::string, K> { { "tickerId", kj(tickerId) }, { "tickType", ki(tickType) }, { "basisPoints", kf(basisPoints) }, { "formattedBasisPoints", kp((S)formattedBasisPoints.c_str()) }, { "totalDividends", kf(totalDividends) }, { "holdDays", ki(holdDays) }, { "futureExpiry", kp((S)futureExpiry.c_str()) }, { "dividendImpact", kf(dividendImpact) }, { "dividendsToExpiry", kf(dividendsToExpiry) } }); receiveData("tickEFP", dict); }
void IBClient::error(const int id, const int errorCode, const IBString errorString) { std::string type; if (1100 <= errorCode && errorCode <= 1300) { type = "system"; } else if (2100 <= errorCode && errorCode <= 2110) { type = "warning"; } else { type = "error"; } receiveData(type.c_str(), knk(3, kj(id), kj(errorCode), kp((S)errorString.c_str()))); // "Connectivity between IB and TWS has been lost" if (id == -1 && errorCode == 1100) { disconnect(); } // Exception caught while reading socket - Connection reset by peer if (id == -1 && errorCode == 509) { disconnect(); } }
void IBClient::tickOptionComputation(TickerId tickerId, TickType tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) { auto dict = createDictionary(std::map<std::string, K> { { "tickerId", kj(tickerId) }, { "tickType", ki(tickType) }, { "impliedVol", kf(impliedVol) }, { "delta", kf(delta) }, { "optPrice", kf(optPrice) }, { "pvDividend", kf(pvDividend) }, { "gamma", kf(gamma) }, { "vega", kf(vega) }, { "theta", kf(theta) }, { "undPrice", kf(undPrice) } }); receiveData("tickOptionComputation", dict); }
Z K1(zframesize){PC(x); R kj(zframe_size(VSK(x)));}
Z K3(zframesend){PC(x); PC(y); TC2(z,-KI,-KJ); IC(z); ZTK(zframe_t,f); R kj(zframe_send(&f, VSK(y), zi));}
Z K1(zframemore){PC(x); R kj(zframe_more(VSK(x)));}
ZK ptr(V*x){if(x){R kj((intptr_t)x);}else{RZ;}} // K from opaque types e.g. void*, zctx_t, etc; dual: VSK(x).
Z K2(zmsgsend){PC(x); PC(y); ZTK(zmsg_t,m); R kj(zmsg_send(&m, VSK(y)));}
Z K1(zmsgcontentsize){PC(x); R kj(zmsg_content_size(VSK(x)));}
Z K2(zmsgaddstr){PC(x); R kj(zmsg_addstr(VSK(x), ys));}
Z K2(zmsgpushstr){PC(x); R kj(zmsg_pushstr(VSK(x), ys));}
Z K1(zmsgsize){PC(x); R kj(zmsg_size(VSK(x)));}
Z K1(zsockwait){PC(x); R kj(zsock_wait(VSK(x)));}
Z K2(zmsgprepend){PC(x); PC(y); zframe_t*f=(zframe_t*)(intptr_t)yj; R kj(zmsg_prepend(VSK(x), &f));}
Z K2(zstrsend){PC(x); R kj(zstr_send(VSK(x), ys));}
Z K2(zmsgpushC){PC(x);TC(y,KC);R kj(zmsg_pushmem(VSK(x),kC(y),(size_t)y->n));}
Z K2(zstrsendm){PC(x); R kj(zstr_sendm(VSK(x), ys));}
Z K2(zmsgaddC){PC(x);TC(y,KC);R kj(zmsg_addmem(VSK(x),kC(y),(size_t)y->n));}
Z K3(zstrsendx){PC(x); R kj(zstr_sendx(VSK(x), ys, z->s, NULL));}
static int enc(K*k,lua_State *L) { switch (lua_type(L, -1)) { case LUA_TSTRING: { size_t len;const char *str = lua_tolstring(L,-1,&len);(*k)=kpn(str,len);R 1;} break; case LUA_TNUMBER: { F num = lua_tonumber(L,-1);(*k) = (num==floor(num))?kj((J)num):kf(num);R 1;} break; case LUA_TBOOLEAN: { (*k)=kb( lua_toboolean(L,-1) );R 1;} break; case LUA_TNIL: { (*k)=ktn(0,0);R 1;} break; case LUA_TTABLE: { double p; int max = 0; int items = 0; int t_integer = 0, t_number = 0, t_boolean = 0, t_other= 0; lua_pushnil(L); /* table, startkey */ while (lua_next(L, -2) != 0) { items++; /* table, key, value */ switch (lua_type(L, -1)) { case LUA_TNUMBER: t_number++; p = lua_tonumber(L,-1); t_integer += (floor(p) == p); break; case LUA_TBOOLEAN: t_boolean++; break; default: t_other++; break; /* or anything else */ }; if (lua_type(L, -2) == LUA_TNUMBER && (p = lua_tonumber(L, -2))) { /* Integer >= 1 ? */ if (floor(p) == p && p >= 1) { if (p > max) max = p; lua_pop(L, 1); continue; } } /* Must not be an array (non integer key) */ for (lua_pop(L,1); lua_next(L, -2) != 0; lua_pop(L,1)) ++items; max = 0; break; } lua_pushnil(L); if (max != items) { /* build K dictionary */ K keys = ktn(KS,items); K values = ktn(0,items); int n = 0; /* table, startkey */ while (lua_next(L, -2) != 0) { kS(keys)[n] = ss(lua_tostring(L, -2)); if(!enc(kK(values)+n,L))R 0; lua_pop(L,1); ++n; } *k = xD(keys,values); R 1; } /* build K list */ if(t_other || ((!!t_boolean)+(!!t_number)) > 1) { K a = ktn(0,items); while (lua_next(L, -2) != 0) { p = lua_tonumber(L, -2); if(!enc(kK(a)+LI(p),L))R 0; lua_pop(L, 1); } *k = a; R 1; } if(t_boolean) { K a = ktn(KB,items); while (lua_next(L, -2) != 0) { p = lua_tonumber(L, -2); kG(a)[LI(p)] = lua_toboolean(L,-1); lua_pop(L, 1); } *k = a; R 1; } if(t_number == t_integer) { K a = ktn(KJ,items); while (lua_next(L, -2) != 0) { p = lua_tonumber(L, -2); kJ(a)[LI(p)] = (int)floor(lua_tonumber(L,-1)); lua_pop(L, 1); } *k = a; R 1; } if(t_number) { K a = ktn(KF,items); while (lua_next(L, -2) != 0) { p = lua_tonumber(L, -2); kF(a)[LI(p)] = lua_tonumber(L,-1); lua_pop(L, 1); } *k = a; R 1; } *k = ktn(0,0); R 1; }; break; default: luaL_error(L, "Cannot serialise %s: %s", lua_typename(L, lua_type(L, -1)), "can't serialize type"); R 0; }; }
Z K3(device){TC2(x,-KI,-KJ); IC(x); PC(y); PC(z); R kj(zmq_device(xi, VSK(y), VSK(z)));}