Skip to content

Commit

Permalink
stoch + stochRSI
Browse files Browse the repository at this point in the history
  • Loading branch information
Bablofil committed May 18, 2019
1 parent dbcb714 commit 44603cc
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 104 deletions.
38 changes: 26 additions & 12 deletions ma.go
Expand Up @@ -8,22 +8,29 @@ import (
// Data expected to be older->newer, fair for result as well
func SMA(data []float64, period int) (result []float64, err error) {
if len(data) == 0 {
return result, errors.New("input parameter 'data' is empty")
return result, errors.New("SMA: input parameter 'data' is empty")
}

if period <= 0 {
return result, errors.New("Invalid period")
return result, errors.New("SMA: Invalid period")
}

var interm float64

for i := 0; i < len(data); i++ {
interm += data[i]
if (i + 1) < period {
if math.IsNaN(data[i]) {
result = append(result, math.NaN())
interm = 0
} else {
result = append(result, interm/float64(period))
interm -= data[i+1-period]
interm += data[i]
if (i + 1) < period {
result = append(result, math.NaN())
} else {
result = append(result, interm/float64(period))
if !math.IsNaN(data[i+1-period]) {
interm -= data[i+1-period]
}
}
}
}
return result, nil
Expand Down Expand Up @@ -82,26 +89,33 @@ func MACD(data []float64, fastperiod, slowperiod, signalperiod int) (macd, macds
}

macd = make([]float64, len(fast_ema))
macdsignal = make([]float64, 0)
diff := make([]float64, 0)
//macdsignal = make([]float64, 0)
macdsignal = make([]float64, len(fast_ema))
//diff := make([]float64, 0)

for k, fast := range fast_ema {
if math.IsNaN(fast) || math.IsNaN(slow_ema[k]) {
macd[k] = math.NaN()
macdsignal = append(macdsignal, math.NaN())
//macdsignal = append(macdsignal, math.NaN())
macdsignal[k] = math.NaN()
} else {
macd[k] = fast - slow_ema[k]
diff = append(diff, macd[k])
//diff = append(diff, macd[k])
macdsignal[k] = macd[k]
}
}

diff_ema, err := EMA(diff, signalperiod)
/*diff_ema, err := EMA(diff, signalperiod)
if err != nil {
return
}
macdsignal = append(macdsignal, diff_ema...)

*/
macdsignal, err = EMA(macdsignal, signalperiod)
if err != nil {
return
}
macdhist = make([]float64, len(macd))

for k, ms := range macdsignal {
Expand Down
2 changes: 0 additions & 2 deletions rsi.go
Expand Up @@ -38,5 +38,3 @@ func RSI(data []float64, period int) (result []float64, err error) {
}
return
}


37 changes: 15 additions & 22 deletions stoch.go
@@ -1,51 +1,44 @@
package ta

import (
"fmt"
"math"
)

func STOCH(high, low, closes []float64, fastk_period, slowk_period, slowd_period int) (fastk, slowd []float64, err error) {

fastk_dummy := make([]float64, fastk_period-1)
fastk_vals := make([]float64, len(closes)-fastk_period+1)

fastk = make([]float64, len(closes))
for i := 0; i < len(closes); i++ {

if (i + 1) < fastk_period {
fastk_dummy[i] = math.NaN()
fastk[i] = math.NaN()
} else {
lower_bound := i + 1 - fastk_period
upper_bound := i + 1
curr_low := SliceMin(low[lower_bound:upper_bound])
curr_high := SliceMax(high[lower_bound:upper_bound])

fastk_vals[i+1-fastk_period] = ((closes[i] - curr_low) / (curr_high - curr_low)) * 100
fastk[i] = ((closes[i] - curr_low) / (curr_high - curr_low)) * 100
}
}

fastk_ema, err := EMA(fastk_vals, slowk_period)

fastk, err = EMA(fastk, slowk_period)
if err != nil {
return
}

fastk = append(fastk_dummy, fastk_ema...)
slowd_dummy := make([]float64, 0)
var offset int
for _, v := range fastk {
if math.IsNaN(v) {
slowd_dummy = append(slowd_dummy, math.NaN())
offset++
} else {
break
}
slowd, err = EMA(fastk, slowd_period)
if err != nil {
return
}

slowd_ema, err := EMA(fastk[offset:], slowd_period)
return
}

func STOCHRSI(data []float64, period, fastk_period, fastd_period int) (fastk, slowd []float64, err error) {
rsi, err := RSI(data, period)
if err != nil {
return
}
slowd = append(slowd_dummy, slowd_ema...)
fmt.Println(rsi)

return
return STOCH(rsi, rsi, rsi, period, fastk_period, fastd_period)
}
77 changes: 29 additions & 48 deletions tests/ma_test.go
Expand Up @@ -2,6 +2,7 @@ package tests

import (
"math"
"strings"
"testing"

"../../ta"
Expand All @@ -13,7 +14,7 @@ func TestEmptyData(t *testing.T) {

res, err := ta.SMA(data, period)
if err != nil {
if err.Error() != "input parameter 'data' is empty" {
if !strings.Contains(err.Error(), "'data' is empty") {
t.Errorf("Unexpected error %s", err.Error())
}
} else {
Expand All @@ -30,7 +31,7 @@ func TestZeroPeriod(t *testing.T) {

res, err := ta.SMA(data, period)
if err != nil {
if err.Error() != "Invalid period" {
if !strings.Contains(err.Error(), "Invalid period") {
t.Errorf("Unexpected error %s", err.Error())
}
} else {
Expand All @@ -46,7 +47,7 @@ func TestNegativePeriod(t *testing.T) {

res, err := ta.SMA(data, period)
if err != nil {
if err.Error() != "Invalid period" {
if !strings.Contains(err.Error(), "Invalid period") {
t.Errorf("Unexpected error %s", err.Error())
}
} else {
Expand All @@ -62,7 +63,7 @@ func TestEmaPeriod(t *testing.T) {

res, err := ta.EMA(data, period)
if err != nil {
if err.Error() != "Invalid period" {
if !strings.Contains(err.Error(), "Invalid period") {
t.Errorf("Unexpected error %s", err.Error())
}
} else {
Expand Down Expand Up @@ -173,7 +174,7 @@ func TestEMACalculation(t *testing.T) {
test_worker(t, tests, ta.EMA, 2)
}

func test_workerCD(t *testing.T) {
func TestMACD(t *testing.T) {

type MACDTestItem struct {
Input []float64
Expand Down Expand Up @@ -228,48 +229,28 @@ func test_workerCD(t *testing.T) {
-0.21748933, -0.04349606, 0.17309122, 0.42058164, 0.68946351,
},
ExpectedMACDSignal: []float64{
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), 0.16148066, 0.08007288,
0.03721329, 0.03663134, 0.07844962, 0.16042697, 0.27886664,
0.26972604, 0.19643942, 0.10229581, 0.01573588, -0.0456146,
-0.07188979, -0.05868482, -0.00533851, 0.0863377, 0.21299016,
0.21085054, 0.14357255, 0.05462109, -0.02742197, -0.08481723,
-0.10760724, -0.09131299, -0.03521311, 0.05892999, 0.18780281,
0.18767003, 0.12221268, 0.03491841, -0.04561188, -0.10162274,
-0.12314307, -0.10568219, -0.04850869, 0.04662376, 0.1764093,
0.17711933, 0.11244085, 0.02586679, -0.05399716, -0.10939127,
-0.13034056, -0.11235082, -0.05468742, 0.04089892, 0.17110502,
0.17220477, 0.10788744, 0.02164809, -0.05790567, -0.11301231,
-0.13369517, -0.11545853, -0.05756632, 0.03823205, 0.16863464,
0.16991646, 0.10576784, 0.01968481, -0.05972412, -0.11469657,
-0.13525512, -0.11690331, -0.0589044, 0.0369928, 0.16748694,
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), -0.00716444, 0.01465165, 0.07390009, 0.16929050, 0.29790203,
0.29632517, 0.22851044, 0.13816764, 0.05408012, -0.00584755, -0.03152305, -0.01835773, 0.03445836, 0.12523397, 0.25071224,
0.24720252, 0.17842060, 0.08788076, 0.00420383, -0.05484023, -0.07927030, -0.06458923, -0.01006204, 0.08255888, 0.20996711,
0.20843210, 0.14163779, 0.05307328, -0.02866021, -0.08580783, -0.10839972, -0.09194697, -0.03572029, 0.05852424, 0.18747821,
0.18741035, 0.12200494, 0.03475222, -0.04574484, -0.10172910, -0.12322816, -0.10575027, -0.04856315, 0.04658020, 0.17637445,
0.17709145, 0.11241854, 0.02584895, -0.05401144, -0.10940269, -0.13034970, -0.11235813, -0.05469327, 0.04089424, 0.17110127,
0.17220177, 0.10788504, 0.02164617, -0.05790721, -0.11301353, -0.13369616, -0.11545932, -0.05756695, 0.03823155, 0.16863424,
0.16991614, 0.10576758, 0.01968460, -0.05972429, -0.11469670, -0.13525523, -0.11690339, -0.05890447, 0.03699275, 0.16748690,
},
ExpectedHist: []float64{
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), -0.44375062, -0.32563113,
-0.17143834, -0.00232781, 0.16727312, 0.32790942, 0.47375867,
-0.03656241, -0.29314649, -0.37657443, -0.34623974, -0.24540189,
-0.10510078, 0.05281987, 0.21338525, 0.36670484, 0.50660986,
-0.00855848, -0.26911198, -0.35580584, -0.32817224, -0.22958104,
-0.09116004, 0.06517701, 0.22439951, 0.37657239, 0.51549127,
-0.00053111, -0.26182939, -0.34917708, -0.32212117, -0.22404342,
-0.08608132, 0.06984351, 0.22869401, 0.38052981, 0.51914216,
0.00284013, -0.25871396, -0.34629622, -0.31945582, -0.22157643,
-0.08379716, 0.07195896, 0.23065361, 0.38234534, 0.5208244,
0.00439901, -0.25726932, -0.3449574, -0.31821505, -0.22042653,
-0.08273148, 0.07294657, 0.23156885, 0.38319349, 0.52161035,
0.00512729, -0.25659449, -0.34433213, -0.31763573, -0.21988979,
-0.08223421, 0.07340725, 0.23199562, 0.38358883, 0.52197657,
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(),
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), -0.05731555, 0.08726436, 0.23699379, 0.38156163, 0.51444613,
-0.00630745, -0.27125893, -0.36137117, -0.33635008, -0.23971070, -0.10270200, 0.05266126, 0.21126438, 0.36310243, 0.50191308,
-0.01403888, -0.27512767, -0.36215937, -0.33470770, -0.23617625, -0.09772027, 0.05872427, 0.21810877, 0.37048366, 0.50963291,
-0.00614003, -0.26717723, -0.35425803, -0.32693400, -0.22859045, -0.09036757, 0.06581099, 0.22490670, 0.37697814, 0.51581587,
-0.00027143, -0.26162165, -0.34901089, -0.32198821, -0.22393706, -0.08599623, 0.06991158, 0.22874846, 0.38057338, 0.51917701,
0.00286802, -0.25869165, -0.34627837, -0.31944154, -0.22156501, -0.08378802, 0.07196627, 0.23065946, 0.38235002, 0.52082814,
0.00440200, -0.25726692, -0.34495548, -0.31821352, -0.22042530, -0.08273049, 0.07294736, 0.23156948, 0.38319399, 0.52161075,
0.00512761, -0.25659424, -0.34433193, -0.31763556, -0.21988966, -0.08223411, 0.07340733, 0.23199569, 0.38358889, 0.52197661,
},
},
}
Expand All @@ -281,8 +262,8 @@ func test_workerCD(t *testing.T) {
if err != nil {
t.Errorf(err.Error())
}
compare_inp_exp(t, macd, test.ExpectedMACD, 8)
compare_inp_exp(t, macdsignal, test.ExpectedMACDSignal, 8)
compare_inp_exp(t, macdhist, test.ExpectedHist, 8)
compare_inp_exp(t, macd, test.ExpectedMACD, 8, "MACD")
compare_inp_exp(t, macdsignal, test.ExpectedMACDSignal, 8, "MACDSignal")
compare_inp_exp(t, macdhist, test.ExpectedHist, 8, "MACDHIST")
}
}
16 changes: 9 additions & 7 deletions tests/misc.go
Expand Up @@ -14,25 +14,26 @@ type testItem struct {
type test_func func([]float64, int) ([]float64, error)

func test_worker(t *testing.T, tests []*testItem, f test_func, round_floats float64) {
for _, test := range tests {

for test_num, test := range tests {
comment := "TEST_" + string(test_num)
res, err := f(test.Input, test.Period)

if err != nil {
t.Errorf("Unexpected error %s", err.Error())
t.Errorf("%s: Unexpected error %s", comment, err.Error())
} else {
compare_inp_exp(t, res, test.Expected, round_floats)
compare_inp_exp(t, res, test.Expected, round_floats, comment)
}
}
}

func compare_inp_exp(t *testing.T, res, expected []float64, round_floats float64) {
func compare_inp_exp(t *testing.T, res, expected []float64, round_floats float64, comment string) {
if len(res) != len(expected) {
t.Errorf(`
TEST COMMENT %s:
Different sizes: result %d, expected %d
res: %v,
expected: %v
`, len(res), len(expected), res, expected,
`, comment, len(res), len(expected), res, expected,
)
}

Expand All @@ -44,11 +45,12 @@ func compare_inp_exp(t *testing.T, res, expected []float64, round_floats float64
(math.IsNaN(rounded_e) && !math.IsNaN(rounded_v)) ||
(math.IsNaN(rounded_v) && !math.IsNaN(rounded_e)) {
t.Errorf(`
TEST COMMENT %s
Expected result %#v
Got result %#v
%0.8f instead of %0.8f
(%0.8f instead of %0.8f)
`, expected, res, rounded_v, rounded_e, v, expected[k])
`, comment, expected, res, rounded_v, rounded_e, v, expected[k])
break
}
}
Expand Down
26 changes: 13 additions & 13 deletions tests/stoch_test.go
Expand Up @@ -8,7 +8,7 @@ import (
)

func TestSTOCHCalculation(t *testing.T) {
var close []float64 = []float64{
var closes []float64 = []float64{
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
Expand Down Expand Up @@ -48,10 +48,10 @@ func TestSTOCHCalculation(t *testing.T) {
}

var expected_slowk []float64 = []float64{
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 72.80551296, 68.93194648, 64.09801434, 67.01261748,
33.87313046, 21.50238050, 19.51599905, 22.74694285, 43.61632131, 54.89057317, 60.33474072, 59.71617774, 64.11716958, 72.58908543,
37.99000927, 25.28654979, 24.62579350, 29.35369057, 63.11142986, 63.87264353, 69.30238698, 65.84761110, 70.49064827, 68.92086282,
34.87326225, 21.86676276, 19.38081379, 22.15514010, 46.33345430, 66.57208246, 63.34893407, 68.54159402, 61.79572053, 62.86587247,
math.NaN(), math.NaN(), math.NaN(), math.NaN(), 27.87890027, 50.85070959, 55.90401438, 60.48119718, 59.87263969, 64.89993016,
32.81678680, 20.97420866, 19.25191313, 22.61489989, 43.55029983, 54.85756243, 60.31823535, 59.70792505, 64.11304324, 72.58702226,
37.98897768, 25.28603400, 24.62553560, 29.35356162, 63.11136538, 63.87261130, 69.30237086, 65.84760304, 70.49064424, 68.92086080,
34.87326125, 21.86676225, 19.38081354, 22.15513997, 46.33345424, 66.57208242, 63.34893405, 68.54159402, 61.79572053, 62.86587247,
31.49596171, 19.89307521, 18.17370084, 21.39608255, 51.51021174, 74.10528969, 72.14488542, 75.60062262, 73.75777263, 62.58372971,
32.65246736, 21.17584260, 18.92653665, 21.29089011, 49.79981076, 68.46652608, 69.25782069, 62.59550901, 65.61605476, 61.53837599,
31.35469526, 19.87697835, 17.75224334, 20.30399929, 43.69896224, 56.11384973, 67.48331110, 81.28271989, 72.41915990, 70.25530869,
Expand All @@ -61,22 +61,22 @@ func TestSTOCHCalculation(t *testing.T) {
}

var expected_slowd []float64 = []float64{
math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 68.61182459, 67.81222104,
50.84267575, 36.17252812, 27.84426359, 25.29560322, 34.45596226, 44.67326771, 52.50400422, 56.11009098, 60.11363028, 66.35135785,
52.17068356, 38.72861668, 31.67720509, 30.51544783, 46.81343884, 55.34304119, 62.32271408, 64.08516259, 67.28790543, 68.10438412,
51.48882319, 36.67779297, 28.02930338, 25.09222174, 35.71283802, 51.14246024, 57.24569715, 62.89364559, 62.34468306, 62.60527777,
47.05061974, 33.47184747, 25.82277416, 23.60942835, 37.55982005, 55.83255487, 63.98872014, 69.79467138, 71.77622201, 67.17997586,
math.NaN(), math.NaN(), math.NaN(), math.NaN(), 9.29296676, 30.07183817, 42.98792627, 51.73456173, 55.80360071, 60.35176543,
46.58427612, 33.77924239, 26.51557776, 24.56523883, 34.05776933, 44.45766588, 52.38795061, 56.04793783, 60.08049053, 66.33375640,
52.16136704, 38.72370052, 31.67461806, 30.51408984, 46.81272761, 55.34266945, 62.32252016, 64.08506160, 67.28785292, 68.10435686,
51.48880905, 36.67778565, 28.02929960, 25.09221978, 35.71283701, 51.14245972, 57.24569689, 62.89364545, 62.34468299, 62.60527773,
47.05061972, 33.47184746, 25.82277415, 23.60942835, 37.55982004, 55.83255487, 63.98872014, 69.79467138, 71.77622201, 67.17997586,
49.91622161, 35.54603211, 27.23628438, 24.26358724, 37.03169900, 52.74911254, 61.00346662, 61.79948782, 63.70777129, 62.62307364,
46.98888445, 33.43293140, 25.59258737, 22.94829333, 33.32362779, 44.71873876, 56.10102493, 68.69187241, 70.55551616, 70.40541242,
53.50126411, 38.72966911, 30.27913856, 29.22228955, 40.71899777, 54.97240137, 66.19989971, 71.78736728, 71.18366337, 71.45039074,
53.90495118, 38.42925613, 29.47634730, 26.59215799, 37.69491080, 48.99952773, 57.42891030, 63.68424346, 70.95309322, 79.24654394,
61.89501833, 45.14304756, 35.40187571, 32.52161407, 45.83112306, 61.43166889, 71.11482286, 75.29755176, 74.06191255, 74.38415717,
}

slowk, slowd, err := ta.STOCH(high, low, close, 5, 3, 3)
slowk, slowd, err := ta.STOCH(high, low, closes, 5, 3, 3)
if err != nil {
t.Errorf(err.Error())
}
compare_inp_exp(t, slowk, expected_slowk, 8)
compare_inp_exp(t, slowd, expected_slowd, 8)
compare_inp_exp(t, slowk, expected_slowk, 8, "SLOWK")
compare_inp_exp(t, slowd, expected_slowd, 8, "SLOWD")
}

0 comments on commit 44603cc

Please sign in to comment.