def kst_oscillator(close_arr, r1, r2, r3, r4, n1, n2, n3, n4): """Calculate KST Oscillator for given data. :param close_arr: close price of the bar, expect series from cudf :param r1: r1 time steps :param r2: r2 time steps :param r3: r3 time steps :param r4: r4 time steps :param n1: n1 time steps :param n2: n2 time steps :param n3: n3 time steps :param n4: n4 time steps :return: KST Oscillator in cudf.Series """ M1 = diff(close_arr, r1 - 1) N1 = shift(close_arr, r1 - 1) M2 = diff(close_arr, r2 - 1) N2 = shift(close_arr, r2 - 1) M3 = diff(close_arr, r3 - 1) N3 = shift(close_arr, r3 - 1) M4 = diff(close_arr, r4 - 1) N4 = shift(close_arr, r4 - 1) term1 = Rolling(n1, division(M1, N1)).sum() term2 = scale(Rolling(n2, division(M2, N2)).sum(), 2.0) term3 = scale(Rolling(n3, division(M3, N3)).sum(), 3.0) term4 = scale(Rolling(n4, division(M4, N4)).sum(), 4.0) KST = summation(summation(summation(term1, term2), term3), term4) return cudf.Series(KST)
def port_average_directional_movement_index(asset_indicator, high_arr, low_arr, close_arr, n, n_ADX): """Calculate the port Average Directional Movement Index for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param n: time steps to do EWM average :param n_ADX: time steps to do EWM average of ADX :return: Average Directional Movement Index in cudf.Series """ UpI, DoI = upDownMove(high_arr.data.to_gpu_array(), low_arr.data.to_gpu_array()) tr = port_true_range(asset_indicator.to_gpu_array(), high_arr.data.to_gpu_array(), low_arr.data.to_gpu_array(), close_arr.data.to_gpu_array()) ATR = PEwm(n, tr, asset_indicator).mean() PosDI = division(PEwm(n, UpI, asset_indicator).mean(), ATR) NegDI = division(PEwm(n, DoI, asset_indicator).mean(), ATR) NORM = division(abs_arr(substract(PosDI, NegDI)), summation(PosDI, NegDI)) port_mask_nan(asset_indicator.data.to_gpu_array(), NORM, -1, 0) ADX = cudf.Series(PEwm(n_ADX, NORM, asset_indicator).mean()) return ADX
def coppock_curve(close_arr, n): """Calculate Coppock Curve for given data. :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: Coppock Curve in cudf.Series """ M = diff(close_arr, int(n * 11 / 10) - 1) N = shift(close_arr, int(n * 11 / 10) - 1) ROC1 = division(M, N) M = diff(close_arr, int(n * 14 / 10) - 1) N = shift(close_arr, int(n * 14 / 10) - 1) ROC2 = division(M, N) Copp = Ewm(n, summation(ROC1, ROC2)).mean() return cudf.Series(Copp)
def port_vortex_indicator(asset_indicator, high_arr, low_arr, close_arr, n): """Calculate the port Vortex Indicator for given data. Vortex Indicator described here: http://www.vortexindicator.com/VFX_VORTEX.PDF :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param n: time steps to do EWM average :return: Vortex Indicator in cudf.Series """ TR = port_true_range(asset_indicator.to_gpu_array(), high_arr.data.to_gpu_array(), low_arr.data.to_gpu_array(), close_arr.data.to_gpu_array()) VM = port_lowhigh_diff(asset_indicator.to_gpu_array(), high_arr.data.to_gpu_array(), low_arr.data.to_gpu_array()) VI = division(Rolling(n, VM).sum(), Rolling(n, TR).sum()) port_mask_nan(asset_indicator.data.to_gpu_array(), VI, 0, n - 1) return cudf.Series(VI)
def ultimate_oscillator(high_arr, low_arr, close_arr): """Calculate Ultimate Oscillator for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :return: Ultimate Oscillator in cudf.Series """ TR_l, BP_l = ultimate_osc(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) term1 = division(scale(Rolling(7, BP_l).sum(), 4.0), Rolling(7, TR_l).sum()) term2 = division(scale(Rolling(14, BP_l).sum(), 2.0), Rolling(14, TR_l).sum()) term3 = division(Rolling(28, BP_l).sum(), Rolling(28, TR_l).sum()) UltO = summation(summation(term1, term2), term3) return cudf.Series(UltO, nan_as_null=False)
def bollinger_bands(close_arr, n): """Calculate the Bollinger Bands. See https://www.investopedia.com/terms/b/bollingerbands.asp for details :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: b1 b2 """ MA = Rolling(n, close_arr).mean() MSD = Rolling(n, close_arr).std() close_arr_gpu = numba.cuda.device_array_like(close_arr.data.to_gpu_array()) close_arr_gpu[:] = close_arr.data.to_gpu_array()[:] close_arr_gpu[0:n - 1] = math.nan MSD_4 = scale(MSD, 4.0) b1 = division(MSD_4, MA) b2 = division(summation(substract(close_arr_gpu, MA), scale(MSD, 2.0)), MSD_4) out = collections.namedtuple('Bollinger', 'b1 b2') return out(b1=cudf.Series(b1), b2=cudf.Series(b2))
def rate_of_change(close_arr, n): """ Calculate the rate of return :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: rate of change in cu.Series """ M = diff(close_arr, n - 1) N = shift(close_arr, n - 1) return cudf.Series(division(M, N))
def port_kst_oscillator(asset_indicator, close_arr, r1, r2, r3, r4, n1, n2, n3, n4): """Calculate port KST Oscillator for given data. :param asset_indicator: the indicator of beginning of the stock :param close_arr: close price of the bar, expect series from cudf :param r1: r1 time steps :param r2: r2 time steps :param r3: r3 time steps :param r4: r4 time steps :param n1: n1 time steps :param n2: n2 time steps :param n3: n3 time steps :param n4: n4 time steps :return: KST Oscillator in cudf.Series """ M1 = diff(close_arr, r1 - 1) N1 = shift(close_arr, r1 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), M1, 0, r1 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), N1, 0, r1 - 1) M2 = diff(close_arr, r2 - 1) N2 = shift(close_arr, r2 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), M2, 0, r2 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), N2, 0, r2 - 1) M3 = diff(close_arr, r3 - 1) N3 = shift(close_arr, r3 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), M3, 0, r3 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), N3, 0, r3 - 1) M4 = diff(close_arr, r4 - 1) N4 = shift(close_arr, r4 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), M4, 0, r4 - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), N4, 0, r4 - 1) term1 = Rolling(n1, division(M1, N1)).sum() port_mask_nan(asset_indicator.data.to_gpu_array(), term1, 0, n1 - 1) term2 = scale(Rolling(n2, division(M2, N2)).sum(), 2.0) port_mask_nan(asset_indicator.data.to_gpu_array(), term2, 0, n2 - 1) term3 = scale(Rolling(n3, division(M3, N3)).sum(), 3.0) port_mask_nan(asset_indicator.data.to_gpu_array(), term3, 0, n3 - 1) term4 = scale(Rolling(n4, division(M4, N4)).sum(), 4.0) port_mask_nan(asset_indicator.data.to_gpu_array(), term4, 0, n4 - 1) KST = summation(summation(summation(term1, term2), term3), term4) return cudf.Series(KST)
def port_coppock_curve(asset_indicator, close_arr, n): """Calculate port Coppock Curve for given data. :param asset_indicator: the indicator of beginning of the stock :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: Coppock Curve in cudf.Series """ M = diff(close_arr, int(n * 11 / 10) - 1) N = shift(close_arr, int(n * 11 / 10) - 1) port_mask_nan(asset_indicator.to_gpu_array(), M, 0, int(n * 11 / 10) - 1) port_mask_nan(asset_indicator.to_gpu_array(), N, 0, int(n * 11 / 10) - 1) ROC1 = division(M, N) M = diff(close_arr, int(n * 14 / 10) - 1) N = shift(close_arr, int(n * 14 / 10) - 1) port_mask_nan(asset_indicator.to_gpu_array(), M, 0, int(n * 14 / 10) - 1) port_mask_nan(asset_indicator.to_gpu_array(), N, 0, int(n * 14 / 10) - 1) ROC2 = division(M, N) Copp = PEwm(n, summation(ROC1, ROC2), asset_indicator).mean() return cudf.Series(Copp, nan_as_null=False)
def average_directional_movement_index(high_arr, low_arr, close_arr, n, n_ADX): """Calculate the Average Directional Movement Index for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param n: time steps to do EWM average :param n_ADX: time steps to do EWM average of ADX :return: Average Directional Movement Index in cudf.Series """ UpI, DoI = upDownMove(high_arr.to_gpu_array(), low_arr.to_gpu_array()) last_ele = len(high_arr) - 1 tr = true_range(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) ATR = Ewm(n, tr).mean() PosDI = division(Ewm(n, UpI).mean(), ATR) NegDI = division(Ewm(n, DoI).mean(), ATR) NORM = division(abs_arr(substract(PosDI, NegDI)), summation(PosDI, NegDI)) NORM[last_ele] = math.nan ADX = cudf.Series(Ewm(n_ADX, NORM).mean(), nan_as_null=False) return ADX
def port_ultimate_oscillator(asset_indicator, high_arr, low_arr, close_arr): """Calculate port Ultimate Oscillator for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :return: Ultimate Oscillator in cudf.Series """ TR_l, BP_l = port_ultimate_osc(asset_indicator.data.to_gpu_array(), high_arr.data.to_gpu_array(), low_arr.data.to_gpu_array(), close_arr.data.to_gpu_array()) term1 = division(scale(Rolling(7, BP_l).sum(), 4.0), Rolling(7, TR_l).sum()) term2 = division(scale(Rolling(14, BP_l).sum(), 2.0), Rolling(14, TR_l).sum()) term3 = division(Rolling(28, BP_l).sum(), Rolling(28, TR_l).sum()) port_mask_nan(asset_indicator.data.to_gpu_array(), term1, 0, 6) port_mask_nan(asset_indicator.data.to_gpu_array(), term2, 0, 13) port_mask_nan(asset_indicator.data.to_gpu_array(), term3, 0, 27) UltO = summation(summation(term1, term2), term3) return cudf.Series(UltO)
def port_bollinger_bands(asset_indicator, close_arr, n): """Calculate the port Bollinger Bands. See https://www.investopedia.com/terms/b/bollingerbands.asp for details :param asset_indicator: the indicator of beginning of the stock :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: b1 b2 """ MA = Rolling(n, close_arr).mean() port_mask_nan(asset_indicator.to_gpu_array(), MA, 0, n - 1) MSD = Rolling(n, close_arr).std() port_mask_nan(asset_indicator.to_gpu_array(), MSD, 0, n - 1) close_arr_gpu = numba.cuda.device_array_like(close_arr.to_gpu_array()) close_arr_gpu[:] = close_arr.to_gpu_array()[:] close_arr_gpu[0:n - 1] = math.nan MSD_4 = scale(MSD, 4.0) b1 = division(MSD_4, MA) b2 = division(summation(substract(close_arr_gpu, MA), scale(MSD, 2.0)), MSD_4) out = collections.namedtuple('Bollinger', 'b1 b2') return out(b1=cudf.Series(b1, nan_as_null=False), b2=cudf.Series(b2, nan_as_null=False))
def mass_index(high_arr, low_arr, n1, n2): """Calculate the Mass Index for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param n1: n1 time steps :param n1: n2 time steps :return: Mass Index in cudf.Series """ Range = high_arr - low_arr EX1 = Ewm(n1, Range).mean() EX2 = Ewm(n1, EX1).mean() Mass = division(EX1, EX2) MassI = Rolling(n2, Mass).sum() return cudf.Series(MassI)
def commodity_channel_index(high_arr, low_arr, close_arr, n): """Calculate Commodity Channel Index for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: Commodity Channel Index in cudf.Series """ PP = average_price(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) M = Rolling(n, PP).mean() N = Rolling(n, PP).std() CCI = division(substract(PP, M), N) return cudf.Series(CCI, nan_as_null=False)
def accumulation_distribution(high_arr, low_arr, close_arr, vol_arr, n): """Calculate Accumulation/Distribution for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param vol_arr: volume of the bar, expect series from cudf :param n: time steps :return: Accumulation/Distribution in cudf.Series """ ad = (2.0 * close_arr - high_arr - low_arr) / (high_arr - low_arr) * vol_arr M = diff(ad, n - 1) N = shift(ad, n - 1) return cudf.Series(division(M, N))
def true_strength_index(close_arr, r, s): """Calculate True Strength Index (TSI) for given data. :param close_arr: close price of the bar, expect series from cudf :param r: r time steps :param s: s time steps :return: True Strength Index in cudf.Series """ M = diff(close_arr, 1) aM = abs_arr(M) EMA1 = Ewm(r, M).mean() aEMA1 = Ewm(r, aM).mean() EMA2 = Ewm(s, EMA1).mean() aEMA2 = Ewm(s, aEMA1).mean() TSI = division(EMA2, aEMA2) return cudf.Series(TSI)
def port_rate_of_change(asset_indicator, close_arr, n): """ Calculate the port rate of return :param asset_indicator: the indicator of beginning of the stock :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: rate of change in cu.Series """ M = diff(close_arr, n - 1) N = shift(close_arr, n - 1) out = division(M, N) if n - 1 >= 0: port_mask_nan(asset_indicator.data.to_gpu_array(), out, 0, n - 1) else: port_mask_nan(asset_indicator.data.to_gpu_array(), out, n - 1, 0) return cudf.Series(out)
def port_mass_index(asset_indicator, high_arr, low_arr, n1, n2): """Calculate the port Mass Index for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param n1: n1 time steps :param n1: n2 time steps :return: Mass Index in cudf.Series """ Range = high_arr - low_arr EX1 = PEwm(n1, Range, asset_indicator).mean() EX2 = PEwm(n1, EX1, asset_indicator).mean() Mass = division(EX1, EX2) MassI = Rolling(n2, Mass).sum() port_mask_nan(asset_indicator.data.to_gpu_array(), MassI, 0, n2 - 1) return cudf.Series(MassI)
def relative_strength_index(high_arr, low_arr, n): """Calculate Relative Strength Index(RSI) for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param n: time steps to do EWM average :return: Relative Strength Index in cudf.Series """ UpI, DoI = upDownMove(high_arr.to_gpu_array(), low_arr.to_gpu_array()) UpI_s = shift(UpI, 1) UpI_s[0] = 0 DoI_s = shift(DoI, 1) DoI_s[0] = 0 PosDI = Ewm(n, UpI_s).mean() NegDI = Ewm(n, DoI_s).mean() RSI = division(PosDI, summation(PosDI, NegDI)) return cudf.Series(RSI, nan_as_null=False)
def money_flow_index(high_arr, low_arr, close_arr, volume_arr, n): """Calculate Money Flow Index and Ratio for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param volume_arr: volume the bar, expect series from cudf :param n: time steps :return: Money Flow Index in cudf.Series """ PP = average_price(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) PosMF = money_flow(PP, volume_arr.to_gpu_array()) MFR = division(PosMF, (multiply(PP, volume_arr.to_gpu_array()))) # TotMF MFI = Rolling(n, MFR).mean() return cudf.Series(MFI, nan_as_null=False)
def port_true_strength_index(asset_indicator, close_arr, r, s): """Calculate port True Strength Index (TSI) for given data. :param asset_indicator: the indicator of beginning of the stock :param close_arr: close price of the bar, expect series from cudf :param r: r time steps :param s: s time steps :return: True Strength Index in cudf.Series """ M = diff(close_arr, 1) port_mask_nan(asset_indicator.data.to_gpu_array(), M, 0, 1) aM = abs_arr(M) EMA1 = PEwm(r, M, asset_indicator).mean() aEMA1 = PEwm(r, aM, asset_indicator).mean() EMA2 = PEwm(s, EMA1, asset_indicator).mean() aEMA2 = PEwm(s, aEMA1, asset_indicator).mean() TSI = division(EMA2, aEMA2) return cudf.Series(TSI)
def ease_of_movement(high_arr, low_arr, volume_arr, n): """Calculate Ease of Movement for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param volume_arr: volume the bar, expect series from cudf :param n: time steps :return: Ease of Movement in cudf.Series """ high_arr_gpu = high_arr.data.to_gpu_array() low_arr_gpu = low_arr.data.to_gpu_array() EoM = division( multiply(summation(diff(high_arr_gpu, 1), diff(low_arr_gpu, 1)), substract(high_arr_gpu, low_arr_gpu)), scale(volume_arr.data.to_gpu_array(), 2.0)) Eom_ma = Rolling(n, EoM).mean() return cudf.Series(Eom_ma)
def vortex_indicator(high_arr, low_arr, close_arr, n): """Calculate the Vortex Indicator for given data. Vortex Indicator described here: http://www.vortexindicator.com/VFX_VORTEX.PDF :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param n: time steps to do EWM average :return: Vortex Indicator in cudf.Series """ TR = true_range(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) VM = lowhigh_diff(high_arr.to_gpu_array(), low_arr.to_gpu_array()) VI = division(Rolling(n, VM).sum(), Rolling(n, TR).sum()) return cudf.Series(VI, nan_as_null=False)
def port_accumulation_distribution(asset_indicator, high_arr, low_arr, close_arr, vol_arr, n): """Calculate port Accumulation/Distribution for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param vol_arr: volume of the bar, expect series from cudf :param n: time steps :return: Accumulation/Distribution in cudf.Series """ ad = (2.0 * close_arr - high_arr - low_arr) / (high_arr - low_arr) * vol_arr M = diff(ad, n - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), M, 0, n - 1) N = shift(ad, n - 1) port_mask_nan(asset_indicator.data.to_gpu_array(), N, 0, n - 1) return cudf.Series(division(M, N))
def port_commodity_channel_index(asset_indicator, high_arr, low_arr, close_arr, n): """Calculate port Commodity Channel Index for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param n: time steps :return: Commodity Channel Index in cudf.Series """ PP = average_price(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) M = Rolling(n, PP).mean() port_mask_nan(asset_indicator.to_gpu_array(), M, 0, n - 1) N = Rolling(n, PP).std() port_mask_nan(asset_indicator.to_gpu_array(), N, 0, n - 1) CCI = division(substract(PP, M), N) return cudf.Series(CCI, nan_as_null=False)
def port_relative_strength_index(asset_indicator, high_arr, low_arr, n): """Calculate Relative Strength Index(RSI) for given data. :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param n: time steps to do EWM average :return: Relative Strength Index in cudf.Series """ UpI, DoI = upDownMove(high_arr.data.to_gpu_array(), low_arr.data.to_gpu_array()) UpI_s = shift(UpI, 1) UpI_s[0] = 0 UpI_s = cudf.Series(UpI_s) * (1.0 - asset_indicator) DoI_s = shift(DoI, 1) DoI_s[0] = 0 DoI_s = cudf.Series(DoI_s) * (1.0 - asset_indicator) PosDI = PEwm(n, UpI_s, asset_indicator).mean() NegDI = PEwm(n, DoI_s, asset_indicator).mean() RSI = division(PosDI, summation(PosDI, NegDI)) return cudf.Series(RSI)
def port_money_flow_index(asset_indicator, high_arr, low_arr, close_arr, volume_arr, n): """Calculate port Money Flow Index and Ratio for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param close_arr: close price of the bar, expect series from cudf :param volume_arr: volume the bar, expect series from cudf :param n: time steps :return: Money Flow Index in cudf.Series """ PP = average_price(high_arr.to_gpu_array(), low_arr.to_gpu_array(), close_arr.to_gpu_array()) PosMF = port_money_flow(asset_indicator.to_gpu_array(), PP, volume_arr.to_gpu_array()) MFR = division(PosMF, (multiply(PP, volume_arr.to_gpu_array()))) # TotMF MFI = Rolling(n, MFR).mean() port_mask_nan(asset_indicator.to_gpu_array(), MFI, 0, n - 1) return cudf.Series(MFI, nan_as_null=False)
def port_ease_of_movement(asset_indicator, high_arr, low_arr, volume_arr, n): """Calculate port Ease of Movement for given data. :param asset_indicator: the indicator of beginning of the stock :param high_arr: high price of the bar, expect series from cudf :param low_arr: low price of the bar, expect series from cudf :param volume_arr: volume the bar, expect series from cudf :param n: time steps :return: Ease of Movement in cudf.Series """ high_arr_gpu = high_arr.data.to_gpu_array() low_arr_gpu = low_arr.data.to_gpu_array() EoM = division( multiply(summation(diff(high_arr_gpu, 1), diff(low_arr_gpu, 1)), substract(high_arr_gpu, low_arr_gpu)), scale(volume_arr.data.to_gpu_array(), 2.0)) port_mask_nan(asset_indicator.data.to_gpu_array(), EoM, 0, 1) Eom_ma = Rolling(n, EoM).mean() port_mask_nan(asset_indicator.data.to_gpu_array(), Eom_ma, 0, n - 1) return cudf.Series(Eom_ma)