Perpustakaan TA yang dikutip oleh penemu open source, belajar menggunakannya (mengandung versi Javascript/Python/C++)

Penulis:Tidak ada, Dibuat: 2016-09-01 16:11:47, Diperbarui: 2020-04-07 16:34:37

Code adalah komentar terbaik, tidak mengerti bagaimana indikator dihasilkan, bagaimana berani mengatakan bahwa Anda akan menggunakan indikator. Kode di bawah ini dibuat dengan tangan saya sendiri ketika saya beralih dari programmer ke industri keuangan, tidak ada yang harus disalin dan ditempelkan, semoga berguna bagi pemula.

var Std = {
    _skip: function(arr, period) {
        var j = 0;
        for (var k = 0; j < arr.length; j++) {
            if (!isNaN(arr[j]))
                k++;
            if (k == period)
                break;
        }
        return j;
    },
    _sum: function(arr, num) {
        var sum = 0.0;
        for (var i = 0; i < num; i++) {
            if (!isNaN(arr[i])) {
                sum += arr[i];
            }
        }
        return sum;
    },

    _avg: function(arr, num) {
        var n = 0;
        var sum = 0.0;
        for (var i = 0; i < num; i++) {
            if (!isNaN(arr[i])) {
                sum += arr[i];
                n++;
            }
        }
        return sum / n;
    },

    _zeros: function(len) {
        var n = [];
        for (var i = 0; i < len; i++) {
            n.push(0.0);
        }
        return n;
    },

    _set: function(arr, start, end, value) {
        var e = Math.min(arr.length, end);
        for (var i = start; i < e; i++) {
            arr[i] = value;
        }
    },

    _diff: function(a, b) {
        var d = [];
        for (var i = 0; i < b.length; i++) {
            if (isNaN(a[i]) || isNaN(b[i])) {
                d.push(NaN);
            } else {
                d.push(a[i] - b[i]);
            }
        }
        return d;
    },
    _move_diff: function(a) {
        var d = [];
        for (var i = 1; i < a.length; i++) {
            d.push(a[i] - a[i - 1]);
        }
        return d;
    },
    _sma: function(S, period) {
        var R = Std._zeros(S.length);
        var j = Std._skip(S, period);
        Std._set(R, 0, j, NaN);
        if (j < S.length) {
            var sum = 0;
            for (var i = j; i < S.length; i++) {
                if (i == j) {
                    sum = Std._sum(S, i + 1);
                } else {
                    sum += S[i] - S[i - period];
                }
                R[i] = sum / period;
            }
        }
        return R;
    },

    _smma: function(S, period) {
        var R = Std._zeros(S.length);
        var j = Std._skip(S, period);
        Std._set(R, 0, j, NaN);
        if (j < S.length) {
            R[j] = Std._avg(S, j + 1);
            for (var i = j + 1; i < S.length; i++) {
                R[i] = (R[i - 1] * (period - 1) + S[i]) / period;
            }
        }
        return R;
    },
    _ema: function(S, period) {
        var R = Std._zeros(S.length);
        var multiplier = 2.0 / (period + 1);
        var j = Std._skip(S, period);
        Std._set(R, 0, j, NaN);
        if (j < S.length) {
            R[j] = Std._avg(S, j + 1);
            for (var i = j + 1; i < S.length; i++) {
                R[i] = ((S[i] - R[i - 1]) * multiplier) + R[i - 1];
            }
        }
        return R;
    },
    _cmp: function(arr, start, end, cmpFunc) {
        var v = arr[start];
        for (var i = start; i < end; i++) {
            v = cmpFunc(arr[i], v);
        }
        return v;
    },
    _filt: function(records, n, attr, iv, cmpFunc) {
        if (records.length < 2) {
            return NaN;
        }
        var v = iv;
        var pos = n !== 0 ? records.length - Math.min(records.length - 1, n) - 1 : 0;
        for (var i = records.length - 2; i >= pos; i--) {
            if (typeof(attr) !== 'undefined') {
                v = cmpFunc(v, records[i][attr]);
            } else {
                v = cmpFunc(v, records[i]);
            }
        }
        return v;
    },
    _ticks: function(records) {
        if (records.length === 0) {
            return [];
        }
        var ticks = [];
        if (typeof(records[0].Close) !== 'undefined') {
            for (var i = 0; i < records.length; i++) {
                ticks.push(records[i].Close);
            }
        } else {
            ticks = records;
        }
        return ticks;
    },
};

var TA = {
    Highest: function(records, n, attr) {
        return Std._filt(records, n, attr, Number.MIN_VALUE, Math.max);
    },
    Lowest: function(records, n, attr) {
        return Std._filt(records, n, attr, Number.MAX_VALUE, Math.min);
    },

    MA: function(records, period) {
        period = typeof(period) === 'undefined' ? 9 : period;
        return Std._sma(Std._ticks(records), period);
    },
    SMA: function(records, period) {
        period = typeof(period) === 'undefined' ? 9 : period;
        return Std._sma(Std._ticks(records), period);
    },

    EMA: function(records, period) {
        period = typeof(period) === 'undefined' ? 9 : period;
        return Std._ema(Std._ticks(records), period);
    },

    MACD: function(records, fastEMA, slowEMA, signalEMA) {
        fastEMA = typeof(fastEMA) === 'undefined' ? 12 : fastEMA;
        slowEMA = typeof(slowEMA) === 'undefined' ? 26 : slowEMA;
        signalEMA = typeof(signalEMA) === 'undefined' ? 9 : signalEMA;
        var ticks = Std._ticks(records);
        var slow = Std._ema(ticks, slowEMA);
        var fast = Std._ema(ticks, fastEMA);
        // DIF
        var dif = Std._diff(fast, slow);
        // DEA
        var signal = Std._ema(dif, signalEMA);
        var histogram = Std._diff(dif, signal);
        return [dif, signal, histogram];
    },

    BOLL: function(records, period, multiplier) {
        period = typeof(period) === 'undefined' ? 20 : period;
        multiplier = typeof(multiplier) === 'undefined' ? 2 : multiplier;
        var S = Std._ticks(records);
        for (var j = period - 1; j < S.length && isNaN(S[j]); j++);
        var UP = Std._zeros(S.length);
        var MB = Std._zeros(S.length);
        var DN = Std._zeros(S.length);
        Std._set(UP, 0, j, NaN);
        Std._set(MB, 0, j, NaN);
        Std._set(DN, 0, j, NaN);
        var sum = 0;
        for (var i = j; i < S.length; i++) {
            if (i == j) {
                for (var k = 0; k < period; k++) {
                    sum += S[k];
                }
            } else {
                sum = sum + S[i] - S[i - period];
            }
            var ma = sum / period;
            var d = 0;
            for (var k = i + 1 - period; k <= i; k++) {
                d += (S[k] - ma) * (S[k] - ma);
            }
            var stdev = Math.sqrt(d / period);
            var up = ma + (multiplier * stdev);
            var dn = ma - (multiplier * stdev);
            UP[i] = up;
            MB[i] = ma;
            DN[i] = dn;
        }
        // upper, middle, lower
        return [UP, MB, DN];
    },

    KDJ: function(records, n, k, d) {
        n = typeof(n) === 'undefined' ? 9 : n;
        k = typeof(k) === 'undefined' ? 3 : k;
        d = typeof(d) === 'undefined' ? 3 : d;

        var RSV = Std._zeros(records.length);
        Std._set(RSV, 0, n - 1, NaN);
        var K = Std._zeros(records.length);
        var D = Std._zeros(records.length);
        var J = Std._zeros(records.length);

        var hs = Std._zeros(records.length);
        var ls = Std._zeros(records.length);
        for (var i = 0; i < records.length; i++) {
            hs[i] = records[i].High;
            ls[i] = records[i].Low;
        }

        for (var i = 0; i < records.length; i++) {
            if (i >= (n - 1)) {
                var c = records[i].Close;
                var h = Std._cmp(hs, i - (n - 1), i + 1, Math.max);
                var l = Std._cmp(ls, i - (n - 1), i + 1, Math.min);
                RSV[i] = 100 * ((c - l) / (h - l));
                K[i] = (1 * RSV[i] + (k - 1) * K[i - 1]) / k;
                D[i] = (1 * K[i] + (d - 1) * D[i - 1]) / d;
            } else {
                K[i] = D[i] = 50;
                RSV[i] = 0;
            }
            J[i] = 3 * K[i] - 2 * D[i];
        }
        // remove prefix
        for (var i = 0; i < n - 1; i++) {
            K[i] = D[i] = J[i] = NaN;
        }
        return [K, D, J];
    },

    RSI: function(records, period) {
        period = typeof(period) === 'undefined' ? 14 : period;
        var i;
        var n = period;
        var rsi = Std._zeros(records.length);
        Std._set(rsi, 0, rsi.length, NaN);
        if (records.length < n) {
            return rsi;
        }
        var ticks = Std._ticks(records);
        var deltas = Std._move_diff(ticks);
        var seed = deltas.slice(0, n);
        var up = 0;
        var down = 0;
        for (i = 0; i < seed.length; i++) {
            if (seed[i] >= 0) {
                up += seed[i];
            } else {
                down += seed[i];
            }
        }
        up /= n;
        down = -(down /= n);
        var rs = down != 0 ? up / down : 0;
        rsi[n] = 100 - 100 / (1 + rs);
        var delta = 0;
        var upval = 0;
        var downval = 0;
        for (i = n + 1; i < ticks.length; i++) {
            delta = deltas[i - 1];
            if (delta > 0) {
                upval = delta;
                downval = 0;
            } else {
                upval = 0;
                downval = -delta;
            }
            up = (up * (n - 1) + upval) / n;
            down = (down * (n - 1) + downval) / n;
            rs = up / down;
            rsi[i] = 100 - 100 / (1 + rs);
        }
        return rsi;
    },
    OBV: function(records) {
        if (records.length === 0) {
            return [];
        }
        if (typeof(records[0].Close) === 'undefined') {
            throw "argument must KLine";
        }
        var R = [];
        for (var i = 0; i < records.length; i++) {
            if (i === 0) {
                R[i] = records[i].Volume;
            } else if (records[i].Close >= records[i - 1].Close) {
                R[i] = R[i - 1] + records[i].Volume;
            } else {
                R[i] = R[i - 1] - records[i].Volume;
            }
        }
        return R;
    },
    ATR: function(records, period) {
        if (records.length === 0) {
            return [];
        }
        if (typeof(records[0].Close) === 'undefined') {
            throw "argument must KLine";
        }
        period = typeof(period) === 'undefined' ? 14 : period;
        var R = Std._zeros(records.length);
        var sum = 0;
        var n = 0;
        for (var i = 0; i < records.length; i++) {
            var TR = 0;
            if (i == 0) {
                TR = records[i].High - records[i].Low;
            } else {
                TR = Math.max(records[i].High - records[i].Low, Math.abs(records[i].High - records[i - 1].Close), Math.abs(records[i - 1].Close - records[i].Low));
            }
            sum += TR;
            if (i < period) {
                n = sum / (i + 1);
            } else {
                n = (((period - 1) * n) + TR) / period;
            }
            R[i] = n;
        }
        return R;
    },
    Alligator: function(records, jawLength, teethLength, lipsLength) {
        jawLength = typeof(jawLength) === 'undefined' ? 13 : jawLength;
        teethLength = typeof(teethLength) === 'undefined' ? 8 : teethLength;
        lipsLength = typeof(lipsLength) === 'undefined' ? 5 : lipsLength;
        var ticks = [];
        for (var i = 0; i < records.length; i++) {
            ticks.push((records[i].High + records[i].Low) / 2);
        }
        return [
            [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN].concat(Std._smma(ticks, jawLength)), // jaw (blue)
            [NaN, NaN, NaN, NaN, NaN].concat(Std._smma(ticks, teethLength)), // teeth (red)
            [NaN, NaN, NaN].concat(Std._smma(ticks, lipsLength)), // lips (green)
        ];
    },
    CMF: function(records, periods) {
        periods = periods || 20;
        var ret = [];
        var sumD = 0;
        var sumV = 0;
        var arrD = [];
        var arrV = [];
        for (var i = 0; i < records.length; i++) {
            var d = (records[i].High == records[i].Low) ? 0 : (2 * records[i].Close - records[i].Low - records[i].High) / (records[i].High - records[i].Low) * records[i].Volume;
            arrD.push(d);
            arrV.push(records[i].Volume);
            sumD += d;
            sumV += records[i].Volume;
            if (i >= periods) {
                sumD -= arrD.shift();
                sumV -= arrV.shift();
            }
            ret.push(sumD / sumV);
        }
        return ret;
    }
};
import math

class Std:
    @staticmethod
    def _skip(arr, period):
        k = 0
        for j in xrange(0, len(arr)):
            if arr[j] is not None:
                k+=1
            if k == period:
                break
        return j

    @staticmethod
    def _sum(arr, num):
        s = 0.0
        for i in xrange(0, num):
            if arr[i] is not None:
                s += arr[i]
        return s

    @staticmethod
    def _avg(arr, num):
        if len(arr) == 0:
            return 0
        s = 0.0
        n = 0
        for i in xrange(0, min(len(arr), num)):
            if arr[i] is not None:
                s += arr[i]
                n += 1
        if n == 0:
            return 0
        return s / n

    @staticmethod
    def _zeros(n):
        return [0.0] * n 

    @staticmethod
    def _set(arr, start, end, value):
        for i in xrange(start, min(len(arr), end)):
            arr[i] = value

    @staticmethod
    def _diff(a, b):
        d = [None] * len(b)
        for i in xrange(0, len(b)):
            if a[i] is not None and b[i] is not None:
                d[i] = a[i] - b[i]
        return d

    @staticmethod
    def _move_diff(a):
        d = [None] * (len(a)-1)
        for i in xrange(1, len(a)):
            d[i-1] = a[i] - a[i-1]
        return d

    @staticmethod
    def _cmp(arr, start, end, cmpFunc):
        v = arr[start]
        for i in xrange(start, end):
            v = cmpFunc(arr[i], v)
        return v

    @staticmethod
    def _filt(records, n, attr, iv, cmpFunc):
        if len(records) < 2:
            return None
        v = iv
        pos = 0
        if n != 0:
            pos = len(records) - min(len(records)-1, n) - 1
        for i in xrange(len(records)-2, pos-1, -1):
            if records[i] is not None:
                if attr is not None:
                    v = cmpFunc(v, records[i][attr])
                else:
                    v = cmpFunc(v, records[i])
        return v

    @staticmethod
    def _ticks(records):
        if len(records) == 0:
            return []
        if 'Close' not in records[0]:
            return records

        ticks = [None] * len(records)
        for i in xrange(0, len(records)):
            ticks[i] = records[i]['Close']
        return ticks

    @staticmethod
    def _sma(S, period):
        R = Std._zeros(len(S))
        j = Std._skip(S, period)
        Std._set(R, 0, j, None)
        if j < len(S):
            s = 0
            for i in xrange(j, len(S)):
                if i == j:
                    s = Std._sum(S, i+1)
                else:
                    s += S[i] - S[i-period]
                R[i] = s / period
        return R

    @staticmethod
    def _smma(S, period):
        R = Std._zeros(len(S))
        j = Std._skip(S, period)
        Std._set(R, 0, j, None)
        if j < len(S):
            R[j] = Std._avg(S, j+1)
            for i in xrange(j+1, len(S)):
                R[i] = (R[i-1] * (period-1) + S[i]) / period
        return R

    @staticmethod
    def _ema(S, period):
        R = Std._zeros(len(S))
        multiplier = 2.0 / (period + 1)
        j = Std._skip(S, period)
        Std._set(R, 0, j, None)
        if j < len(S):
            R[j] = Std._avg(S, j+1)
            for i in xrange(j+1, len(S)):
                R[i] = ((S[i] - R[i-1] ) * multiplier) + R[i-1]
        return R

class TA:
    @staticmethod
    def Highest(records, n, attr=None):
        return Std._filt(records, n, attr, 5e-324, max)

    @staticmethod
    def Lowest(records, n, attr=None):
        return Std._filt(records, n, attr, 1.7976931348623157e+308, min)

    @staticmethod
    def MA(records, period=9):
        return Std._sma(Std._ticks(records), period)

    @staticmethod
    def SMA(records, period=9):
        return Std._sma(Std._ticks(records), period)

    @staticmethod
    def EMA(records, period=9):
        return Std._ema(Std._ticks(records), period)

    @staticmethod
    def MACD(records, fastEMA=12, slowEMA=26, signalEMA=9):
        ticks = Std._ticks(records)
        slow = Std._ema(ticks, slowEMA)
        fast = Std._ema(ticks, fastEMA)
        # DIF
        dif = Std._diff(fast, slow)
        # DEA
        signal = Std._ema(dif, signalEMA)
        histogram = Std._diff(dif, signal)
        return [ dif, signal, histogram]

    @staticmethod
    def BOLL(records, period=20, multiplier=2):
        S = Std._ticks(records)
        j = period - 1
        while j < len(S) and (S[j] is None):
            j+=1
        UP = Std._zeros(len(S))
        MB = Std._zeros(len(S))
        DN = Std._zeros(len(S))
        Std._set(UP, 0, j, None)
        Std._set(MB, 0, j, None)
        Std._set(DN, 0, j, None)
        n = 0.0
        for i in xrange(j, len(S)):
            if i == j:
                for k in xrange(0, period):
                    n += S[k]
            else:
                n = n + S[i] - S[i - period]
            ma = n / period
            d = 0
            for k in xrange(i+1-period, i+1):
                d += (S[k] - ma) * (S[k] - ma)
            stdev = math.sqrt(d / period)
            up = ma + (multiplier * stdev)
            dn = ma - (multiplier * stdev)
            UP[i] = up
            MB[i] = ma
            DN[i] = dn
        return [UP, MB, DN]

    @staticmethod
    def KDJ(records, n=9, k=3, d=3):
        RSV = Std._zeros(len(records))
        Std._set(RSV, 0, n - 1, None)
        K = Std._zeros(len(records))
        D = Std._zeros(len(records))
        J = Std._zeros(len(records))

        hs = Std._zeros(len(records))
        ls = Std._zeros(len(records))
        for i in xrange(0, len(records)):
            hs[i] = records[i]['High']
            ls[i] = records[i]['Low']

        for i in xrange(0, len(records)):
            if i >= (n - 1):
                c = records[i]['Close']
                h = Std._cmp(hs, i - (n - 1), i + 1, max)
                l = Std._cmp(ls, i - (n - 1), i + 1, min)
                RSV[i] = 100 * ((c - l) / (h - l))
                K[i] = float(1 * RSV[i] + (k - 1) * K[i - 1]) / k
                D[i] = float(1 * K[i] + (d - 1) * D[i - 1]) / d
            else:
                K[i] = D[i] = 50.0
                RSV[i] = 0.0
            J[i] = 3 * K[i] - 2 * D[i]
        # remove prefix
        for i in xrange(0, n-1):
            K[i] = D[i] = J[i] = None
        return [K, D, J]

    @staticmethod
    def RSI(records, period=14):
        n = period
        rsi = Std._zeros(len(records))
        Std._set(rsi, 0, len(rsi), None)
        if len(records) < n:
            return rsi

        ticks = Std._ticks(records)
        deltas = Std._move_diff(ticks)
        seed = deltas[:n]
        up = 0.0
        down = 0.0
        for i in xrange(0, len(seed)):
            if seed[i] >= 0:
                up += seed[i]
            else:
                down += seed[i]
        up /= n
        down /= n
        down = -down
        if down != 0:
            rs = up / down
        else:
            rs = 0
        rsi[n] = 100 - 100 / (1 + rs)
        delta = 0.0
        upval = 0.0
        downval = 0.0
        for i in xrange(n+1, len(ticks)):
            delta = deltas[i - 1]
            if delta > 0:
                upval = delta
                downval = 0.0
            else:
                upval = 0.0
                downval = -delta
            up = (up * (n - 1) + upval) / n
            down = (down * (n - 1) + downval) / n
            rs = up / down
            rsi[i] = 100 - 100 / (1 + rs)
        return rsi
    @staticmethod
    def OBV(records):
        if len(records) == 0:
            return []

        if 'Close' not in records[0]:
            raise "TA.OBV argument must KLine"

        R = Std._zeros(len(records))
        for i in xrange(0, len(records)):
            if i == 0:
                R[i] = records[i]['Volume']
            elif records[i]['Close'] >= records[i - 1]['Close']:
                R[i] = R[i - 1] + records[i]['Volume']
            else:
                R[i] = R[i - 1] - records[i]['Volume']
        return R

    @staticmethod
    def ATR(records, period=14):
        if len(records) == 0:
            return []
        if 'Close' not in records[0]:
            raise "TA.ATR argument must KLine"

        R = Std._zeros(len(records))
        m = 0.0
        n = 0.0
        for i in xrange(0, len(records)):
            TR = 0
            if i == 0:
                TR = records[i]['High'] - records[i]['Low']
            else:
                TR = max(records[i]['High'] - records[i]['Low'], abs(records[i]['High'] - records[i - 1]['Close']), abs(records[i - 1]['Close'] - records[i]['Low']))
            m += TR
            if i < period:
                n = m / (i + 1)
            else:
                n = (((period - 1) * n) + TR) / period
            R[i] = n
        return R

    @staticmethod
    def Alligator(records, jawLength=13, teethLength=8, lipsLength=5):
        ticks = []
        for i in xrange(0, len(records)):
            ticks.append((records[i]['High'] + records[i]['Low']) / 2)
        return [
            [None]*8+Std._smma(ticks, jawLength), # // jaw (blue)
            [None]*5+Std._smma(ticks, teethLength), # teeth (red)
            [None]*3+Std._smma(ticks, lipsLength) # lips (green)
        ]

    @staticmethod
    def CMF(records, periods=20):
        ret = []
        sumD = 0.0
        sumV = 0.0
        arrD = []
        arrV = []
        for i in xrange(0, len(records)):
            d = 0.0
            if records[i]['High'] != records[i]['Low']:
                d = (2 * records[i]['Close'] - records[i]['Low'] - records[i]['High']) / (records[i]['High'] - records[i]['Low']) * records[i]['Volume']
            arrD.append(d)
            arrV.append(records[i]['Volume'])
            sumD += d
            sumV += records[i]['Volume']
            if i >= periods:
                sumD -= arrD.pop(0)
                sumV -= arrV.pop(0)
            ret.append(sumD / sumV)
        return ret
double _cmp_min(double a, double b) {
    return a < b ? a : b;
}

double _cmp_max(double a, double b) {
    return a > b ? a : b;
}

double _cmp_max(double a, double b, double c) {
    double d = a > b ? a : b;
    return d > c ? d : c;
}

class TAHelper {
  public:
    array<vector<double>, 3> MACD(Records &records, size_t fastEMA = 12, size_t slowEMA = 26, size_t signalEMA = 9) {
        vector<double> ticks = records.Close();
        vector<double> dif = _diff(_ema(ticks, fastEMA), _ema(ticks, slowEMA));
        vector<double> signal = _ema(dif, signalEMA);
        vector<double> histogram = _diff(dif, signal);
        return {{ dif, signal, histogram }};
    }

    array<vector<double>, 3> KDJ(Records &records, size_t n = 9, size_t k = 3, size_t d = 3) {
        size_t length = records.size();
        vector<double> RSV(length, 0);
        _set(RSV, 0, n - 1, NAN);
        vector<double> K(length, 0);
        vector<double> D(length, 0);
        vector<double> J(length, 0);

        vector<double> hs = records.High();
        vector<double> ls = records.Low();

        for (size_t i = 0; i < length; i++) {
            if (i >= size_t(n - 1)) {
                double c = records[i].Close;
                double h = _cmp(hs, i - (n - 1), i + 1, _cmp_max);
                double l = _cmp(ls, i - (n - 1), i + 1, _cmp_min);
                RSV[i] = h != l ? (100 * ((c - l) / (h - l))) : 100;
                K[i] = (1 * RSV[i] + (k - 1) * K[i - 1]) / k;
                D[i] = (1 * K[i] + (d - 1) * D[i - 1]) / d;
            } else {
                K[i] = D[i] = 50;
                RSV[i] = 0;
            }
            J[i] = 3 * K[i] - 2 * D[i];
        }
        for (size_t i = 0; i < n - 1; i++) {
            K[i] = D[i] = J[i] = NAN;
        }
        return{{ K, D, J }};
    }

    vector<double> RSI(Records &records, size_t period = 14) {
        size_t i = 0;
        size_t n = period;
        vector<double> rsi(records.size(), 0);
        _set(rsi, 0, rsi.size(), NAN);
        if (records.size() < n) {
            return rsi;
        }
        vector<double> ticks = records.Close();
        vector<double> deltas = _move_diff(ticks);
        vector<double> seed(deltas.begin(), deltas.begin() + n);
        double up = 0.0;
        double down = 0.0;
        for (i = 0; i < seed.size(); i++) {
            if (seed[i] >= 0) {
                up += seed[i];
            } else {
                down += seed[i];
            }
        }
        up /= n;
        down /= n;
        down = -down;
        double rs = down != 0 ? up / down : 0;
        rsi[n] = 100 - 100 / (1 + rs);
        double delta = 0.0;
        double upval = 0.0;
        double downval = 0.0;
        for (i = n + 1; i < ticks.size(); i++) {
            delta = deltas[i - 1];
            if (delta > 0) {
                upval = delta;
                downval = 0;
            } else {
                upval = 0;
                downval = -delta;
            }
            up = (up * (n - 1) + upval) / n;
            down = (down * (n - 1) + downval) / n;
            rs = up / down;
            rsi[i] = 100 - 100 / (1 + rs);
        }
        return rsi;
    }

    vector<double> ATR(Records &records, size_t period = 14) {
        vector<double> ret;
        if (records.size() == 0) {
            return ret;
        }
        vector<double> R(records.size(), 0);
        double sum = 0.0;
        double n = 0.0;
        for (size_t i = 0; i < records.size(); i++) {
            double TR = 0.0;
            if (i == 0) {
                TR = records[i].High - records[i].Low;
            } else {
                TR = _cmp_max(records[i].High - records[i].Low, abs(records[i].High - records[i - 1].Close), abs(records[i - 1].Close - records[i].Low));
            }
            sum += TR;
            if (i < period) {
                n = sum / (i + 1);
            } else {
                n = (((period - 1) * n) + TR) / period;
            }
            R[i] = n;
        }
        return R;
    }

    vector<double> OBV(Records &records) {
        vector<double> R;
        if (records.size() == 0) {
            return R;
        }
        for (size_t i = 0; i < records.size(); i++) {
            if (i == 0) {
                R.push_back(records[i].Volume);
            } else if (records[i].Close >= records[i - 1].Close) {
                R.push_back(R[i - 1] + records[i].Volume);
            } else {
                R.push_back(R[i - 1] - records[i].Volume);
            }
        }
        return R;
    }

    vector<double> MA(Records &records, size_t period = 9) {
        return _sma(records.Close(), period);
    }

    vector<double> EMA(Records &records, size_t period = 9) {
        return _ema(records.Close(), period);
    }

    array<vector<double>, 3> BOLL(Records &records, size_t period = 20, double multiplier = 2) {
        vector<double> S = records.Close();
        size_t j = 0;
        for (j = period - 1; j < S.size() && isnan(S[j]); j++);
        vector<double> UP(S.size(), 0);
        vector<double> MB(S.size(), 0);
        vector<double> DN(S.size(), 0);
        _set(UP, 0, j, NAN);
        _set(MB, 0, j, NAN);
        _set(DN, 0, j, NAN);
        double sum = 0;
        for (size_t i = j; i < S.size(); i++) {
            if (i == j) {
                for (size_t k = 0; k < period; k++) {
                    sum += S[k];
                }
            } else {
                sum = sum + S[i] - S[i - period];
            }
            double ma = sum / period;
            double d = 0.0;
            for (size_t k = i + 1 - period; k <= i; k++) {
                d += (S[k] - ma) * (S[k] - ma);
            }
            double stdev = sqrt(d / period);
            double up = ma + (multiplier * stdev);
            double dn = ma - (multiplier * stdev);
            UP[i] = up;
            MB[i] = ma;
            DN[i] = dn;
        }
        return {{ UP, MB, DN }};
    }

    array<vector<double>, 3> Alligator(Records &records, size_t jawLength = 13, size_t teethLength = 8, size_t lipsLength = 5) {
        vector<double> ticks;
        for (size_t i = 0; i < records.size(); i++) {
            ticks.push_back((records[i].High + records[i].Low) / 2);
        }
        vector<double> jaw = _smma(ticks, jawLength);
        jaw.insert(jaw.begin(), 8, NAN);
        vector<double> teeth = _smma(ticks, teethLength);
        teeth.insert(teeth.begin(), 5, NAN);
        vector<double> lips = _smma(ticks, lipsLength);
        lips.insert(lips.begin(), 3, NAN);
        return{{ jaw, teeth, lips }};
    }

    vector<double> CMF(Records &records, size_t periods = 20) {
        vector<double> ret;
        double sumD = 0.0;
        double sumV = 0.0;
        vector<double> arrD;
        vector<double> arrV;
        for (size_t i = 0; i < records.size(); i++) {
            double d = (records[i].High == records[i].Low) ? 0 : (2 * records[i].Close - records[i].Low - records[i].High) / (records[i].High - records[i].Low) * records[i].Volume;
            arrD.push_back(d);
            arrV.push_back(records[i].Volume);
            sumD += d;
            sumV += records[i].Volume;
            if (i >= periods) {
                sumD -= arrD.front();
                arrD.erase(arrD.begin());
                sumV -= arrV.front();
                arrV.erase(arrV.begin());
            }
            ret.push_back(sumD / sumV);
        }
        return ret;
    }

    double Highest(vector<double> records, size_t n) {
        return _filt(records, n, NAN, _cmp_max);
    }

    double Lowest(vector<double> records, size_t n) {
        return _filt(records, n, NAN, _cmp_min);
    }

    double _filt(vector<double> records, double n, double iv, double(*pfun) (double a, double b)) {
        if (records.size() < 2) {
            return NAN;
        }
        double v = iv;
        double pos = n != 0 ? records.size() - _cmp_min(records.size() - 1, n) - 1 : 0;
        for (size_t i = records.size() - 2; i >= pos; i--) {
            v = pfun(v, records[i]);
        }
        return v;
    }

    vector<double> _smma(vector<double> S, size_t period) {
        size_t length = S.size();
        vector<double> R(length, 0);
        size_t j = _skip(S, period);
        _set(R, 0, j, NAN);
        if (j < length) {
            R[j] = _avg(S, j + 1);
            for (size_t i = j + 1; i < length; i++) {
                R[i] = (R[i - 1] * (period - 1) + S[i]) / period;
            }
        }
        return R;
    }

    vector<double> _move_diff(vector<double> a) {
        vector<double> d;
        for (size_t i = 1; i < a.size(); i++) {
            d.push_back(a[i] - a[i - 1]);
        }
        return d;
    }

    vector<double> _ema(vector<double> S, size_t period) {
        size_t length = S.size();
        vector<double> R(length, 0);
        double multiplier = 2.0 / (period + 1);
        size_t j = _skip(S, period);
        _set(R, 0, j, NAN);
        if (j < length) {
            R[j] = _avg(S, j + 1);
            for (size_t i = j + 1; i < length; i++) {
                R[i] = (S[i] - R[i - 1]) * multiplier + R[i - 1];
            }
        }
        return R;
    }

    vector<double> _sma(vector<double> S, size_t period) {
        vector<double> R(S.size(), 0);
        size_t j = _skip(S, period);
        _set(R, 0, j, NAN);
        if (j < S.size()) {
            double sum = 0;
            for (size_t i = j; i < S.size(); i++) {
                if (i == j) {
                    sum = _sum(S, i + 1);
                } else {
                    if (i < period) {
                        R[i] = NAN;
                        continue;
                    }
                    sum += S[i] - S[i - period];
                }
                R[i] = sum / period;
            }
        }
        return R;
    }

    double _sum(vector<double> arr, size_t num) {
        double sum = 0.0;
        for (size_t i = 0; i < num; i++) {
            if (!isnan(arr[i])) {
                sum += arr[i];
            }
        }
        return sum;
    }

    vector<double> _diff(vector<double> a, vector<double> b) {
        vector<double> d;
        for (size_t i = 0; i < b.size(); i++) {
            if (isnan(a[i]) || isnan(b[i])) {
                d.push_back(NAN);
            } else {
                d.push_back(a[i] - b[i]);
            }
        }
        return d;
    }

    double _avg(vector<double> arr, double num) {
        size_t n = 0;
        double sum = 0.0;
        for (size_t i = 0; i < num; i++) {
            if (!isnan(arr[i])) {
                sum += arr[i];
                n++;
            }
        }
        return sum / n;
    }

    void _set(vector<double> &arr, size_t start, size_t end, double value) {
        size_t e = _cmp_min(arr.size(), end);
        for (size_t i = start; i < e; i++) {
            arr[i] = value;
        }
    }

    size_t _skip(vector<double> arr, size_t period) {
        size_t j = 0;
        for (size_t k = 0; j < arr.size(); j++) {
            if (!isnan(arr[j])) {
                k++;
            }
            if (k == period) {
                break;
            }
        }
        return j;
    }

    double _cmp(vector<double> arr, size_t start, size_t end, double(*pfun) (double a, double b)) {
        double v = arr[start];
        for (size_t i = start; i < end; i++) {
            v = pfun(arr[i], v);
        }
        return v;
    }
};

TAHelper TA;

Berkaitan

Lebih banyak

ScottliyqSaya belajar, dan itu sangat mudah.

ScottliyqSaya belajar, dan itu sangat mudah.

pixy3173 666

Saudara laki-lakiSaya sangat membutuhkannya. Terima kasih.

MomoxIni sangat sulit, rasanya lebih banyak kode py daripada js, tidak ilmiah.

Ini adalah nama ibu saya.Bersama-sama

Tidak adaBanyak orang yang menulis Python suka membuat kode yang sulit dipahami, tetapi saya tidak suka melakukannya. Saya menulis kode dengan gaya yang mudah dipahami. Tidak menggunakan sihir hitam.