#include "../alert_framework/AlertBase.h" #include "../data_framework/GenericTosData.h" #include "../../shared/MarketHours.h" #include "FastCrossedOpenClose.h" /* Crossed above / below open / close. These are computed every print. * * These were some of our first alerts. They were not very popular because * they would go off repeatedly when we were near an interesting level. */ //////////////////////////////////////////////////////////////////// // TimePassed // // This was added later as a way to compute the quality of the alert. //////////////////////////////////////////////////////////////////// class TimePassed : public DataNode { private: time_t _lastTime; double _quality; TimePassed(DataNodeArgument const &args); friend class DataNode; public: void updateTime(); double getQuality() const { return _quality; } static DataNodeLink *find(TimePassed *&node, std::string const &symbol, std::string const &group); }; TimePassed::TimePassed(DataNodeArgument const &args) : _lastTime(0), _quality(-1) // This should never be used. { } void TimePassed::updateTime() { const time_t newTime = getSubmitTime(); if ((_lastTime == 0) || (_lastTime > newTime)) _quality = MARKET_HOURS_MINUTE * 5; else _quality = (newTime - _lastTime); _lastTime = newTime; } DataNodeLink *TimePassed::find(TimePassed *&node, std::string const &symbol, std::string const &group) { return findHelper(NULL, 0, node, argList(symbol, group)); } //////////////////////////////////////////////////////////////////// // FastCrossedOpenClose //////////////////////////////////////////////////////////////////// class FastCrossedOpenClose : public Alert { bool _reportUp; std::string _msg; GenericTosDataNode *_tosData; TimePassed *_timePassedData; GenericDataNode *_compareToData; AboveOrBelow _previousState; void onWakeup(int msgId); FastCrossedOpenClose(DataNodeArgument const &args); friend class GenericDataNodeFactory; }; void FastCrossedOpenClose::onWakeup(int msgId) { bool valid; double compareToValue; _compareToData->getDouble(valid, compareToValue); if (!(valid && _tosData->getValid())) { _previousState = ccEqual; return; } const double last = _tosData->getLast().price; if (last == 0.0) { // It seems as if valid is often set to true even when there is no price. // This is espeically common with NYSE data. Treat 0 as invalid. The // definitions of open and close (from SimpleMarketData.[Ch]) already do // this for us. _previousState = ccEqual; return; } AboveOrBelow newState; if (last < compareToValue) newState = ccBelow; else if (last == compareToValue) newState = ccEqual; else newState = ccAbove; if (((!_reportUp) && (newState == ccBelow) && (_previousState == ccAbove)) || (_reportUp && (newState == ccAbove) && (_previousState == ccBelow))) { _timePassedData->updateTime(); const std::string otherPrice = formatPrice(compareToValue); report(_msg + otherPrice, "op=" + otherPrice, _timePassedData->getQuality()); } if (newState != ccEqual) _previousState = newState; } FastCrossedOpenClose::FastCrossedOpenClose(DataNodeArgument const &args) : _previousState(ccEqual) { DataNodeArgumentVector const &argList = args.getListValue(); // Symbol, report up, compare to name, compare to data. assert(argList.size() == 4); std::string const &symbol = argList[0].getStringValue(); _reportUp = argList[1].getBooleanValue(); std::string const &compareToName = argList[2].getStringValue(); GenericDataNodeFactory const &factory = argList[3].getValue< GenericDataNodeFactory >(); _msg = "Price crossed "; if (_reportUp) _msg += "above "; else _msg += "below "; _msg += compareToName; _msg += ": "; addAutoLink(GenericTosDataNode::find(this, 0, _tosData, symbol)); addAutoLink(TimePassed::find(_timePassedData, symbol, compareToName)); addAutoLink(factory.find(_compareToData)); onWakeup(0); } //////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////// void initializeFastCrossedOpenClose() { GenericDataNodeFactory::sf< FastCrossedOpenClose > ("CrossedAboveClose", symbolPlaceholderObject, true, "close", GenericDataNodeFactory::findFactory("MostRecentClose")); GenericDataNodeFactory::sf< FastCrossedOpenClose > ("CrossedBelowClose", symbolPlaceholderObject, false, "close", GenericDataNodeFactory::findFactory("MostRecentClose")); GenericDataNodeFactory::sf< FastCrossedOpenClose > ("CrossedAboveOpen", symbolPlaceholderObject, true, "open", GenericDataNodeFactory::findFactory("OpenPrice")); GenericDataNodeFactory::sf< FastCrossedOpenClose > ("CrossedBelowOpen", symbolPlaceholderObject, false, "open", GenericDataNodeFactory::findFactory("OpenPrice")); }