"""
事先声明, 模型源码仅作参考和交流使用, 不能直接用于实盘
"""
#include "WtHftStraDemo.h"
//#include "../Includes/IHftStraCtx.h"
#include "../WtCore/HftStraBaseCtx.h"#include "../Includes/WTSVariant.hpp"
#include "../Includes/WTSDataDef.hpp"
#include "../Includes/WTSContractInfo.hpp"#include "../Share/TimeUtils.hpp"
#include "../Share/decimal.h"extern const char* FACT_NAME;/// alpha params
#define OPEN_CLOSE_POSITION_OFFSET_TICKS 2
#define UNIT 1
#define MIDPRICE_OFFSET_TICKS 1
#define ALPHA_TICK_COUNTS 600WtHftStraDemo::WtHftStraDemo(const char* id): HftStrategy(id), _last_tick(nullptr), _last_scan_time(0), _channel_ready(false), _re_connect_ready(false), _last_mid_price(-1), _current_session_status(DEFAULT_STATUS), _code_buy_lock(false), _code_sell_lock(false), _code_short_lock(false), _code_cover_lock(false), _re_marketMaking(true), _ticks_uptr(make_unique<Ticks>())
{this->_commoditiesDocument = this->__tqz_loadJsonDocument("commodities.json");this->_sessionsDocument = this->__tqz_loadJsonDocument("sessions.json");
}WtHftStraDemo::~WtHftStraDemo() {if (_last_tick)_last_tick->release();this->_ticks_uptr.reset();this->__tqz_cancelAllOrders();
}const char* WtHftStraDemo::getName() {return "HftDemoStrategy";
}const char* WtHftStraDemo::getFactName() {return FACT_NAME;
}bool WtHftStraDemo::init(WTSVariant* cfg) {this->_code = cfg->getCString("code");this->_marketMaking_scan_interval = cfg->getUInt32("market_making_scan_interval");this->_long_order_offset = cfg->getUInt32("long_order_offset");this->_short_order_offset = cfg->getUInt32("short_order_offset");this->_offset_open_minutes = cfg->getUInt32("offset_open_minutes");this->_offset_close_minutes = cfg->getUInt32("offset_close_minutes");this->_record_hft_log = cfg->getBoolean("record_hft_log");this->_cancel_limit_counts = cfg->getUInt32("cancel_limit_counts");return true;
}void WtHftStraDemo::on_init(HftStraBaseCtx* ctx) {ctx->stra_sub_ticks(_code.c_str());this->_ctx = ctx;
}void WtHftStraDemo::on_tick(HftStraBaseCtx* ctx, const char* code, WTSTickData* newTick) {if (0 != this->_code.compare(code))return;if (!this->__isTradingTime(code))return;if (!this->_channel_ready)return;if (!this->_re_connect_ready) {if (!this->__isNewScanInterval(this->_marketMaking_scan_interval))return;/// query re_connect_ready & do reconnect.this->_re_connect_ready = this->__tqz_queryReconnectResult();if (!this->_re_connect_ready)this->tqz_doReconnect();return;}if (!this->updateTicks(*newTick))return;if (this->__isClosePositionsTime(code)) {if (this->_current_session_status != CLOSE_POSTIONS_STATUS)this->__initSessionStatus(CLOSE_POSTIONS_STATUS);if (!this->__isNewScanInterval(this->_marketMaking_scan_interval))return;if (this->__marketMakingIsLock(true))return;if (this->__closeCodeIsLock(true))return;this->tqz_closePositions(this->_code, OPEN_CLOSE_POSITION_OFFSET_TICKS);} else {if (this->_current_session_status != MARKET_MAKING_STATUS)this->__initSessionStatus(MARKET_MAKING_STATUS);if (this->__closeCodeIsLock(true))return;/// scan only new time slice.if (!this->__isNewScanInterval(this->_marketMaking_scan_interval))return;if (!this->__midPriceIsChange(MIDPRICE_OFFSET_TICKS))return;/// do market making with time slice.if (this->_re_marketMaking) {this->tqz_marketMaking(this->getLongOffsetValue(), this->getShortOffsetValue());this->_re_marketMaking = !this->_re_marketMaking;} else {this->__marketMakingIsLock(true);}}
}int32_t WtHftStraDemo::totalAlphasValue(TicksUPtr& ticksUPtr) {int32_t maAlphaValue = MaAlpha::alphaValue(ticksUPtr, 20);/*int32_t macdAlphaValue = MacdAlpha::alphaValue(ticksUPtr, 9, 12, 26);int32_t diffAlphaValue = DiffAlpha::alphaValue(ticksUPtr, 20);int32_t lastTradedQuantityAlphaValue = LastTradedQuantityAlpha::alphaValue(ticksUPtr, 20);int32_t bookAlphaValue = BookAlpha::alphaValue(ticksUPtr, 20);*//*/// output all values to terminal for test...std::cout << "-------------------------------------------" << std::endl;//std::cout << "maAlphaValue: " << maAlphaValue << std::endl;std::cout << "macdAlphaValue: " << macdAlphaValue << std::endl;//std::cout << "diffAlphaValue: " << diffAlphaValue << std::endl;std::cout << "lastTradedQuantityAlphaValue: " << lastTradedQuantityAlphaValue << std::endl;//std::cout << "bookAlphaValue: " << bookAlphaValue << std::endl;std::cout << "-------------------------------------------" << std::endl;*///return (maAlphaValue + macdAlphaValue + diffAlphaValue + lastTradedQuantityAlphaValue + bookAlphaValue);return maAlphaValue;
}uint32_t WtHftStraDemo::getLongOffsetValue() {int32_t totalAlphasValue = this->totalAlphasValue(this->_ticks_uptr);return (totalAlphasValue < 0) ? this->_long_order_offset : (this->_long_order_offset + totalAlphasValue);
}uint32_t WtHftStraDemo::getShortOffsetValue() {int32_t totalAlphasValue = this->totalAlphasValue(this->_ticks_uptr);return (totalAlphasValue < 0) ? this->_short_order_offset : (this->_short_order_offset + totalAlphasValue);
}bool WtHftStraDemo::updateTicks(WTSTickData tickData) {if (this->_ticks_uptr->size() == ALPHA_TICK_COUNTS)this->_ticks_uptr->erase(this->_ticks_uptr->begin());this->_ticks_uptr->push_back(tickData);return (this->_ticks_uptr->size() == ALPHA_TICK_COUNTS);
}void WtHftStraDemo::on_trade(HftStraBaseCtx* ctx, uint32_t localid, const char* stdCode, bool isBuy, double qty, double price, const char* userTag) {if (this->__isBelongToHft(localid)) { // localid is codethis->__tqz_receiveCodeOnlyCloseCode(localid, this->_code, qty);} else {/// this->_ctx->stra_log_text("[WtHftStraDemo::on_trade], localid(%d) is not belong to hft strategy(%s)", localid, stdCode);}this->__tqz_writeStrategyTradeLog(localid, price, qty);
}void WtHftStraDemo::on_order(HftStraBaseCtx* ctx, uint32_t localid, const char* stdCode, bool isBuy, double totalQty, double leftQty, double price, bool isCanceled, const char* userTag) { // 下单成功后调用if (0 != this->_code.compare(stdCode))return;if (!isCanceled) // order is not cancel.return;TQZOrderType orderType = this->__tqz_getOrderType(localid); // get order type first.if (this->__isBelongToHft(localid)) { // localid is inside.switch (orderType) {case BUY_TYPE: {this->__unlockBuy();this->tqz_marketMaking(this->getLongOffsetValue(), this->getShortOffsetValue());break;}case SELL_TYPE: {std::string orderComment(this->_re_connect_ready ? "code_sellOrder_reSend" : "code_sellOrder_reConnect_reSend");if (this->_code_sell_lock) // re send code sell order.this->tqz_sell(this->_code, UNIT, OPEN_CLOSE_POSITION_OFFSET_TICKS, orderComment.c_str());break;}case SHORT_TYPE: {this->__unlockShort();this->tqz_marketMaking(this->getLongOffsetValue(), this->getShortOffsetValue());break;}case COVER_TYPE: {std::string orderComment(this->_re_connect_ready ? "code_coverOrder_reSend" : "code_coverOrder_reConnect_reSend");if (this->_code_cover_lock) // re send code cover order.this->tqz_cover(this->_code, UNIT, OPEN_CLOSE_POSITION_OFFSET_TICKS, orderComment.c_str());break;}default:break;}} else {this->_ctx->stra_log_text("[WtHftStraDemo::on_order] localid is not code, stdCode: %s, localid: %d", stdCode, localid);}}void WtHftStraDemo::on_channel_ready(HftStraBaseCtx* ctx) {std::cout << "HFT_strategy code: " << this->_code << "\n\n" << std::endl;this->_tradeChange_log_filename = this->__tqz_getLogFileName(TRADE_CHANGE_TYPE);this->_channel_ready = true;this->__initSessionStatus(RE_CONNECT_STATUS);
}void WtHftStraDemo::on_entrust(uint32_t localid, bool bSuccess, const char* message, const char* userTag) {this->_ctx->stra_log_text("WtHftStraDemo::on_entrust  bSuccess: %d, message: %s\n\n", bSuccess, message);TQZOrderType orderType = this->__tqz_getOrderType(localid);switch (orderType) {case BUY_TYPE:this->__unlockBuy();break;case SELL_TYPE:this->__unlockSell();break;case SHORT_TYPE:this->__unlockShort();break;case COVER_TYPE:this->__unlockCover();break;default:break;}
}void WtHftStraDemo::on_channel_lost(HftStraBaseCtx* ctx) {this->_channel_ready = false;
}void WtHftStraDemo::on_bar(HftStraBaseCtx* ctx, const char* code, const char* period, uint32_t times, WTSBarStruct* newBar) {}void WtHftStraDemo::on_position(HftStraBaseCtx* ctx, const char* stdCode, bool isLong, double prevol, double preavail, double newvol, double newavail) {}void WtHftStraDemo::tqz_buy(const std::string code, const double lots, const int offsetTicks, const std::string orderComment) {if (!this->__isEntrustable(code))return;this->__lockBuy();// send buy order & update local var.double buyOrderPrice = this->__tqz_getLongPrice(code, offsetTicks);uint32_t buyOrderLocalid = this->_ctx->stra_enter_long(code.c_str(), buyOrderPrice, lots, orderComment.c_str());std::string currentMarketTimeString = this->__tqz_getCurrentMarketTime();std::string sendOrderTimeString = this->__tqz_getCurrentTime();this->_code_buy_order = buyOrderLocalid;this->_code_buy_orders.insert(buyOrderLocalid);if (this->_record_hft_log) // recode log or not.this->_log_message_map[buyOrderLocalid] = this->__tqz_getNewLogMessage(code,buyOrderLocalid,this->_ctx->stra_get_price(code.c_str()),buyOrderPrice,"buy_order",currentMarketTimeString,sendOrderTimeString,orderComment);
}void WtHftStraDemo::tqz_sell(const std::string code, const double lots, const int offsetTicks, const std::string orderComment) {if (!this->__isEntrustable(code))return;this->__lockSell();// send sell order & update local var.double sellOrderPrice = this->__tqz_getShortPrice(code, offsetTicks);uint32_t sellOrderLocalid = this->_ctx->stra_exit_long(code.c_str(), sellOrderPrice, lots, orderComment.c_str(), true);std::string currentMarketTimeString = this->__tqz_getCurrentMarketTime();std::string sendOrderTimeString = this->__tqz_getCurrentTime();this->_code_sell_order = sellOrderLocalid;this->_code_sell_orders.insert(sellOrderLocalid);if (this->_record_hft_log) // recode log or not.this->_log_message_map[sellOrderLocalid] = this->__tqz_getNewLogMessage(code,sellOrderLocalid,this->_ctx->stra_get_price(code.c_str()),sellOrderPrice,"sell_order",currentMarketTimeString,sendOrderTimeString,orderComment);
}void WtHftStraDemo::tqz_short(const std::string code, const double lots, const int offsetTicks, const std::string orderComment) {if (!this->__isEntrustable(code))return;this->__lockShort();double shortOrderPrice = this->__tqz_getShortPrice(code, offsetTicks);uint32_t shortOrderLocalid = this->_ctx->stra_enter_short(code.c_str(), shortOrderPrice, lots, orderComment.c_str());std::string currentMarketTimeString = this->__tqz_getCurrentMarketTime();std::string sendOrderTimeString = this->__tqz_getCurrentTime();this->_code_short_order = shortOrderLocalid;this->_code_short_orders.insert(shortOrderLocalid);if (this->_record_hft_log) // recode log or not.this->_log_message_map[shortOrderLocalid] = this->__tqz_getNewLogMessage(code,shortOrderLocalid,this->_ctx->stra_get_price(code.c_str()),shortOrderPrice,"short_order",currentMarketTimeString,sendOrderTimeString,orderComment);
}void WtHftStraDemo::tqz_cover(const std::string code, const double lots, const int offsetTicks, const std::string orderComment) {if (!this->__isEntrustable(code))return;this->__lockCover();// send cover order & update local var.double coverOrderPrice = this->__tqz_getLongPrice(code, offsetTicks);uint32_t coverOrderLocalid = this->_ctx->stra_exit_short(code.c_str(), coverOrderPrice, lots, orderComment.c_str(), true);std::string currentMarketTimeString = this->__tqz_getCurrentMarketTime();std::string sendOrderTimeString = this->__tqz_getCurrentTime();this->_code_cover_order = coverOrderLocalid;this->_code_cover_orders.insert(coverOrderLocalid);if (this->_record_hft_log) // recode log or not.this->_log_message_map[coverOrderLocalid] = this->__tqz_getNewLogMessage(code,coverOrderLocalid,this->_ctx->stra_get_price(code.c_str()),coverOrderPrice,"cover_order",currentMarketTimeString,sendOrderTimeString,orderComment);
}void WtHftStraDemo::tqz_marketMaking(const int codeLongOffsetTicks, const int codeShortOffsetTicks) {if (!this->__isMarketMakingAble())return;this->__lockBuy(); // lock market_making.this->__lockShort();std::string buyOrderComment("code_buyOrder_marketMaking");std::string shortOrderComment("code_shortOrder_marketMaking");double currentMidPrice = this->_last_mid_price; // make sure mid price of market making is same.double buyOrderPrice = this->__tqz_getMarketMakingLongPrice(this->_code.c_str(), currentMidPrice, codeLongOffsetTicks);double shortOrderPrice = this->__tqz_getMarketMakingShortPrice(this->_code.c_str(), currentMidPrice, codeShortOffsetTicks);uint32_t buyOrderLocalid = this->_ctx->stra_enter_long(this->_code.c_str(), buyOrderPrice, UNIT, buyOrderComment.c_str());uint32_t shortOrderLocalid = this->_ctx->stra_enter_short(this->_code.c_str(), shortOrderPrice, UNIT, shortOrderComment.c_str());std::string currentMarketTimeString = this->__tqz_getCurrentMarketTime();std::string sendOrderTimeString = this->__tqz_getCurrentTime();this->_code_buy_order = buyOrderLocalid;this->_code_buy_orders.insert(buyOrderLocalid);this->_code_short_order = shortOrderLocalid;this->_code_short_orders.insert(shortOrderLocalid);if (!this->_record_hft_log)return;double currentPrice = this->_ctx->stra_get_price(this->_code.c_str()); // current market price.this->_log_message_map[buyOrderLocalid] = this->__tqz_getNewLogMessage(this->_code, buyOrderLocalid, currentPrice, buyOrderPrice, "buy_order", currentMarketTimeString, sendOrderTimeString, buyOrderComment);this->_log_message_map[shortOrderLocalid] = this->__tqz_getNewLogMessage(this->_code, shortOrderLocalid, currentPrice, shortOrderPrice, "short_order", currentMarketTimeString, sendOrderTimeString, shortOrderComment);
}void WtHftStraDemo::tqz_closePositions(const std::string code, const uint32_t closePositionsOffsetTicks) {if (this->_ctx->tqz_getLongPosition(code.c_str()) > 0) { /// close long positions.this->tqz_sell(code, UNIT, closePositionsOffsetTicks, "code_sellOrder_closePositions");} else if (this->_ctx->tqz_getShortPosition(code.c_str()) > 0) { /// close short positions.this->tqz_cover(code, UNIT, closePositionsOffsetTicks, "code_coverOrder_closePositions");}
}void WtHftStraDemo::tqz_doReconnect() {if (this->__closeCodeIsLock(true))return;double currentCodeLongLots = this->_ctx->tqz_getLongPosition(this->_code.c_str());double currentCodeShortLots = this->_ctx->tqz_getShortPosition(this->_code.c_str());if (currentCodeLongLots > 0 && currentCodeLongLots >= currentCodeShortLots) { /// have long position & long lots big.this->tqz_sell(this->_code, UNIT, OPEN_CLOSE_POSITION_OFFSET_TICKS, "code_sellOrder_reConnect");} else if (currentCodeShortLots > 0 && currentCodeLongLots < currentCodeShortLots) { /// have short position & short lots big.this->tqz_cover(this->_code, UNIT, OPEN_CLOSE_POSITION_OFFSET_TICKS, "code_coverOrder_reConnect");}
}bool WtHftStraDemo::__isEntrustable(std::string code) {if (this->__isBeyondUpperlimitOrLowerlimit(code, OPEN_CLOSE_POSITION_OFFSET_TICKS, OPEN_CLOSE_POSITION_OFFSET_TICKS)) /// because cancel limit is 100.return false;if (this->_ctx->tqz_getCancelCounts(code.c_str()) > (this->_cancel_limit_counts + 10)) {this->_ctx->stra_log_text("[WtHftStraDemo::__isEntrustable], out of cancel limit counts when entrust, code: %s, 如果这条log被记录了, 说明策略执行逻辑被强行干扰了", code.c_str());return false;}return true;
}void WtHftStraDemo::__initSessionStatus(TQZSessionStatus sessionStatus) {this->_current_session_status = sessionStatus;switch (sessionStatus) {case CLOSE_POSTIONS_STATUS: {break;}case MARKET_MAKING_STATUS: { // position and order is empty in theory.this->__unlockAllOrders();this->__tqz_clearPreviousSessionCache();this->_re_marketMaking = true;break;}case RE_CONNECT_STATUS: {this->__tqz_writeCancelOrderCountsLog(this->_code);this->_re_connect_ready = this->__tqz_queryReconnectResult();}default:break;}
}bool WtHftStraDemo::__tqz_queryReconnectResult() {double codeLongLots = this->_ctx->tqz_getLongPosition(this->_code.c_str());double codeShortLots = this->_ctx->tqz_getShortPosition(this->_code.c_str());return (codeLongLots < 0.00001 && codeShortLots < 0.00001); // hold positions is empty.
}void WtHftStraDemo::__tqz_clearPreviousSessionCache() {// 缓存清理无效, 成员变量换成指针类型; (每小节初始化时清理一次)this->_code_buy_orders.erase(this->_code_buy_orders.begin(), this->_code_buy_orders.end());this->_code_sell_orders.erase(this->_code_sell_orders.begin(), this->_code_sell_orders.end());this->_code_short_orders.erase(this->_code_short_orders.begin(), this->_code_short_orders.end());this->_code_cover_orders.erase(this->_code_cover_orders.begin(), this->_code_cover_orders.end());this->_log_message_map.clear();
}void WtHftStraDemo::__tqz_cancelOrder(const std::string code, const uint32_t orderId) {if (this->_ctx->tqz_getCancelCounts(code.c_str()) > (this->_cancel_limit_counts + 15)) {this->_ctx->stra_log_text("[WtHftStraDemo::__tqz_cancelOrder] out of cancel limit counts when cancel order, code: %s, orderId: %d, 如果这条log被记录了, 说明策略执行逻辑被强行干扰了", code.c_str(), orderId);return;}this->_ctx->stra_cancel(orderId);
}void WtHftStraDemo::__tqz_cancelOrders(const std::string code, const IDSet orderIds) {for (auto& localid : orderIds)this->__tqz_cancelOrder(code, localid);
}void WtHftStraDemo::__tqz_cancelAllOrders() {this->__tqz_cancelOrders(this->_code, this->_code_buy_orders);this->__tqz_cancelOrders(this->_code, this->_code_sell_orders);this->__tqz_cancelOrders(this->_code, this->_code_short_orders);this->__tqz_cancelOrders(this->_code, this->_code_cover_orders);
}TQZOrderType WtHftStraDemo::__tqz_getOrderType(const uint32_t orderId) {TQZOrderType orderType = DEFAULT_ORDER_TYPE;if (this->_code_buy_orders.find(orderId) != std::end(this->_code_buy_orders)) {orderType = BUY_TYPE;} else if (this->_code_sell_orders.find(orderId) != std::end(this->_code_sell_orders)) {orderType = SELL_TYPE;} else if (this->_code_short_orders.find(orderId) != std::end(this->_code_short_orders)) {orderType = SHORT_TYPE;} else if (this->_code_cover_orders.find(orderId) != std::end(this->_code_cover_orders)) {orderType = COVER_TYPE;} else {orderType = NO_TYPE;}return orderType;
}double WtHftStraDemo::__tqz_getAskPrice(const std::string code) {return this->_ctx->stra_get_last_tick(code.c_str())->askprice(0);
}double WtHftStraDemo::__tqz_getBidPrice(const std::string code) {return this->_ctx->stra_get_last_tick(code.c_str())->bidprice(0);
}double WtHftStraDemo::__tqz_getCurrentMidPrice(const std::string code) {return (this->__tqz_getAskPrice(code) + this->__tqz_getBidPrice(code)) * 0.5;
}bool WtHftStraDemo::__midPriceIsChange(int offsetTicks) {double currentMidPrice = this->__tqz_getCurrentMidPrice(this->_code);double minPriceTick = this->_ctx->stra_get_comminfo(this->_code.c_str())->getPriceTick();double midPriceOffset = abs(currentMidPrice - this->_last_mid_price);bool midPriceIsChange = (midPriceOffset >= (minPriceTick * offsetTicks));if (midPriceIsChange)this->_last_mid_price = currentMidPrice;return midPriceIsChange;
}double WtHftStraDemo::__tqz_getLowerlimitPrice(const std::string code) {return this->_ctx->stra_get_last_tick(code.c_str())->lowerlimit();
}double WtHftStraDemo::__tqz_getUpperlimitPrice(const std::string code) {return this->_ctx->stra_get_last_tick(code.c_str())->upperlimit();
}double WtHftStraDemo::__tqz_getMarketMakingLongPrice(const std::string code, const double currentMidPrice, const int offsetTicks) {double minPriceTick = this->_ctx->stra_get_comminfo(code.c_str())->getPriceTick();double marketMakerLongOrderPrice = currentMidPrice - minPriceTick * offsetTicks;int longOrderPriceTicks = static_cast<int>(floor(marketMakerLongOrderPrice / minPriceTick));return longOrderPriceTicks * minPriceTick;
}double WtHftStraDemo::__tqz_getMarketMakingShortPrice(const std::string code, const double currentMidPrice, const int offsetTicks) {double minPriceTick = this->_ctx->stra_get_comminfo(code.c_str())->getPriceTick();double marketMakerShortOrderPrice = currentMidPrice + minPriceTick * offsetTicks;int shortOrderPriceTicks = static_cast<int>(ceil(marketMakerShortOrderPrice / minPriceTick));return shortOrderPriceTicks * minPriceTick;
}bool WtHftStraDemo::__isBeyondUpperlimitOrLowerlimit(const string code, const int longOrderOffsetTicks, const int shortOrderOffsetTicks) {if (this->__tqz_getLongPrice(code, longOrderOffsetTicks) >= this->__tqz_getUpperlimitPrice(code))return true;if (this->__tqz_getShortPrice(code, shortOrderOffsetTicks) <= this->__tqz_getLowerlimitPrice(code))return true;return false;
}double WtHftStraDemo::__tqz_getLongPrice(const std::string code, const int offsetTicks = 0) {WTSCommodityInfo* codeInfo = this->_ctx->stra_get_comminfo(code.c_str());double longPrice = this->__tqz_getAskPrice(code.c_str()) + codeInfo->getPriceTick() * offsetTicks;if (longPrice >= this->__tqz_getUpperlimitPrice(code))longPrice = this->__tqz_getUpperlimitPrice(code);if (longPrice <= this->__tqz_getLowerlimitPrice(code))longPrice = this->__tqz_getLowerlimitPrice(code);return longPrice;
}double WtHftStraDemo::__tqz_getShortPrice(const std::string code, const int offsetTicks = 0) {WTSCommodityInfo* codeInfo = this->_ctx->stra_get_comminfo(code.c_str());double shortPrice = this->__tqz_getBidPrice(code) - codeInfo->getPriceTick() * offsetTicks;if (shortPrice <= this->__tqz_getLowerlimitPrice(code))shortPrice = this->__tqz_getLowerlimitPrice(code);if (shortPrice >= this->__tqz_getUpperlimitPrice(code))shortPrice = this->__tqz_getUpperlimitPrice(code);return shortPrice;
}void WtHftStraDemo::__tqz_receiveCodeOnlyCloseCode(const uint32_t localid, const std::string code, const double lots) {switch (this->__tqz_getOrderType(localid)) {case BUY_TYPE: {this->__tqz_cancelOrder(code, this->_code_short_order);if (this->_ctx->tqz_getLongPosition(code.c_str()) > 0)this->tqz_sell(code, lots, OPEN_CLOSE_POSITION_OFFSET_TICKS, "code_sellOrder_onlyClose");break;} case SELL_TYPE: { // close positions time.this->__unlockBuy();this->__unlockSell();this->_re_marketMaking = true;break;} case SHORT_TYPE: {this->__tqz_cancelOrder(code, this->_code_buy_order);if (this->_ctx->tqz_getShortPosition(code.c_str()) > 0)this->tqz_cover(code, lots, OPEN_CLOSE_POSITION_OFFSET_TICKS, "code_coverOrder_onlyClose");break;} case COVER_TYPE: { // close positions time.this->__unlockShort();this->__unlockCover();this->_re_marketMaking = true;break;}}
}bool WtHftStraDemo::__isBelongToHft(const uint32_t orderId) {bool isBelongToHft = false;if (this->_code_buy_orders.find(orderId) != std::end(this->_code_buy_orders)) {isBelongToHft = true;} else if (this->_code_sell_orders.find(orderId) != std::end(this->_code_sell_orders)) {isBelongToHft = true;} else if (this->_code_short_orders.find(orderId) != std::end(this->_code_short_orders)) {isBelongToHft = true;} else if (this->_code_cover_orders.find(orderId) != std::end(this->_code_cover_orders)) {isBelongToHft = true;}return isBelongToHft;
}int WtHftStraDemo::__tqz_getCurrentHourMinute() {struct tm *newtime;time_t long_time;time(&long_time);newtime = localtime(&long_time);return newtime->tm_hour * 100 + newtime->tm_min;
}rapidjson::Document WtHftStraDemo::__tqz_loadJsonDocument(const std::string jsonPath) {char readBuffer[65536];FILE* filePoint = fopen(jsonPath.c_str(), "r");rapidjson::FileReadStream fileStream(filePoint, readBuffer, sizeof(readBuffer));rapidjson::Document document;document.ParseStream(fileStream);fclose(filePoint);return document;
}std::string WtHftStraDemo::__tqz_getSession(const std::string symbolCode) {std::vector<std::string> elements;std::stringstream stringStream(symbolCode.c_str());std::string item;int index = 0;std::string exchangeString;std::string symString;std::string symbolYearMonth;while (std::getline(stringStream, item, '.')) {elements.push_back(item);if (index == 0) {exchangeString = item;} else if (index == 1) {symString = item;} else if (index == 2) {symbolYearMonth = item;}index++;}return this->_commoditiesDocument[exchangeString.c_str()][symString.c_str()]["session"].GetString();
}bool WtHftStraDemo::__isTradingTime(const std::string code) {string sessionString = this->__tqz_getSession(code);rapidjson::Value& sections = this->_sessionsDocument[sessionString.c_str()]["sections"];bool tradeable = false;if (sections.IsArray() && !sections.Empty()) {for (auto& section : sections.GetArray()) {if (!section.IsObject()) // type of section is not object.continue;if (!(section.HasMember("from") && section.HasMember("to"))) // has no from key or to key.continue;int currentHourMinute = this->__tqz_getCurrentHourMinute();if (section["from"].GetInt() <= currentHourMinute && currentHourMinute < section["to"].GetInt()) { // is trading time.tradeable = true;}if (section["from"].GetInt() > section["to"].GetInt()) { // is night trading time.if (currentHourMinute >= section["from"].GetInt() || currentHourMinute < section["to"].GetInt()) {tradeable = true;}}}} else {throw exception("result is not array type or empty array");}return tradeable;
}bool WtHftStraDemo::__isClosePositionsTime(const std::string code) {string sessionString = this->__tqz_getSession(code);rapidjson::Value& sections = this->_sessionsDocument[sessionString.c_str()]["sections"];bool isClosePositionsTime = false;if (sections.IsArray() && !sections.Empty()) {for (auto& section : sections.GetArray()) {if (!section.IsObject()) // type of section is not object.continue;if (!(section.HasMember("from") && section.HasMember("to"))) // has no from key or to key.continue;uint32_t toHourMinute = this->__tqz_resetToHourMinute(section["to"].GetInt(), this->_offset_close_minutes);uint32_t currentHourMinute = this->__tqz_getCurrentHourMinute();if ((toHourMinute - this->_offset_close_minutes) <= currentHourMinute && currentHourMinute < toHourMinute) // is close positions time.isClosePositionsTime = true;}} else {throw exception("result is not array type or empty array");}return isClosePositionsTime;
}int WtHftStraDemo::__tqz_resetToHourMinute(int toHourMinute, const int offsetCloseMinutes = 0){int toMinute = toHourMinute % 100;int toHour = toHourMinute / 100;int offsetMinutes = offsetCloseMinutes % 60;int offsetHours = offsetCloseMinutes / 60;int newMinute = 60 + toMinute; // reset minutesint newHour = (toHour - (offsetHours % 24 + 1) + 24) % 24; // reset hoursif (toMinute - offsetMinutes < 0 || offsetHours != 0) // reset toHourMinute or nottoHourMinute = newHour * 100 + newMinute;return toHourMinute;
}std::string WtHftStraDemo::__tqz_getLogFileName(const TQZLogFileType logfileType) {switch (logfileType) {case TRADE_CHANGE_TYPE:return "hft_tradeChange_" + to_string(this->_ctx->tqz_getTradingDate());case CANCEL_ORDER_COUNTS_TYPE:return "hft_cancelOrderCounts_" + to_string(this->_ctx->tqz_getTradingDate());default:return "";}
}std::string WtHftStraDemo::__tqz_getCurrentTime() {const boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();const boost::posix_time::time_duration timeOfDay = now.time_of_day();const uint64_t hours = timeOfDay.hours();const uint64_t minutes = timeOfDay.minutes();const uint64_t seconds = timeOfDay.seconds();const uint64_t milliseconds = timeOfDay.total_milliseconds() - (hours * 3600 + minutes * 60 + seconds) * 1000;return this->__tqz_getTimeString(hours, minutes, seconds, milliseconds);
}std::string WtHftStraDemo::__tqz_getCurrentMarketTime() {uint32_t time = this->_ctx->stra_get_time();uint32_t secs = this->_ctx->stra_get_secs();int hours = time / 100;int minutes = time % 100;int seconds = secs / 1000;int milliseconds = secs % 1000;return this->__tqz_getTimeString(hours, minutes, seconds, milliseconds);
}std::string WtHftStraDemo::__tqz_getTimeString(const uint64_t hours, const uint64_t minutes, const uint64_t seconds, const uint64_t milliseconds) {std::string hoursString = to_string(hours);if (hours < 10)hoursString = "0" + to_string(hours);std::string minutesString = to_string(minutes);if (minutes < 10)minutesString = "0" + to_string(minutes);std::string secondsString = to_string(seconds);if (seconds < 10)secondsString = "0" + to_string(seconds);std::string millisecondsString = to_string(milliseconds);if (milliseconds < 10) {millisecondsString = "00" + to_string(milliseconds);} else if (milliseconds < 100) {millisecondsString = "0" + to_string(milliseconds);}return hoursString + ":" + minutesString + ":" + secondsString + "." + millisecondsString;
}void WtHftStraDemo::__tqz_writeStrategyTradeLog(const uint32_t orderid, const double receiveTradePrice, const double lots) {if (this->_log_message_map.find(orderid) == this->_log_message_map.end()) return;TQZLogMessage logMessage = this->_log_message_map[orderid];std::string logString = "[code|" + logMessage.code + ",order_type|" + logMessage.orderType + ",orderid|" + to_string(logMessage.orderid) + ",market_price_of_send_order|" + to_string(logMessage.currentPrice) + ",market_time_of_send_order|" + logMessage.currentMarketTime + ",send_order_price|" + to_string(logMessage.orderPrice) + ",send_order_time|" + logMessage.sendOrderTime + ",receive_trade_price|" + to_string(receiveTradePrice) + ",receive_trade_time|" + this->__tqz_getCurrentTime() + ",lots|" + to_string(lots) + ",volScale|" + to_string(this->_ctx->stra_get_comminfo(this->_code.c_str())->getVolScale()) + ",order_comment|" + logMessage.orderComment + "]";this->_ctx->tqz_writeLog(this->_tradeChange_log_filename, logString);
}void WtHftStraDemo::__tqz_writeCancelOrderCountsLog(const std::string code) {int now = this->__tqz_getCurrentHourMinute();if (now < 1500 || now > 1630)return;uint32_t cancel_order_counts = this->_ctx->tqz_getCancelCounts(code.c_str());std::string logString = "[code|" + code + ",cancel_order_counts|" + to_string(cancel_order_counts) + "]";this->_ctx->tqz_writeLog(this->__tqz_getLogFileName(CANCEL_ORDER_COUNTS_TYPE), logString);
}TQZLogMessage WtHftStraDemo::__tqz_getNewLogMessage(std::string code, uint32_t orderid, double currentPrice, double orderPrice, char* orderType, std::string currentMarketTime, std::string sendOrderTime, std::string orderComment) {return TQZLogMessage(code, orderid, currentPrice, orderPrice, orderType, currentMarketTime, sendOrderTime, orderComment);
}uint64_t WtHftStraDemo::__getCurrentTimestamp() {const boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();const boost::posix_time::time_duration timeOfDay = now.time_of_day();boost::posix_time::ptime epoch(boost::gregorian::date(1970, boost::gregorian::Jan, 1));boost::posix_time::time_duration time_from_epoch = boost::posix_time::second_clock::universal_time() - epoch;return time_from_epoch.total_seconds();
}bool WtHftStraDemo::__isNewScanInterval(const uint32_t scanInterval) {uint64_t now = this->__getCurrentTimestamp();bool isNew = (now - this->_last_scan_time < scanInterval) ? false : true;if (isNew)this->_last_scan_time = now;return isNew;
}void WtHftStraDemo::__lockBuy() {this->_code_buy_lock = true;
}void WtHftStraDemo::__lockSell() {this->_code_sell_lock = true;
}void WtHftStraDemo::__lockShort() {this->_code_short_lock = true;
}void WtHftStraDemo::__lockCover() {this->_code_cover_lock = true;
}void WtHftStraDemo::__unlockBuy() {this->_code_buy_lock = false;
}void WtHftStraDemo::__unlockSell() {this->_code_sell_lock = false;
}void WtHftStraDemo::__unlockShort() {this->_code_short_lock = false;
}void WtHftStraDemo::__unlockCover() {this->_code_cover_lock = false;
}void WtHftStraDemo::__unlockAllOrders() {this->__unlockBuy();this->__unlockSell();this->__unlockShort();this->__unlockCover();this->__unlockBuy();this->__unlockSell();this->__unlockShort();this->__unlockCover();
}bool WtHftStraDemo::__isMarketMakingAble() {if (this->__marketMakingIsLock(false))return false;if (this->_ctx->tqz_getCancelCounts(this->_code.c_str()) > this->_cancel_limit_counts)return false;if (this->_current_session_status != MARKET_MAKING_STATUS)return false;if (this->__isBeyondUpperlimitOrLowerlimit(this->_code, this->_long_order_offset, this->_short_order_offset)) // judge this->_re_market_making is true or false, then modify it...return false;return true;
}bool WtHftStraDemo::__closeCodeIsLock(bool reSendLockOrder) {bool isLock = (this->_code_sell_lock || this->_code_cover_lock);if (!reSendLockOrder)return isLock;if (this->_code_sell_lock)this->__tqz_cancelOrder(this->_code, this->_code_sell_order);if (this->_code_cover_lock)this->__tqz_cancelOrder(this->_code, this->_code_cover_order);return isLock;
}bool WtHftStraDemo::__marketMakingIsLock(bool cancelLockOrder) {bool isLock = !(!this->_code_buy_lock && !this->_code_short_lock);if (!cancelLockOrder)return isLock;if (this->_code_buy_lock)this->__tqz_cancelOrder(this->_code, this->_code_buy_order);if (this->_code_short_lock)this->__tqz_cancelOrder(this->_code, this->_code_short_order);return isLock;
}

量化交易之HFT篇 - 高频做市模型源码(.cpp文件)相关推荐

  1. 量化交易之HFT篇 - 高频做市模型源码(.h文件)

    """ 事先声明, 模型源码仅作参考和交流使用, 不能直接用于实盘 """ #pragma once #include <unorde ...

  2. python 组合优化 回撤最小_Python进阶量化交易专栏场外篇23-Markowitz实现股票最优组合...

    欢迎大家订阅<教你用 Python 进阶量化交易>专栏!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外已陆续推出一些手记来辅助同学们学习本专栏内容,目前推出的扩展篇链接如下: 股票 ...

  3. 量化交易之数据获取篇

    该篇主要是是用来展示量化交易的效果,不构成任何投资建议,仅供参考 先说说思路 该篇主要是教你怎么去获取数据,包括怎么去选取一支好的基金,怎么去获取基金往期的历史数据 先说说怎么去选取一支好的基金吧 个 ...

  4. asp毕业设计——基于asp+sqlserver的二手交易系统设计与实现(毕业论文+程序源码)——二手交易系统

    基于asp+sqlserver的二手交易系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于asp+sqlserver的二手交易系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦 ...

  5. bert模型简介、transformers中bert模型源码阅读、分类任务实战和难点总结

    bert模型简介.transformers中bert模型源码阅读.分类任务实战和难点总结:https://blog.csdn.net/HUSTHY/article/details/105882989 ...

  6. 第三篇:白话tornado源码之请求来了

    上一篇<白话tornado源码之待请求阶段>中介绍了tornado框架在客户端请求之前所做的准备(下图1.2部分),本质上就是创建了一个socket服务端,并进行了IP和端口的绑定,但是未 ...

  7. Koa洋葱圈模型源码浅析(`await next()`为什么能够形成洋葱圈模型?)

    Koa洋葱圈模型源码浅析 写在前面 什么是中间件? 为什么要使用中间件? auth中间件源码 Koa源码浅析 我们先来康一张gif图片 我们的探索流程图 listen函数 callback函数 cre ...

  8. IOCP 网络通讯模型源码解读

    From: http://hi.baidu.com/tsingsing/item/1aa5062fa27791fa50fd87b7 以前写服务器的时候用的是iocp,最近偶然发现windows的 网络 ...

  9. Threejs渲染obj+mtl模型源码,3D工厂模型

    1,介绍 Threejs实现引入工厂模型,加载obj+mtl模型源码下载,可用于学习研究,二次开发 2,部分代码 // 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光. var scene ...

最新文章

  1. ViewPager与Fragment结合使用,以及切换的时候Fragment 的生命周期
  2. Python基础总结(5)
  3. Exchange2010配置实验(六)部署forefront到edge服务器
  4. 如何利用反射实现EL表达式
  5. python豆瓣mysql_python操作mysql
  6. idea连接不了5.6mysql_IDEA无法连接mysql数据库的6种解决方法大全
  7. [jzoj 4528] [GDOI2019模拟2019.3.26] 要换换名字 (最大权闭合子图)
  8. 【MTSP】基于matlab GUI遗传算法求解多旅行商问题【含Matlab源码 935期】
  9. GWAS meta分析
  10. Ae 效果快速参考:3D 通道
  11. Unity 3D网页游戏与flash网页游戏的较量
  12. 米家扫地机器人尘盒怎么取_米家扫地机器人怎么清理灰尘盒
  13. 腾讯云账号实名认证和域名实名认证的区别
  14. MT7628K eCos开发入门
  15. Redis网站热搜关键词加载实践,建议收藏
  16. 别再用知网下载文献了,这16个国内外好用的论文网站,赶紧收藏起来
  17. 时钟分频原理 - 时钟分频原理详解
  18. php 读取cad文件路径,cad备份文件在哪里找
  19. 深度实践嵌入式linux系统移植 光盘下载地址
  20. EMNLP 2022半监督和强化对话系统挑战赛持续火热报名中,7月1日截止

热门文章

  1. canvas到底是块级元素还是内联元素?
  2. java怎么修改支付宝步数_支付宝怎么修改运动步数 刷步数方法
  3. ZooKeeper3.7.0 编译客户端zookeeper-client
  4. ROS-开源的机器人操作系统
  5. 机器学习项目之数据清洗
  6. 双足机器人课设报告_双足机器人毕业设计报告.docx
  7. bootstrap中固定table的表头
  8. Linux 配置php
  9. Access to XMLHttpRequest at ‘file:///D:/xx/xxx.json‘ from origin ‘null‘ has been blocked by CORS问题解决
  10. 编写程序把24小时制的时间改成12小时制