From 20833935cd3836cd1b33e6bd90a4a95882f391a4 Mon Sep 17 00:00:00 2001
From: Arthur Sudarikov <1@levitan.su>
Date: Mon, 23 Sep 2024 12:32:42 +0300
Subject: [PATCH] v1.3.2
---
README.md | 2 +-
tradingview.go | 2 +-
tradingview_test.go | 241 +++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 242 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 2569e2f..b715f65 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
An unofficial Go API simple wrapper to retrieve technical analysis from TradingView.
-
+
## Installation
diff --git a/tradingview.go b/tradingview.go
index e6f1768..15a8390 100644
--- a/tradingview.go
+++ b/tradingview.go
@@ -1,6 +1,6 @@
// Copyright 2022-2024. All rights reserved.
// https://github.com/artlevitan/go-tradingview-ta
-// v1.3.1
+// v1.3.2
package tradingview
diff --git a/tradingview_test.go b/tradingview_test.go
index f9fe412..c499bc9 100644
--- a/tradingview_test.go
+++ b/tradingview_test.go
@@ -1,6 +1,6 @@
// Copyright 2022-2024. All rights reserved.
// https://github.com/artlevitan/go-tradingview-ta
-// v1.3.1
+// v1.3.2
package tradingview
@@ -31,6 +31,7 @@ func TestTradingView_GetAllIntervals(t *testing.T) {
{"Interval1day", Interval1Day},
{"Interval1week", Interval1Week},
{"Interval1month", Interval1Month},
+ {"default", ""}, // default
}
// Run tests for each interval
@@ -43,3 +44,241 @@ func TestTradingView_GetAllIntervals(t *testing.T) {
})
}
}
+
+func Test_tvComputeRecommend(t *testing.T) {
+ type args struct {
+ v float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Strong Buy", args{0.6}, SignalStrongBuy}, // v between 0.5 and 1
+ {"Test Buy", args{0.3}, SignalBuy}, // v between 0.1 and 0.5
+ {"Test Neutral Positive", args{0.1}, SignalNeutral}, // v between -0.1 and 0.1
+ {"Test Neutral Negative", args{-0.1}, SignalNeutral}, // v between -0.1 and 0.1
+ {"Test Strong Sell", args{-0.6}, SignalStrongSell}, // v between -1 and -0.5
+ {"Test Sell", args{-0.3}, SignalSell}, // v between -0.5 and -0.1
+ {"Test Neutral Edge", args{2}, SignalNeutral}, // value outside of range
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvComputeRecommend(tt.args.v); got != tt.want {
+ t.Errorf("tvComputeRecommend() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvRsi(t *testing.T) {
+ type args struct {
+ rsi float64
+ rsi1 float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{29, 28}, SignalBuy}, // RSI < 30 and rsi1 < rsi
+ {"Test Sell", args{71, 72}, SignalSell}, // RSI > 70 and rsi1 > rsi
+ {"Test Neutral", args{50, 50}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvRsi(tt.args.rsi, tt.args.rsi1); got != tt.want {
+ t.Errorf("tvRsi() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvStoch(t *testing.T) {
+ type args struct {
+ k float64
+ d float64
+ k1 float64
+ d1 float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{19, 18, 17, 18}, SignalBuy}, // k, d < 20, k > d, k1 < d1
+ {"Test Sell", args{81, 82, 83, 82}, SignalSell}, // k, d > 80, k < d, k1 > d1
+ {"Test Neutral", args{50, 50, 50, 50}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvStoch(tt.args.k, tt.args.d, tt.args.k1, tt.args.d1); got != tt.want {
+ t.Errorf("tvStoch() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvCci20(t *testing.T) {
+ type args struct {
+ cci20 float64
+ cci201 float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{-101, -102}, SignalBuy}, // CCI20 < -100 and CCI20 > CCI201
+ {"Test Sell", args{101, 102}, SignalSell}, // CCI20 > 100 and CCI20 < CCI201
+ {"Test Neutral", args{0, 0}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvCci20(tt.args.cci20, tt.args.cci201); got != tt.want {
+ t.Errorf("tvCci20() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvAdx(t *testing.T) {
+ type args struct {
+ adx float64
+ adxpdi float64
+ adxndi float64
+ adxpdi1 float64
+ adxndi1 float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{21, 30, 20, 19, 21}, SignalBuy}, // ADX > 20, adxpdi1 < adxndi1, adxpdi > adxndi
+ {"Test Sell", args{21, 20, 30, 31, 29}, SignalSell}, // ADX > 20, adxpdi1 > adxndi1, adxpdi < adxndi
+ {"Test Neutral", args{19, 20, 20, 20, 20}, SignalNeutral}, // ADX <= 20
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvAdx(tt.args.adx, tt.args.adxpdi, tt.args.adxndi, tt.args.adxpdi1, tt.args.adxndi1); got != tt.want {
+ t.Errorf("tvAdx() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvAo(t *testing.T) {
+ type args struct {
+ ao float64
+ ao1 float64
+ ao2 float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{1, -1, 0}, SignalBuy}, // AO > 0, AO1 < 0
+ {"Test Sell", args{-1, 1, 0}, SignalSell}, // AO < 0, AO1 > 0
+ {"Test Neutral", args{0, 0, 0}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvAo(tt.args.ao, tt.args.ao1, tt.args.ao2); got != tt.want {
+ t.Errorf("tvAo() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvMom(t *testing.T) {
+ type args struct {
+ mom float64
+ mom1 float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{2, 1}, SignalBuy}, // mom > mom1
+ {"Test Sell", args{1, 2}, SignalSell}, // mom < mom1
+ {"Test Neutral", args{1, 1}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvMom(tt.args.mom, tt.args.mom1); got != tt.want {
+ t.Errorf("tvMom() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvMacd(t *testing.T) {
+ type args struct {
+ macd float64
+ s float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{1, 0}, SignalBuy}, // MACD > Signal
+ {"Test Sell", args{0, 1}, SignalSell}, // MACD < Signal
+ {"Test Neutral", args{1, 1}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvMacd(tt.args.macd, tt.args.s); got != tt.want {
+ t.Errorf("tvMacd() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvSimple(t *testing.T) {
+ type args struct {
+ v float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{1}, SignalBuy}, // v == 1
+ {"Test Sell", args{-1}, SignalSell}, // v == -1
+ {"Test Neutral", args{0}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvSimple(tt.args.v); got != tt.want {
+ t.Errorf("tvSimple() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_tvMa(t *testing.T) {
+ type args struct {
+ ma float64
+ close float64
+ }
+ tests := []struct {
+ name string
+ args args
+ want int
+ }{
+ {"Test Buy", args{100, 101}, SignalBuy}, // ma < close
+ {"Test Sell", args{101, 100}, SignalSell}, // ma > close
+ {"Test Neutral", args{100, 100}, SignalNeutral}, // Default case (neutral)
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := tvMa(tt.args.ma, tt.args.close); got != tt.want {
+ t.Errorf("tvMa() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}