double TechUtils::CalulateWMA(const std::vector<TickWrapper>& data, const TickWrapper& current, size_t seconds) { //datetime to timestamp size_t n = seconds * 2; double totalExchangeLastPrice = current.LastPrice() * n; long long count = n--; long long leftedge = current.toTimeStamp() - seconds * 2; for (auto it = data.rbegin(); it != data.rend(); it++) { if (it->toTimeStamp() > leftedge){ totalExchangeLastPrice += (it->LastPrice() * n); --n; count += n; } else{ break; } } //assert(totalVolume != 0); //assert(totalExchangePrice >= 0.0); return totalExchangeLastPrice / count; }
double TechUtils::CalulateEMA(const std::vector<TickWrapper>& data, const TickWrapper& current, size_t seconds) { if (data.empty()){ return current.LastPrice(); } size_t N = seconds * 2; TickWrapper preNode = data.back(); MACrossTech* preTechVec = dynamic_cast<MACrossTech*>(preNode.m_techvec); if (preTechVec){ if (seconds == 60 * preTechVec->ShortMA()){ double ret = (2 * current.LastPrice() + (N - 1)* preTechVec->ShortMA()) / (N + 1); return ret; } else if (seconds == 60 * preTechVec->LongMA()){ double ret = (2 * current.LastPrice() + (N - 1)* preTechVec->LongMA()) / (N + 1); return ret; } else{ assert(false); return -1; } } else{ return current.LastPrice(); } }
double TechUtils::CalulateAMA(const std::vector<TickWrapper>& data, const TickWrapper& current, size_t seconds) { double totalExchangePrice = current.TurnOver(); long long totalVolume = current.Volume(); long long leftedge = current.toTimeStamp() - seconds * 2; for (auto it = data.rbegin(); it != data.rend(); it++) { if (it->toTimeStamp() > leftedge){ totalExchangePrice += it->TurnOver(); totalVolume += it->Volume(); } else{ break; } } //assert(totalVolume != 0); //assert(totalExchangePrice >= 0.0); return totalExchangePrice / totalVolume; }
double TechUtils::CalulateMA(const std::list<TickWrapper>& data, const TickWrapper& current, size_t seconds) { //datetime to timestamp double totalExchangeLastPrice = current.LastPrice(); long long count = 1; long long leftedge = current.toTimeStamp() - seconds * 2; for (auto it = data.begin(); it != data.end(); it++) { if (it->toTimeStamp() > leftedge){ totalExchangeLastPrice += it->LastPrice(); ++count; } else{ break; } } //assert(totalVolume != 0); //assert(totalExchangePrice >= 0.0); return totalExchangeLastPrice / count; }
//main thread void RealTimeDataProcessor::AppendRealTimeData(TickWrapper& info){ //(in)front-------------back(out) // if m_strategy == nullptr, that means RealTimeDataProcessor is in data-recording mode if (m_strategy){ #ifdef UseKDataToInvoke bool triggered = m_strategy->tryInvoke(m_DataSeq, m_KDataVec, m_TickSet60, info); #else bool triggered = m_strategy->tryInvoke(m_DataSeq, info); #endif if (triggered){ Order ord; //for now, only permit order_queue has one item. if (order_queue.empty() && m_strategy->generateOrder(ord)){ order_queue.push(ord); } } } m_DataSeq.push_front(info); //construct 1-minutes k-line intermediate data if (m_TickSet60.empty()){ m_TickSet60.push_back(info); } else{ if (CommonUtils::InSameMinute(info.Time(), m_TickSet60.front().Time())){ m_TickSet60.push_back(info); } else{ // the comming tick data is in next minutes KData k1m(m_TickSet60, 60); m_KDataVec.push_back(k1m); m_TickSet60.clear(); } } #ifdef SHOW_PROGRESS spdlog::get("console")->info() << "> Data queue size :" << m_DataSeq.size(); #endif }
bool MACrossStratgy::tryInvoke(const std::list<TickWrapper>& data, TickWrapper& info) { TickType direction = TickType::Commom; const size_t breakthrough_confirm_duration = 100; //50ms MACrossTech* curPtr = generateTechVec(info); bool orderSingal = false; double short_ma = calculateK(data, info, m_shortMA * 60); double long_ma = calculateK(data, info, m_longMA * 60); curPtr->setShortMA(short_ma); curPtr->setLongMA(long_ma); if (!data.empty()){ if (curPtr->IsTriggerPoint()){ // up if (!data.empty() && data.size() > 500){ std::list<TickWrapper>::const_iterator stoper = data.begin(); std::advance(stoper, breakthrough_confirm_duration); for (auto it = data.begin(); it != stoper; it++){ StrategyTech* prePtr = it->GetTechVec(); // if prePtr == NULL, mean it's recovered from db, so that md is not continuous. so it's should not be singal point. if (prePtr == NULL || !prePtr->IsTriggerPoint()) { // not special point orderSingal = false; break; } orderSingal = true; } //special point if (orderSingal){ //update m_curOrder m_curOrder->SetInstrumentId(info.InstrumentId()); m_curOrder->SetOrderType(Order::LimitPriceFOKOrder); m_curOrder->SetRefExchangePrice(info.LastPrice()); m_curOrder->SetExchangeDirection(THOST_FTDC_D_Buy); curPtr->SetTickType(TickType::BuyPoint); } } } else{ // down if (!data.empty() && data.size() > 500){ std::list<TickWrapper>::const_iterator stoper = data.begin(); std::advance(stoper, breakthrough_confirm_duration); for (auto it = data.begin(); it != stoper; it++){ StrategyTech* prePtr = it->GetTechVec(); if (prePtr == NULL || prePtr->IsTriggerPoint()) { // not special point orderSingal = false; break; } orderSingal = true; } if (orderSingal){ //special point m_curOrder->SetInstrumentId(info.InstrumentId()); m_curOrder->SetOrderType(Order::LimitPriceFOKOrder); m_curOrder->SetRefExchangePrice(info.LastPrice()); m_curOrder->SetExchangeDirection(THOST_FTDC_D_Sell); curPtr->SetTickType(TickType::SellPoint); } } } } //info.SetTechVec((StrategyTech*)curPtr); info.m_techvec = curPtr; return orderSingal; }