コード例 #1
0
ファイル: MySQLKDataDriver.cpp プロジェクト: fasiondog/hikyuu
bool MySQLKDataDriver::_init() {
    string func_name(" [MySQLKDataDriver::MySQLKDataDriver]");

    string default_host("127.0.0.1");
    string default_usr("root");
    string default_pwd("");

    try {
        m_host = m_params.get<string>("host");
    } catch(...) {
        m_host = default_host;
        HKU_WARN("Can't get mysql host! " << func_name);
    }

    try {
        m_port = m_params.get<int>("port");
    } catch(...) {
        m_port = 3306;
    }

    try {
        m_usr = m_params.get<string>("usr");
    } catch(...) {
        m_usr = default_usr;
    }

    try {
        m_pwd = m_params.get<string>("pwd");
    } catch(...) {
        m_pwd = default_pwd;
    }

    shared_ptr<MYSQL> mysql(new MYSQL, MySQLCloser());
    if (!mysql_init(mysql.get())) {
        HKU_ERROR(" Initial MySQL handle error!" << func_name);
        return false;
    }

    if (!mysql_real_connect(mysql.get(), m_host.c_str(), m_usr.c_str(),
            m_pwd.c_str(), NULL, m_port, NULL, 0) ) {
        HKU_ERROR(" Failed to connect to database!" << func_name);
        return false;
    }

    if (mysql_set_character_set(mysql.get(), "utf8")) {
        HKU_ERROR(" mysql_set_character_set error!" << func_name);
        return false;
    }

    m_mysql = mysql;

    return true;
}
コード例 #2
0
ファイル: MySQLKDataDriver.cpp プロジェクト: fasiondog/hikyuu
KRecord MySQLKDataDriver::
getKRecord(const string& market, const string& code,
          size_t pos, KQuery::KType kType) {
    string func_name(" [MySQLKDataDriver::getKRecord]");
    KRecord result;
    if (!m_mysql) {
        HKU_ERROR("Null m_mysql!" << func_name);
        return result;
    }

    /*if (kType >= KQuery::INVALID_KTYPE ) {
        HKU_WARN("ktype(" << kType << ") is invalid" << func_name);
        return result;
    }*/

    MYSQL_RES *mysql_result;
    MYSQL_ROW row;

    string table(_getTableName(market, code, kType));
    std::stringstream buf (std::stringstream::out);
    buf << "select date, open, high, low, close, amount, count from "
            << table << " order by date limit " << pos << ", 1";
    if (!_query(buf.str())) {
        HKU_ERROR("mysql_query error! " << func_name);
        return result;
    }

    mysql_result = mysql_store_result(m_mysql.get());
    if (!mysql_result) {
        HKU_ERROR("mysql_store_result error!" << func_name);
        return result;
    }

    while ((row = mysql_fetch_row(mysql_result))) {
        try {
            hku_uint64 d = boost::lexical_cast<hku_uint64>(row[0]);
            result.datetime = Datetime(d);
            result.openPrice = boost::lexical_cast<price_t>(row[1]);
            result.highPrice = boost::lexical_cast<price_t>(row[2]);
            result.lowPrice = boost::lexical_cast<price_t>(row[3]);
            result.closePrice = boost::lexical_cast<price_t>(row[4]);
            result.transAmount = boost::lexical_cast<price_t>(row[5]);
            result.transCount = boost::lexical_cast<price_t>(row[6]);
        } catch (...) {
            HKU_INFO("Error get record " << pos << " " << table << func_name);
            result = Null<KRecord>();
        }
    }

    mysql_free_result(mysql_result);
    return result;
}
コード例 #3
0
ファイル: SaftyLoss.cpp プロジェクト: fasiondog/hikyuu
bool SaftyLoss::check() {
    int n1 = getParam<int>("n1");
    int n2 = getParam<int>("n2");

    if (n1 < 2) {
        HKU_ERROR("Invalid param[n1] must >= 2 ! [SaftyLoss::SaftyLoss]");
        return false;
    }

    if (n2 < 1) {
        HKU_ERROR("Invalid param[n2] must >= 1 ! [SaftyLoss::SaftyLoss]");
        return false;
    }

    return true;
}
コード例 #4
0
ファイル: Weave.cpp プロジェクト: zklvyy/hikyuu
void Weave::_calculate(const Indicator& ind) {
    size_t total = ind.size();
    if (m_result_num != 0 && total != size()) {
        HKU_ERROR("ind's size must be equal weave's size! [Weave::_calculate]");
        return;
    }

    if (total == 0) {
        return;
    }

    size_t old_m_result_num = m_result_num;
    m_result_num = ind.getResultNumber() + m_result_num;
    if (m_result_num > MAX_RESULT_NUM) {
        HKU_WARN("Weave only can contains " << MAX_RESULT_NUM <<
                 "reult_num! [Weave::_calculate]");
        m_result_num = MAX_RESULT_NUM;
    }

    if (m_discard < ind.discard()) {
        m_discard = ind.discard();
    }

    price_t null_price = Null<price_t>();
    for (size_t i = old_m_result_num; i < m_result_num; ++i) {
        m_pBuffer[i] = new PriceList(total, null_price);
        for (size_t j = m_discard; j < total; ++j) {
            (*m_pBuffer[i])[j] = ind.get(j, i-old_m_result_num);
        }
    }
}
コード例 #5
0
size_t FixedPercentMoneyManager
::_getBuyNumber(const Datetime& datetime, const Stock& stock,
            price_t price, price_t risk, SystemPart from) {
    double p = getParam<double>("p");
    if (p <= 0.0 || p > 1.0) {
        HKU_ERROR("Error param (p = " << p
                << ") [PercentRiskMoneyManager::_getBuyNumber]");
        return 0;
    }

    if (risk == 0.0) {
        HKU_ERROR("risk is zero! [PercentRiskMoneyManager::_getBuyNumber");
        return 0;
    }

    return int(m_tm->currentCash() * p / risk);
}
コード例 #6
0
ファイル: IRound.cpp プロジェクト: fasiondog/hikyuu
bool IRound::check() {
    if (getParam<int>("ndigits") < 0) {
        HKU_ERROR("Invalid param[ndigits] ! (n >= 0) " << m_params
                << " [IRound::check]");
        return false;
    }
    return true;
}
コード例 #7
0
ファイル: ILowLineBars.cpp プロジェクト: fasiondog/hikyuu
bool ILowLineBars::check() {
    if (getParam<int>("n") < 0) {
        HKU_ERROR("Invalid param! (n>=0) "
                  << m_params << " [ILowLineBars::check]");
        return false;
    }
    return true;
}
コード例 #8
0
ファイル: MySQLKDataDriver.cpp プロジェクト: fasiondog/hikyuu
size_t MySQLKDataDriver::
getCount(const string& market,
        const string& code,
        KQuery::KType kType) {
    string func_name(" [MySQLKDataDriver::getCount]");
    size_t result = 0;
    if (!m_mysql) {
        HKU_ERROR("Null m_mysql!" << func_name);
        return result;
    }

    /*if (kType >= KQuery::INVALID_KTYPE ) {
        HKU_WARN("ktype(" << kType << ") is invalid" << func_name);
        return result;
    }*/

    MYSQL_RES *mysql_result;
    MYSQL_ROW row;

    string table(_getTableName(market, code, kType));
    std::stringstream buf (std::stringstream::out);
    buf << "select count(1) from " << table;
    if (!_query(buf.str())) {
        HKU_ERROR("mysql_query error! " << func_name);
        return result;
    }

    mysql_result = mysql_store_result(m_mysql.get());
    if (!mysql_result) {
        HKU_ERROR("mysql_store_result error!" << func_name);
        return result;
    }

    while ((row = mysql_fetch_row(mysql_result))) {
        try {
            result = boost::lexical_cast<size_t>(row[0]);
        } catch (...) {
            HKU_INFO("Error get record count of" << table << func_name);
            result = 0;
        }
    }

    mysql_free_result(mysql_result);
    return result;
}
コード例 #9
0
ファイル: Indicator.cpp プロジェクト: fasiondog/hikyuu
Indicator HKU_API WEAVE(const Indicator& ind1, const Indicator& ind2) {
    if (!ind1.getImp() || !ind2.getImp()) {
        HKU_ERROR("ind1 or ind2 is Null Indicator! [WEAVE]");
        return Indicator();
    }
    IndicatorImpPtr p = make_shared<IndicatorImp>();
    p->add(IndicatorImp::WEAVE, ind1.getImp(), ind2.getImp());
    return p->calculate();
}
コード例 #10
0
ファイル: RightShift.cpp プロジェクト: zklvyy/hikyuu
bool RightShift::check() {
    int n = getParam<int>("n");
    if (n < 0) {
        HKU_ERROR("Invalid param! (n>=0) "
                  << m_params << " [RightShift::RightShift]");
        return false;
    }

    return true;
}
コード例 #11
0
ファイル: IVarp.cpp プロジェクト: fasiondog/hikyuu
bool IVarp::check() {
    int n = getParam<int>("n");
    if (n < 2) {
        HKU_ERROR("Invalid param[n] ! (n >= 2) " << m_params
                << " [IVarp::calculate]");
        return false;
    }

    return true;
}
コード例 #12
0
ファイル: LowLine.cpp プロジェクト: zklvyy/hikyuu
bool LowLine::check() {
    int n = getParam<int>("n");
    if (n < 1) {
        HKU_ERROR("Invalid param[n] ! (n >= 1) " << m_params
                << " [HighLine::calculate]");
        return false;
    }

    return true;
}
コード例 #13
0
ファイル: Indicator.cpp プロジェクト: fasiondog/hikyuu
Indicator HKU_API IF(const Indicator& ind1, 
        const Indicator& ind2, const Indicator& ind3) {
    if (!ind1.getImp() || !ind2.getImp() || !ind3.getImp()) {
        HKU_ERROR("Exists null indicator! [IF]");
        return Indicator();
    }

    IndicatorImpPtr p = make_shared<IndicatorImp>();
    p->add_if(ind1.getImp(), ind2.getImp(), ind3.getImp());
    return p->calculate();
}
コード例 #14
0
ファイル: StockManager.cpp プロジェクト: fasiondog/hikyuu
bool StockManager::addStockTypeInfo(const StockTypeInfo& stkTypeInfo) {
    if (m_stockTypeInfo.find(stkTypeInfo.type()) != m_stockTypeInfo.end()) {
        HKU_ERROR("The stockTypeInfo had exist! "
                << stkTypeInfo.type()
                << " [StockManager::addStockTypeInfo]");
        return false;
    }

    m_stockTypeInfo[stkTypeInfo.type()] = stkTypeInfo;
    return true;
}
コード例 #15
0
ファイル: StockManager.cpp プロジェクト: fasiondog/hikyuu
bool StockManager::addMarketInfo(const MarketInfo& marketInfo) {
    string market = marketInfo.market();
    boost::to_upper(market);
    if (m_marketInfoDict.find(market) != m_marketInfoDict.end()) {
        HKU_ERROR("The marketInfo had exist! "
                << market
                << " [StockManager::addMarketInfo]");
        return false;
    }

    m_marketInfoDict[market] = marketInfo;
    return true;
}
コード例 #16
0
ファイル: StockManager.cpp プロジェクト: fasiondog/hikyuu
bool StockManager::addStock(const Stock& stock) {
    string market_code(stock.market_code());
    boost::to_upper(market_code);
    if(m_stockDict.find(market_code) != m_stockDict.end()) {
        HKU_ERROR("The stock had exist! "
                << market_code
                << " [StockManager::addStock]");
        return false;
    }

    m_stockDict[market_code] = stock;
    return true;
}
コード例 #17
0
ファイル: MySQLKDataDriver.cpp プロジェクト: fasiondog/hikyuu
bool MySQLKDataDriver::_query(const string& sql_str) {
    string func_name(" [MySQLKDataDriver::query]");
    int res = mysql_query(m_mysql.get(), sql_str.c_str());
    if (!res) {
        return true;
    }

    //重新连接数据库
    HKU_INFO("MySQL connect invalid, will retry connect!" << func_name);
    m_mysql = NULL;

    shared_ptr<MYSQL> mysql(new MYSQL, MySQLCloser());
    if (!mysql_init(mysql.get())) {
        HKU_ERROR(" Initial MySQL handle error!" << func_name);
        return false;
    }

    if (!mysql_real_connect(mysql.get(), m_host.c_str(), m_usr.c_str(),
        m_pwd.c_str(), NULL, m_port, NULL, 0) ) {
        HKU_ERROR(" Failed to connect to database!" << func_name);
        return false;
    }

    if (mysql_set_character_set(mysql.get(), "utf8")) {
        HKU_ERROR(" mysql_set_character_set error!" << func_name);
        return false;
    }

    m_mysql = mysql;

    res = mysql_query(m_mysql.get(), sql_str.c_str());
    if(!res) {
        return true;
    }

    HKU_ERROR("mysql_query error! error no: " << res
                << " " << sql_str << func_name);
    return false;
}
コード例 #18
0
ファイル: BaseInfoDriver.cpp プロジェクト: fasiondog/hikyuu
bool BaseInfoDriver::checkType() {
    bool result = false;
    try {
        string type = getParam<string>("type");
        boost::to_upper(type);
        if (type == m_name) {
            result = true;
        } else {
            result = false;
            HKU_WARN("Type of driver mismatch! ("
                    << type << " != " << m_name << ") "
                    << "[BaseInfoDriver::checkType]");
        }

    } catch(...) {
        result = false;
        HKU_ERROR("Can't get type of driver! [BaseInfoDriver::checkType]");
    }

    return result;
}
コード例 #19
0
ファイル: IPriceList.cpp プロジェクト: fasiondog/hikyuu
void IPriceList::_calculate(const Indicator& data) {
    //如果在叶子节点,直接取自身的data参数
    if (isLeaf()) {
        PriceList x = getParam<PriceList>("data");
        int discard = getParam<int>("discard");

        size_t total = x.size();
        _readyBuffer(total, 1);

        //更新抛弃数量
        m_discard = discard > total ? total : discard;

        for (size_t i = m_discard; i < total; ++i) {
            _set(x[i], i);
        }

        return;
    }

    //不在叶子节点上,则忽略本身的data参数,认为其输入实际为函数入参中的data
    int result_index = getParam<int>("result_index");
    if (result_index < 0 || result_index >= data.getResultNumber()) {
        HKU_ERROR("result_index out of range! [IPriceList::IPriceList]");
        return;
    }

    size_t total = data.size();
    _readyBuffer(total, 1);

    for (size_t i = data.discard(); i < total; ++i) {
        _set(data.get(i, result_index), i);
    }

    //更新抛弃数量
    m_discard = data.discard();
}
コード例 #20
0
ファイル: StockManager.cpp プロジェクト: fasiondog/hikyuu
void StockManager::setKDataDriver(const KDataDriverPtr& driver) {
    if (!driver) {
        HKU_ERROR("kdata driver is null! [StockManager::setKDataDriver]");
        return;
    }

    if (m_kdataDriverParam == driver->getParameter()) {

    } else {
        m_kdataDriverParam = driver->getParameter();
    }

    bool preload_day = false;
    try {
        preload_day = m_preloadParam.get<bool>("day");
        if (preload_day)
            HKU_INFO("Preloading all day kdata to buffer!");
    } catch(...) {
        preload_day = false;
    }

    bool preload_week = false;
    try {
        preload_week = m_preloadParam.get<bool>("week");
        if (preload_week)
            HKU_INFO("Preloading all week kdata to buffer!");
    } catch(...) {
        preload_week = false;
    }

    bool preload_month = false;
    try {
        preload_month = m_preloadParam.get<bool>("month");
        if (preload_week)
            HKU_INFO("Preloading all month kdata to buffer!");
    } catch(...) {
        preload_month = false;
    }

    bool preload_quarter = false;
    try {
        preload_quarter = m_preloadParam.get<bool>("quarter");
        if (preload_quarter)
            HKU_INFO("Preloading all quarter kdata to buffer!");
    } catch(...) {
        preload_quarter = false;
    }

    bool preload_halfyear = false;
    try {
        preload_halfyear = m_preloadParam.get<bool>("halfyear");
        if (preload_halfyear)
            HKU_INFO("Preloading all halfyear kdata to buffer!");
    } catch(...) {
        preload_halfyear = false;
    }

    bool preload_year = false;
    try {
        preload_year = m_preloadParam.get<bool>("year");
        if (preload_year)
            HKU_INFO("Preloading all year kdata to buffer!");
    } catch(...) {
        preload_year = false;
    }

    bool preload_min = false;
    try {
        preload_min = m_preloadParam.get<bool>("min");
        if (preload_min)
            HKU_INFO("Preloading all 1 min kdata to buffer!");
    } catch(...) {
        preload_min = false;
    }

    bool preload_min5 = false;
    try {
        preload_min5 = m_preloadParam.get<bool>("min5");
        if (preload_min5)
            HKU_INFO("Preloading all 5 min kdata to buffer!");
    } catch(...) {
        preload_min5 = false;
    }

    bool preload_min15 = false;
    try {
        preload_min15 = m_preloadParam.get<bool>("min15");
        if (preload_min15)
            HKU_INFO("Preloading all 15 min kdata to buffer!");
    } catch(...) {
        preload_min15 = false;
    }

    bool preload_min30 = false;
    try {
        preload_min30 = m_preloadParam.get<bool>("min30");
        if (preload_min30)
            HKU_INFO("Preloading all 30 min kdata to buffer!");
    } catch(...) {
        preload_min30 = false;
    }

    bool preload_min60 = false;
    try {
        preload_min60 = m_preloadParam.get<bool>("min60");
        if (preload_min60)
            HKU_INFO("Preloading all 60 min kdata to buffer!");
    } catch(...) {
        preload_min60 = false;
    }

    for(auto iter = m_stockDict.begin(); iter != m_stockDict.end(); ++iter) {
        if (iter->second.market() == "TMP")
            continue;

        iter->second.setKDataDriver(driver);

        if (preload_day)
            iter->second.loadKDataToBuffer(KQuery::DAY);

        if (preload_week)
            iter->second.loadKDataToBuffer(KQuery::WEEK);

        if (preload_month)
            iter->second.loadKDataToBuffer(KQuery::MONTH);

        if (preload_quarter)
            iter->second.loadKDataToBuffer(KQuery::QUARTER);

        if (preload_halfyear)
            iter->second.loadKDataToBuffer(KQuery::HALFYEAR);

        if (preload_year)
            iter->second.loadKDataToBuffer(KQuery::YEAR);

        if (preload_min)
            iter->second.loadKDataToBuffer(KQuery::MIN);

        if (preload_min5)
            iter->second.loadKDataToBuffer(KQuery::MIN5);

        if (preload_min15)
            iter->second.loadKDataToBuffer(KQuery::MIN15);

        if (preload_min30)
            iter->second.loadKDataToBuffer(KQuery::MIN30);

        if (preload_min60)
            iter->second.loadKDataToBuffer(KQuery::MIN60);
    }
}
コード例 #21
0
ファイル: MySQLKDataDriver.cpp プロジェクト: fasiondog/hikyuu
bool MySQLKDataDriver::
getIndexRangeByDate(const string& market, const string& code,
        const KQuery& query, size_t& out_start, size_t& out_end) {
    string func_name(" [MySQLKDataDriver::getIndexRangeByDate]");
    out_start = 0;
    out_end = 0;
    if (query.queryType() != KQuery::DATE) {
        HKU_ERROR("queryType must be KQuery::DATE" << func_name);
        return false;
    }

    if(query.startDatetime() >= query.endDatetime()
    || query.startDatetime() > (Datetime::max)()) {
        return false;
    }

    MYSQL_RES *mysql_result;
    MYSQL_ROW row;

    string table(_getTableName(market, code, query.kType()));
    std::stringstream buf (std::stringstream::out);
    buf << "select count(1) from " << table
        << " where date<" << query.startDatetime().number();

    if (!_query(buf.str())) {
        HKU_ERROR("mysql_query error! " << func_name);
        return false;
    }

    mysql_result = mysql_store_result(m_mysql.get());
    if (!mysql_result) {
        HKU_ERROR("mysql_store_result error!" << func_name);
        return false;
    }

    while ((row = mysql_fetch_row(mysql_result))) {
        try {
            out_start = boost::lexical_cast<size_t>(row[0]);
        } catch (...) {
            HKU_INFO("Error boost::lexical_cast<size_t>" << table << func_name);
            out_start = 0;
            mysql_free_result(mysql_result);
            return false;
        }
    }

    mysql_free_result(mysql_result);

    buf.str("");
    buf << "select count(1) from " << table
        << " where date<=" << query.endDatetime().number();
    if (!_query(buf.str())) {
        HKU_ERROR("mysql_query error! " << func_name);
        return false;
    }

    mysql_result = mysql_store_result(m_mysql.get());
    if (!mysql_result) {
        HKU_ERROR("mysql_store_result error!" << func_name);
        return false;
    }

    while ((row = mysql_fetch_row(mysql_result))) {
        try {
            out_end = boost::lexical_cast<size_t>(row[0]) - 1;
        } catch (...) {
            HKU_INFO("Error boost::lexical_cast<size_t>" << table << func_name);
            out_end = 0;
            mysql_free_result(mysql_result);
            return false;
        }
    }

    mysql_free_result(mysql_result);
    return true;
}
コード例 #22
0
ファイル: MySQLKDataDriver.cpp プロジェクト: fasiondog/hikyuu
void MySQLKDataDriver::
loadKData(const string& market, const string& code,
        KQuery::KType kType, size_t start_ix, size_t end_ix,
        KRecordListPtr out_buffer) {
    string func_name(" [MySQLKDataDriver::loadKData]");
    if (!m_mysql) {
        //HKU_ERROR("Null m_mysql!" << func_name);
        return;
    }

    //if (kType >= KQuery::INVALID_KTYPE || start_ix >= end_ix) {
    if (start_ix >= end_ix) {        
        HKU_WARN("ktype(" << kType << ") is invalid or start_ix("
                << start_ix << ") >= endix(" << end_ix << ")" << func_name);
        return;
    }

    MYSQL_RES *result;
    MYSQL_ROW row;

    string table(_getTableName(market, code, kType));
    std::stringstream buf (std::stringstream::out);
    buf << "select date, open, high, low, close, amount, count from "
            << table << " order by date limit " << start_ix
            << ", " << (end_ix - start_ix);
    if (!_query(buf.str())) {
        //HKU_ERROR("mysql_query error!" << func_name);
        return;
    }

    result = mysql_store_result(m_mysql.get());
    if (!result) {
        HKU_ERROR("mysql_store_result error!" << func_name);
        return;
    }

    int i = 0;
    while ((row = mysql_fetch_row(result))) {
        try {
            KRecord k;
            hku_uint64 d = boost::lexical_cast<hku_uint64>(row[0]);
            k.datetime = Datetime(d);
            k.openPrice = boost::lexical_cast<price_t>(row[1]);
            k.highPrice = boost::lexical_cast<price_t>(row[2]);
            k.lowPrice = boost::lexical_cast<price_t>(row[3]);
            k.closePrice = boost::lexical_cast<price_t>(row[4]);
            k.transAmount = boost::lexical_cast<price_t>(row[5]);
            k.transCount = boost::lexical_cast<price_t>(row[6]);
            out_buffer->push_back(k);
            i++;
        } catch (...) {
            HKU_INFO("Can't fecth No." << i << " record in "
                    << table << func_name);
            i++;
            continue;
        }
    }

    mysql_free_result(result);
    return;
}
コード例 #23
0
PriceList HistoryFinanceReader
::getHistoryFinanceInfo(Datetime date, 
        const string& market, const string& code) {
    string funcname(" [HistoryFinanceReader::getHistoryFinanceInfo]");
    PriceList result;

    string filename(m_dir + "/gpcw" 
                   + boost::lexical_cast<string>(date.number() / 10000)
                   + ".dat");
    FILE *fp = fopen(filename.c_str(), "rb");
    if (NULL == fp) {
        HKU_INFO("Can't found " << filename << funcname);
        return result;
    }

    unsigned int report_date = 0;  
    unsigned short max_count = 0;
    unsigned long report_size = 0;
    
    char header_buf[20];
    if (!fread(header_buf, 1, 20, fp)) {
        HKU_ERROR("read data failed! " << filename << funcname);
        fclose(fp);
        return result;
    }

    memcpy(&report_date, header_buf + 2, 4);
    memcpy(&max_count, header_buf + 6, 2);
    memcpy(&report_size, header_buf + 12, 4);

    char stock_code[7];
    hku_uint32 address = 0;
    for (int i = 0; i < max_count; i++) {
        if (!fread(stock_code, 1, 7, fp)) {
            HKU_ERROR("read stock_code failed! " << filename << funcname);
            fclose(fp);
            return result;
        }

        if (!fread(&address, 4, 1, fp)) {
            HKU_ERROR("read stock_item address failed! " << filename << funcname);
            fclose(fp);
            return result;
        }

        stock_code[6] = '\0';
        if (strcmp(stock_code, code.c_str()) == 0) {
            break;
        }
    }

    if (address != 0) {
        const int MAX_COL_NUM = 350;
        float result_buffer[MAX_COL_NUM];
        int report_fields_count = int(report_size / 4);
        if (report_fields_count >= MAX_COL_NUM) {
            HKU_WARN("Over MAX_COL_NUM! " << filename << funcname);
            report_fields_count = MAX_COL_NUM;
        }
        
        fseek(fp, address, SEEK_SET);

        if (!fread(result_buffer, 4, report_fields_count, fp)) {
            HKU_ERROR("read col data failed! " << filename << funcname);
            fclose(fp);
            return result;
        }

        result.reserve(report_fields_count);
        price_t null_price = Null<price_t>();
        for (int i = 0; i < report_fields_count; i++) {
            if (result_buffer[i] == 0xf8f8f8f8) {
                result.push_back(null_price);
            } else {
                result.push_back(result_buffer[i]);
            }
        }
    
    } else {
        HKU_ERROR("Invalid address(0)! " << filename << funcname);
    }

    fclose(fp);
    return result;
}