#include #include #include #include "../../shared/MiscSupport.h" #include "../../shared/SimpleLogFile.h" #include "SymbolList.h" ///////////////////////////////////////////////////////////////////// // StockInfoContainer ///////////////////////////////////////////////////////////////////// class StockInfoContainer { public: StockInfo value; bool operator <(StockInfoContainer const &other) const; bool operator ==(StockInfoContainer const &other) const; uint32_t hashCode() const; StockInfoContainer() { } StockInfoContainer(StockInfo const &orig) : value(orig) { } }; bool StockInfoContainer::operator <(StockInfoContainer const &other) const { // Sort with the "best" symbols first. Start with the items with the // highest dollar volume. If that's the same, give higher priority to // stocks which have traded more recently. Use the symbol as the third // key, only to make sure that each entry is unique, and we can put all // the values into a set. if (value.dollarVolume > other.value.dollarVolume) return true; else if (value.dollarVolume < other.value.dollarVolume) return false; else if (value.closeDate > other.value.closeDate) return true; else if (value.closeDate < other.value.closeDate) return false; else return value.symbol < other.value.symbol; } bool StockInfoContainer::operator ==(StockInfoContainer const &other) const { return (value.dollarVolume == other.value.dollarVolume) && (value.closeDate == other.value.closeDate) && (value.symbol == other.value.symbol); } uint32_t StockInfoContainer::hashCode() const { // Keep this simple. There isn't much we can do with a stock symbol. uint32_t accumulator = 0; int bitFrom = 1; int bitTo = 0x123000; for (std::string::const_iterator it = value.symbol.begin(); it != value.symbol.end(); it++) { accumulator *= 9; accumulator += *it; if (accumulator && bitFrom) accumulator ^= bitTo; bitFrom<<=1; bitTo>>=1; } accumulator += accumulator<<24; accumulator += (accumulator>>8) & 0xffff; return accumulator; } ///////////////////////////////////////////////////////////////////// // SymbolList ///////////////////////////////////////////////////////////////////// SymbolList::SymbolList() : _oldestPossible(0) { disableHashing(); } void SymbolList::add(StockInfo const &toAdd) { assert(!toAdd.symbol.empty()); StockInfo &info = _symbols[toAdd.symbol]; if (info.symbol.empty()) // New entry. info = toAdd; else { // Merge the the into the existing. info.closeDate = std::max(info.closeDate, toAdd.closeDate); info.dollarVolume = std::max(info.dollarVolume, toAdd.dollarVolume); } } void SymbolList::addIfNew(StockInfo const &toAdd, std::string const &source) { assert(!toAdd.symbol.empty()); StockInfo &info = _symbols[toAdd.symbol]; if (info.symbol.empty()) { // New entry. info = toAdd; TclList msg; msg<<"Adding missing stock" <<"symbol"< 0); _hashCount = value; } void SymbolList::setHashPartition(int value) { setHashPartitions(value, value); } void SymbolList::setHashPartitions(int first, int last) { assert((first >= 0) && (last >= first)); _hashFirst = first; _hashLast = last; } void SymbolList::disableHashing() { setHashCount(1); setHashPartition(0); } SymbolList::Result SymbolList::getValues() const { return getValues(std::numeric_limits< int >::max()); } SymbolList::Result SymbolList::getValues(int maxCount) const { // Verify the hash parameters. Some of these we checked when they were first entered. We check these here because they are // comparing different parameters to each other. That way the user can enter the parameters in any order. assert(_hashLast < _hashCount); assert(maxCount >= 0); // Always sort for simplicity. We could try to optimize, and not sort unless we had to. std::set< StockInfoContainer > _allPossible; for (std::map< std::string, StockInfo >::const_iterator it = _symbols.begin(); it != _symbols.end(); it++) { StockInfoContainer possible = it->second; if (possible.value.closeDate < _oldestPossible) continue; if (_hashCount > 1) { const uint32_t hash = possible.hashCode() % (unsigned int)_hashCount; if ((hash < (uint32_t)_hashFirst) || (hash > (uint32_t)_hashLast)) continue; } _allPossible.insert(possible); } Result result; for (std::set< StockInfoContainer >::const_iterator it = _allPossible.begin(); (it != _allPossible.end()) && maxCount; it++, maxCount--) result.push_back(it->value.symbol); return result; } void SymbolList::add(StockInfoList const &toAdd) { for (StockInfoList::const_iterator it = toAdd.begin(); it != toAdd.end(); it++) add(*it); } void SymbolList::addIfNew(StockInfoList const &toAdd, std::string const &source) { for (StockInfoList::const_iterator it = toAdd.begin(); it != toAdd.end(); it++) addIfNew(*it, source); }