joshuaulrich / TTR

Technical analysis and other functions to construct technical trading rules with R
GNU General Public License v2.0
326 stars 102 forks source link

MFI special cases (strong up-trend and volume contains zeros) #81

Closed jgehw closed 3 years ago

jgehw commented 5 years ago

Description

If there is no money flow for 'n' consecutive time frames (this is sometimes the case for less popular securities towards end of the day), or if there is no negative money flow for 'n' consecutive time frames (e.g. during a strong up-trend), the denominator in

mr <- runSum( pmf, n ) / runSum( nmf, n )

becomes zero, resulting in NA.

Expected behavior

No NAs in these cases.

Suggest to fix by setting 'mfi' to 100 if denominator of 'mr' is 0 because for limit denominator -> 0: 'mr' -> infinity and limit 'mr' -> infinity: 'mfi' -> 100.

Special case: both numerator and denominator are 0. Suggest to fix by setting 'mfi' to 50 in this case because for limit numerator and denominator -> 0: 'mr' -> 1 and thus 'mfi' = 50.

mfi[is.infinite(mr)] <- 100
mfi[is.nan(mr)] <- 50
joshuaulrich commented 5 years ago

Thanks for the report and suggestion! Can you provide an example (of an actual instrument, preferably) that demonstrates this behavior? It will help me understand your suggested change, and serve as a template for a unit test.

jgehw commented 5 years ago

Here is an example:

# OHLCV data
x <- rbind(cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,9171293400.000000),
cbind(6284.190000,6284.190000,6284.190000,6284.190000,152854890.000000),
cbind(6288.560000,6290.550000,6287.300000,6287.300000,0.000000),
cbind(6288.230000,6290.880000,6287.440000,6290.280000,0.000000),
cbind(6290.450000,6292.880000,6288.890000,6292.600000,0.000000),
cbind(6292.380000,6299.360000,6291.300000,6299.360000,0.000000),
cbind(6298.600000,6298.600000,6294.730000,6294.730000,0.000000),
cbind(6294.470000,6294.510000,6292.490000,6293.610000,0.000000),
cbind(6293.680000,6294.970000,6293.360000,6293.920000,0.000000),
cbind(6293.710000,6295.030000,6293.710000,6294.110000,0.000000),
cbind(6294.070000,6295.710000,6294.070000,6294.960000,0.000000),
cbind(6294.890000,6300.370000,6294.850000,6299.450000,0.000000),
cbind(6299.290000,6299.290000,6297.290000,6297.530000,0.000000),
cbind(6297.530000,6297.980000,6295.770000,6296.090000,0.000000),
cbind(6296.090000,6298.360000,6296.070000,6297.330000,0.000000),
cbind(6297.330000,6298.440000,6296.670000,6298.440000,0.000000),
cbind(6298.390000,6299.070000,6298.360000,6298.550000,0.000000),
cbind(6298.120000,6298.740000,6297.010000,6297.280000,0.000000),
cbind(6297.440000,6299.040000,6297.280000,6297.830000,0.000000),
cbind(6297.790000,6299.540000,6297.770000,6298.210000,0.000000),
cbind(6297.880000,6298.610000,6297.280000,6297.870000,0.000000),
cbind(6298.050000,6298.520000,6296.590000,6297.040000,0.000000),
cbind(6297.040000,6297.670000,6295.820000,6296.530000,0.000000),
cbind(6296.530000,6297.050000,6296.270000,6297.030000,0.000000),
cbind(6297.180000,6298.540000,6296.640000,6296.640000,0.000000),
cbind(6296.640000,6298.710000,6296.490000,6297.200000,0.000000),
cbind(6297.200000,6297.580000,6296.010000,6296.880000,0.000000),
cbind(6296.880000,6297.380000,6296.230000,6296.650000,0.000000),
cbind(6296.430000,6297.080000,6295.490000,6295.570000,0.000000),
cbind(6295.550000,6296.080000,6294.360000,6294.380000,0.000000),
cbind(6294.380000,6294.740000,6293.600000,6294.680000,0.000000),
cbind(6294.600000,6296.170000,6294.600000,6295.930000,0.000000),
cbind(6295.930000,6297.120000,6295.340000,6297.100000,0.000000),
cbind(6297.000000,6298.580000,6297.000000,6298.360000,0.000000),
cbind(6298.360000,6298.450000,6295.880000,6296.190000,0.000000),
cbind(6296.120000,6296.890000,6296.040000,6296.540000,0.000000),
cbind(6296.490000,6296.530000,6294.810000,6294.850000,0.000000),
cbind(6294.850000,6294.930000,6290.350000,6291.390000,0.000000),
cbind(6291.450000,6291.730000,6290.460000,6291.260000,0.000000),
cbind(6291.300000,6291.810000,6289.240000,6289.240000,0.000000),
cbind(6289.230000,6289.970000,6286.870000,6286.870000,0.000000),
cbind(6286.840000,6286.840000,6285.520000,6285.920000,0.000000),
cbind(6286.010000,6287.110000,6285.110000,6285.110000,0.000000),
cbind(6285.090000,6285.580000,6283.980000,6285.210000,0.000000),
cbind(6285.210000,6286.550000,6285.210000,6285.510000,0.000000),
cbind(6285.510000,6286.630000,6284.280000,6284.280000,0.000000),
cbind(6284.340000,6284.340000,6283.300000,6283.480000,0.000000),
cbind(6283.330000,6284.820000,6282.990000,6283.860000,0.000000),
cbind(6283.840000,6285.010000,6283.690000,6284.160000,0.000000),
cbind(6284.360000,6284.760000,6283.620000,6284.740000,0.000000),
cbind(6284.760000,6284.970000,6283.160000,6283.510000,0.000000),
cbind(6283.430000,6283.430000,6280.160000,6281.780000,0.000000),
cbind(6281.780000,6282.190000,6281.030000,6282.190000,0.000000),
cbind(6282.190000,6283.400000,6281.880000,6283.210000,0.000000),
cbind(6283.540000,6284.080000,6282.760000,6283.990000,0.000000),
cbind(6283.950000,6284.440000,6283.580000,6283.580000,0.000000),
cbind(6283.630000,6285.750000,6283.390000,6285.730000,0.000000),
cbind(6285.730000,6286.310000,6284.810000,6284.810000,0.000000),
cbind(6284.780000,6285.510000,6284.070000,6284.080000,0.000000),
cbind(6284.080000,6284.930000,6283.160000,6283.280000,0.000000),
cbind(6283.280000,6285.190000,6283.250000,6284.890000,0.000000),
cbind(6284.890000,6285.540000,6284.840000,6285.110000,0.000000),
cbind(6285.220000,6285.220000,6283.980000,6284.460000,1650189487.000000),
cbind(6284.460000,6285.960000,6284.200000,6285.540000,1796244384.000000),
cbind(6285.540000,6287.540000,6285.540000,6287.470000,1864666606.000000),
cbind(6287.480000,6287.840000,6286.710000,6286.920000,1845475611.000000),
cbind(6286.930000,6287.890000,6286.580000,6286.820000,1831082797.000000),
cbind(6286.820000,6288.950000,6286.750000,6288.950000,1918533018.000000))

MFI(x[,2:4], x[,5], n=3)

This results in:

 [1]        NA        NA        NA       NaN       NaN       NaN       NaN
 [8]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[15]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[22]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[29]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[36]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[43]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[50]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[57]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[64]       NaN       NaN       NaN       NaN       NaN       NaN       NaN
[71]   0.00000  52.12163  68.93455 100.00000  66.95494  67.27551

while I would expect:

 [1]        NA        NA        NA  50.00000  50.00000  50.00000  50.00000
 [8]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[15]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[22]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[29]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[36]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[43]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[50]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[57]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[64]  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000  50.00000
[71]   0.00000  52.12163  68.93455 100.00000  66.95494  67.27551

Note: While debugging examples, I found out that 100 - ( 100 / ( 1 + Inf ) ) evaluates to 100 (not NaN), so the first part of my suggestion

mfi[is.infinite(mr)] <- 100

is not required. Only the special case NaN resulting from 0 / 0 needs to be addressed, i.e.

mfi[is.nan(mr)] <- 50

is sufficient.