输入/搜索内容
3
关注
224
关注者
开源优宽量化的TA库, 学习使用(含Javascript/Python/C++版本)
帮助
创建于 2021-11-05 15:50:12  
 0
 2274

代码就是最好的注释, 不懂指标如何生成的, 怎么敢说自己会用指标.
以下代码是我自己从程序员转入金融行业的时候手撸而成, 无任何复制粘贴, 希望对新手有用

javascript
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; } };
python
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
c++
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;
相关推荐
评论
全部评论 (0)
暂无数据
暂无数据
  • 1
iPhone 下载
社区
回测系统
© 2015 - ∞ YouQuant 豫ICP备19046564号