#include #include "StochasticFormula.h" StochasticFormula::StochasticFormula() : _inputsAreValid(false), _secondSmaValid(false) { } StochasticFormula::StochasticFormula(int rangeCount, int pKSmaCount, int pDSmaCount) { setParams(rangeCount, pKSmaCount, pDSmaCount); } void StochasticFormula::setParams(int rangeCount, int pKSmaCount, int pDSmaCount) { reset(); if ((rangeCount > 0) && (pKSmaCount > 0) && (pDSmaCount > 0)) { _inputsAreValid = true; _rangeCount = rangeCount; _pKSmaCount = pKSmaCount; _pDSmaCount = pDSmaCount; } else _inputsAreValid = false; } int StochasticFormula::getDayCount() const { return _data.size(); } void StochasticFormula::limitDayCount(int days) { if (days < getDayCount()) { _data.resize(days); _secondSmaValid = false; } } void StochasticFormula::addDay(double high, double low, double close) { if (!_inputsAreValid) // Note: This means that addDay() does not always increment getDayCount(). // One proposed way to use this class is to create a loop which calls // addDay() unilt getDayCount() is big enough. If you tried that, and the // inputs were wrong, you'd see an infinite loop. return; { Row row; row.high = high; row.low = low; row.positionInRange = NAN; row.firstSma = NAN; _data.push_back(row); } Row &newRow = _data[_data.size() - 1]; if (getDayCount() >= _rangeCount) { double highestHigh = high; double lowestLow = low; for (std::vector< Row >::const_iterator it = _data.end() - _rangeCount; it != _data.end(); it++) { // Look at _rangeCount items. That's the current row, plus // (_rangeCount - 1) items from history. setParams ensures that // _rangeCount is at least one, so that makes this algorithm a little // simpler. highestHigh = std::max(highestHigh, it->high); lowestLow = std::min(lowestLow, it->low); } newRow.positionInRange = (close - lowestLow) / (highestHigh - lowestLow) * 100.0; } if (getDayCount() >= _pKSmaCount) { double total = 0.0; for (std::vector< Row >::const_iterator it = _data.end() - _pKSmaCount; it != _data.end(); it++) total += it->positionInRange; newRow.firstSma = total / _pKSmaCount; } // We compute a lot of stuff here because we know we'll need it one way or // another. But we defer on this last item because we often won't need it. // This saves both memory and time, because we only save the last one. _secondSmaValid = false; } void StochasticFormula::getValues(bool &valid, double &pK, double &pD) const { valid = false; if (!_inputsAreValid) return; if (getDayCount() < _pDSmaCount) return; pK = _data[getDayCount() - 1].firstSma; if (!isfinite(pK)) return; if (!_secondSmaValid) { double total = 0.0; for (std::vector< Row >::const_iterator it = _data.end() - _pDSmaCount; it != _data.end(); it++) total += it->firstSma; _secondSma = total / _pDSmaCount; _secondSmaValid = true; } pD = _secondSma; if (!isfinite(pD)) return; valid = true; }