#include "ConfirmedCrossing.h" #include "../data_framework/NormalVolumeBreakBars.h" #include "../data_framework/GenericTosData.h" #include "../alert_framework/AlertBase.h" #include "../misc_framework/CsvFileDataNodes.h" class ConfirmedCrossing : public Alert { private: enum { wPrice, wBar }; GenericDataNode *_priceLevelDataNode; NormalVolumeBreakBars *_barData; std::string _introString; bool _reportAbove; bool _recentPricesValid; AboveOrBelow _currentState; double _lowestRecentPrice; double _highestRecentPrice; double _lastPrice; // Cache this strictly for performance reasons. void newPriceLevel(); void updateRecentPriceLevels(); void newBarData(); void onWakeup(int msgId); ConfirmedCrossing(DataNodeArgument const &args); friend class GenericDataNodeFactory; }; ConfirmedCrossing::ConfirmedCrossing(DataNodeArgument const &args) : _recentPricesValid(false), _currentState(ccEqual) { DataNodeArgumentVector const &argList = args.getListValue(); assert(argList.size() == 4); // (Symbol, PriceLevelFactory, PriceLevelName, ReportAbove) const std::string symbol = argList[0].getStringValue(); DataNodeArgument const &factory = argList[1]; const std::string priceLevelName = argList[2].getStringValue(); _reportAbove = argList[3].getBooleanValue(); _introString = "Price crossed "; if (_reportAbove) _introString += "above"; else _introString += "below"; _introString += ' '; _introString += priceLevelName; _introString += " ("; addAutoLink(GenericDataNodeFactory::replaceAndFind (factory, this, wPrice, _priceLevelDataNode, symbolPlaceholder, symbol)); addAutoLink(NormalVolumeBreakBars::find(this, wBar, _barData, symbol)); newPriceLevel(); newBarData(); } void ConfirmedCrossing::newPriceLevel() { bool currentlyValid; _priceLevelDataNode->getDouble(currentlyValid, _lastPrice); if (currentlyValid) if (_recentPricesValid) { _lowestRecentPrice = std::min(_lowestRecentPrice, _lastPrice); _highestRecentPrice = std::max(_highestRecentPrice, _lastPrice); } else { _lowestRecentPrice = _lastPrice; _highestRecentPrice = _lastPrice; _recentPricesValid = true; } else { _recentPricesValid = false; _currentState = ccEqual; } } void ConfirmedCrossing::updateRecentPriceLevels() { _priceLevelDataNode->getDouble(_recentPricesValid, _lastPrice); if (_recentPricesValid) { _lowestRecentPrice = _lastPrice; _highestRecentPrice = _lastPrice; } } static const std::string finalString = "). Confirmed by volume."; void ConfirmedCrossing::newBarData() { if (!_recentPricesValid) _currentState = ccEqual; else { AboveOrBelow newState = ccEqual; if (int barCount = _barData->getBlockCount()) { VolumeBlock const &lastBar = _barData->getBlocks()[barCount - 1]; if (lastBar.low > _highestRecentPrice) newState = ccAbove; else if (lastBar.low < _lowestRecentPrice) newState = ccBelow; } if ((_reportAbove && (newState == ccAbove) && (_currentState == ccBelow)) || ((!_reportAbove) && (newState == ccBelow) && (_currentState == ccAbove))) { std::string lastPrice = priceToString(_lastPrice); report(_introString + lastPrice + finalString, "lp=" + lastPrice); } if (newState != ccEqual) _currentState = newState; } updateRecentPriceLevels(); } void ConfirmedCrossing::onWakeup(int msgId) { switch (msgId) { case wPrice: newPriceLevel(); break; case wBar: newBarData(); break; } } void initializeConfirmedCrossing() { GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedAboveVWAP", symbolPlaceholderObject, GenericDataNodeFactory::findFactory("VWAP"), "VWAP", true); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedBelowVWAP", symbolPlaceholderObject, GenericDataNodeFactory::findFactory("VWAP"), "VWAP", false); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedAbove200Day", symbolPlaceholderObject, makeCsvFactory("TC_OvernightData.csv", "200 Day SMA", symbolPlaceholderObject), "200 day SMA", true); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedBelow200Day", symbolPlaceholderObject, makeCsvFactory("TC_OvernightData.csv", "200 Day SMA", symbolPlaceholderObject), "200 day SMA", false); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedAbove50Day", symbolPlaceholderObject, makeCsvFactory("TC_OvernightData.csv", "50 Day SMA", symbolPlaceholderObject), "50 day SMA", true); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedBelow50Day", symbolPlaceholderObject, makeCsvFactory("TC_OvernightData.csv", "50 Day SMA", symbolPlaceholderObject), "50 day SMA", false); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedAbove20Day", symbolPlaceholderObject, makeCsvFactory("TC_OvernightData.csv", "20 Day SMA", symbolPlaceholderObject), "20 day SMA", true); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedBelow20Day", symbolPlaceholderObject, makeCsvFactory("TC_OvernightData.csv", "20 Day SMA", symbolPlaceholderObject), "20 day SMA", false); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedAboveCloseConfirmed", symbolPlaceholderObject, GenericDataNodeFactory::findFactory("MostRecentClose"), "close", true); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedBelowCloseConfirmed", symbolPlaceholderObject, GenericDataNodeFactory::findFactory("MostRecentClose"), "close", false); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedAboveOpenConfirmed", symbolPlaceholderObject, GenericDataNodeFactory::findFactory("OpenPrice"), "open", true); GenericDataNodeFactory::sf< ConfirmedCrossing > ("CrossedBelowOpenConfirmed", symbolPlaceholderObject, GenericDataNodeFactory::findFactory("OpenPrice"), "open", false); }