Team Ai
Apppublic

Sumitx369/Paper_Trading_Backtesting

sourceHugging Faceupdated 4mo agoView on Hugging Face
2likes
indicators.cpp166 linesDownload Raw Back to src
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