text: 
  #include <stdlib.h>
  #include <tradingcore2/exchange.h>
  #include <tradingcore2/indicator/smma.h>
  #include <tradingcore2/utils.h>
  
  #include <ctime>
  #include <iomanip>
  
  CR2BEGIN
  
  void IndicatorSMMA::pushData(TimeStamp ts, IndicatorDataValue val) {
    Node n;
  
    n.ts = ts;
    n.val.value = val;
  
    m_lst.push_back(n);
  }
  
  bool IndicatorSMMA::build(Exchange& exchange, const char* assetsName, int start,
                            int length) {
    assert(assetsName != NULL);
    assert(start >= 0);
    assert(length > 0);
  
    this->release();
  
    int totalLength = exchange.getDataLength(assetsName);
    if (start >= totalLength) {
      return false;
    }
  
    if (start + length >= totalLength) {
      length = totalLength - start;
    }
  
    if (length <= 0) {
      return false;
    }
  
    m_iStart = start;
  
    CandleData cd;
    auto isok = exchange.getData(assetsName, start, cd);
    assert(isok);
  
    IndicatorDataValue pv = cd.close;
  
    this->pushData(cd.ts, cd.close);
  
    for (int i = 1; i < length; ++i) {
      auto isok = exchange.getData(assetsName, start + i, cd);
      assert(isok);
  
      pv = (pv * (this->m_avgtimes - 1) + cd.close) / this->m_avgtimes;
      this->pushData(cd.ts, pv);
    }
  
    return true;
  }
  
  bool IndicatorSMMA::build2(Exchange& exchange, const char* assetsName,
                             const char* assetsName2, IndicatorBuild2Type b2t,
                             int64_t ot, int start, int length) {
    assert(assetsName != NULL);
    assert(assetsName2 != NULL);
    assert(start >= 0);
    assert(length > 0);
  
    this->release();
  
    int totalLength = exchange.getDataLength(assetsName);
    if (start >= totalLength) {
      return false;
    }
  
    if (start + length >= totalLength) {
      length = totalLength - start;
    }
  
    if (length <= 0) {
      return false;
    }
  
    m_iStart = start;
  
    CandleData cd;
    auto isok = exchange.getData(assetsName, start, cd);
    assert(isok);
  
    IndicatorDataValue pv = cd.close;
  
    CandleData cd1;
    isok = exchange.getDataWithTimestamp(assetsName2,
                                         cd.ts + this->m_params.b2OffTime, cd1);
    assert(isok);
  
    this->pushData(cd.ts, cd1.close);
  
    for (int i = 1; i < length; ++i) {
      auto isok = exchange.getData(assetsName, start + i, cd);
      assert(isok);
  
      CandleData cd1;
      isok = exchange.getDataWithTimestamp(assetsName2,
                                           cd.ts + this->m_params.b2OffTime, cd1);
      assert(isok);
  
      this->pushData(
          cd.ts, (pv * (this->m_avgtimes - 1) + cd1.close) / this->m_avgtimes);
  
      pv = (pv * (this->m_avgtimes - 1) + cd.close) / this->m_avgtimes;
    }
  
    return true;
  }
  
  const IndicatorData_singleValue* IndicatorSMMA::getMinSingleValue(
      int& index) const {
    const IndicatorData_singleValue* pMin = NULL;
  
    for (auto it = this->m_lst.begin(); it != this->m_lst.end(); ++it) {
      if (it->val.value != 100 && (pMin == NULL || it->val.value < pMin->value)) {
        pMin = &(it->val);
        index = std::distance(it, this->m_lst.begin());
      }
    }
  
    return pMin;
  }
  
  const IndicatorData_singleValue* IndicatorSMMA::getMaxSingleValue(
      int& index) const {
    const IndicatorData_singleValue* pMax = NULL;
  
    for (auto it = this->m_lst.begin(); it != this->m_lst.end(); ++it) {
      if (it->val.value != 100 && (pMax == NULL || it->val.value > pMax->value)) {
        pMax = &(it->val);
        index = std::distance(it, this->m_lst.begin());
      }
    }
  
    return pMax;
  }
  
  // newIndicator - new IndicatorSMMA
  Indicator* IndicatorSMMA::newIndicator(const char* fullname,
                                         const char* assetsName) {
    return new IndicatorSMMA(fullname, assetsName);
  }
  
  // isMine - isMine
  bool IndicatorSMMA::isMine(const char* name) {
    std::vector<std::string> arr;
    splitStr(arr, name, ".");
  
    if (arr.size() == 2 && arr[0] == "smma") {
      try {
        auto v = std::stoi(arr[1]);
        return true;
      } catch (...) {
        return false;
      }
    }
  
    return false;
  }
  
  CR2END