Sumitx369/Paper_Trading_Backtesting
2
1#include "indicators.hpp"2 3#include <cmath>4#include <limits>5 6namespace ind {7 8namespace {9const double NaN = std::numeric_limits<double>::quiet_NaN();10inline bool ok(double v) { return !std::isnan(v); }11} // namespace12 13Vec sma(const Vec& x, int n) {14 const int sz = static_cast<int>(x.size());15 Vec out(sz, NaN);16 if (n <= 0) return out;17 double sum = 0.0;18 int count = 0;19 for (int i = 0; i < sz; ++i) {20 if (!ok(x[i])) { sum = 0; count = 0; continue; } // reset on gaps21 sum += x[i];22 ++count;23 if (i >= n && ok(x[i - n])) sum -= x[i - n];24 if (count >= n) out[i] = sum / n;25 }26 return out;27}28 29Vec ema(const Vec& x, int n) {30 const int sz = static_cast<int>(x.size());31 Vec out(sz, NaN);32 if (n <= 0) return out;33 const double alpha = 2.0 / (n + 1.0);34 double prev = NaN;35 double seed_sum = 0.0;36 int seed_count = 0;37 for (int i = 0; i < sz; ++i) {38 if (!ok(x[i])) { // gap: reset the accumulator39 prev = NaN;40 seed_sum = 0.0;41 seed_count = 0;42 continue;43 }44 if (!ok(prev)) {45 seed_sum += x[i];46 ++seed_count;47 if (seed_count == n) {48 prev = seed_sum / n;49 out[i] = prev;50 }51 } else {52 prev = alpha * x[i] + (1.0 - alpha) * prev;53 out[i] = prev;54 }55 }56 return out;57}58 59Vec rsi(const Vec& close, int n) {60 const int sz = static_cast<int>(close.size());61 Vec out(sz, NaN);62 if (n <= 0 || sz <= n) return out;63 64 double avg_gain = 0.0, avg_loss = 0.0;65 // Seed with the first n deltas (indices 1..n).66 for (int i = 1; i <= n; ++i) {67 double d = close[i] - close[i - 1];68 if (d >= 0) avg_gain += d; else avg_loss -= d;69 }70 avg_gain /= n;71 avg_loss /= n;72 auto rsi_of = [](double g, double l) {73 if (l == 0.0) return 100.0;74 double rs = g / l;75 return 100.0 - 100.0 / (1.0 + rs);76 };77 out[n] = rsi_of(avg_gain, avg_loss);78 for (int i = n + 1; i < sz; ++i) {79 double d = close[i] - close[i - 1];80 double gain = d > 0 ? d : 0.0;81 double loss = d < 0 ? -d : 0.0;82 avg_gain = (avg_gain * (n - 1) + gain) / n;83 avg_loss = (avg_loss * (n - 1) + loss) / n;84 out[i] = rsi_of(avg_gain, avg_loss);85 }86 return out;87}88 89Vec rolling_std(const Vec& x, int n) {90 const int sz = static_cast<int>(x.size());91 Vec out(sz, NaN);92 if (n <= 0) return out;93 for (int i = n - 1; i < sz; ++i) {94 double mean = 0.0;95 bool gap = false;96 for (int j = i - n + 1; j <= i; ++j) {97 if (!ok(x[j])) { gap = true; break; }98 mean += x[j];99 }100 if (gap) continue;101 mean /= n;102 double var = 0.0;103 for (int j = i - n + 1; j <= i; ++j) {104 double d = x[j] - mean;105 var += d * d;106 }107 out[i] = std::sqrt(var / n); // population std108 }109 return out;110}111 112Vec bb_mid(const Vec& close, int n) { return sma(close, n); }113 114Vec bb_upper(const Vec& close, int n, double k) {115 Vec mid = sma(close, n);116 Vec sd = rolling_std(close, n);117 Vec out(mid.size(), NaN);118 for (size_t i = 0; i < mid.size(); ++i)119 if (ok(mid[i]) && ok(sd[i])) out[i] = mid[i] + k * sd[i];120 return out;121}122 123Vec bb_lower(const Vec& close, int n, double k) {124 Vec mid = sma(close, n);125 Vec sd = rolling_std(close, n);126 Vec out(mid.size(), NaN);127 for (size_t i = 0; i < mid.size(); ++i)128 if (ok(mid[i]) && ok(sd[i])) out[i] = mid[i] - k * sd[i];129 return out;130}131 132void macd(const Vec& close, int fast, int slow, int signal,133 Vec& line, Vec& sig, Vec& hist) {134 Vec ef = ema(close, fast);135 Vec es = ema(close, slow);136 const size_t sz = close.size();137 line.assign(sz, NaN);138 for (size_t i = 0; i < sz; ++i)139 if (ok(ef[i]) && ok(es[i])) line[i] = ef[i] - es[i];140 sig = ema(line, signal); // ema tolerates the NaN prefix of `line`141 hist.assign(sz, NaN);142 for (size_t i = 0; i < sz; ++i)143 if (ok(line[i]) && ok(sig[i])) hist[i] = line[i] - sig[i];144}145 146Vec atr(const Vec& high, const Vec& low, const Vec& close, int n) {147 const int sz = static_cast<int>(close.size());148 Vec out(sz, NaN);149 if (n <= 0 || sz <= n) return out;150 Vec tr(sz, NaN);151 for (int i = 1; i < sz; ++i) {152 double hl = high[i] - low[i];153 double hc = std::fabs(high[i] - close[i - 1]);154 double lc = std::fabs(low[i] - close[i - 1]);155 tr[i] = std::max(hl, std::max(hc, lc));156 }157 double sum = 0.0;158 for (int i = 1; i <= n; ++i) sum += tr[i];159 out[n] = sum / n;160 for (int i = n + 1; i < sz; ++i)161 out[i] = (out[i - 1] * (n - 1) + tr[i]) / n;162 return out;163}164 165} // namespace ind166 