Skip to content

Commit

Permalink
chore: optimized tests, added more readability to main.go, increased …
Browse files Browse the repository at this point in the history
…deviation for stable trend
  • Loading branch information
RamazanKara committed Jan 3, 2024
1 parent b9ffea3 commit 3fbbb18
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 38 deletions.
16 changes: 13 additions & 3 deletions cmd/main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,34 @@ import (
"log"

aggregator "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-aggregator"
preprocessing "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-preprocessing"
prognosis "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-prognosis"
)

func main() {
config := aggregator.ApiConfig()

// Fetch Bitcoin prices
prices, err := aggregator.FetchBitcoinPrices(config)
if err != nil {
log.Fatalf("Error fetching Bitcoin prices: %v", err)
}

// Display fetched prices
for _, price := range prices {
fmt.Printf("Date: %s, Price: %s %s\n", price.Date, price.Value, config.VsCurrency)
}

prognosis, trend, err := prognosis.PrognoseNextDayPrice(prices, config)
// Preprocess the prices
preprocessedPrices, err := preprocessing.PreprocessData(prices)
if err != nil {
log.Fatalf("Error calculating prognosis: %v", err)
log.Fatalf("Error in preprocessing data: %v", err)
}

fmt.Printf("Prognosis for the next day: %s (%s trend)\n", prognosis, trend)
// Calculate and display the prognosis
nextDayPricePrognosis, trend, err := prognosis.PrognoseNextDayPrice(preprocessedPrices, config)
if err != nil {
log.Fatalf("Error calculating prognosis: %v", err)
}
fmt.Printf("Prognosis for the next day: %s (%s trend)\n", nextDayPricePrognosis, trend)
}
19 changes: 6 additions & 13 deletions pkg/price-prognosis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,25 @@ import (
"math"

aggregator "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-aggregator"
preprocessing "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-preprocessing" // Import the preprocessing package
)

func PrognoseNextDayPrice(prices []aggregator.BitcoinPrice, config aggregator.Config) (string, string, error) {
// Preprocess the data
preprocessedPrices, err := preprocessing.PreprocessData(prices)
if err != nil {
return "", "", fmt.Errorf("error in data preprocessing: %v", err)
}

n := len(preprocessedPrices)
// Update the function signature to accept a slice of float64
func PrognoseNextDayPrice(prices []float64, config aggregator.Config) (string, string, error) {
n := len(prices)
if n < 30 { // Adjusted to check the length of preprocessed data
return "0.00", "", errors.New("insufficient data points for accurate prognosis")
}

var sumX, sumY, sumXY, sumXX float64
for i, value := range preprocessedPrices {
for i, value := range prices {
x := float64(i + 1)
sumX += x
sumY += value
sumXY += x * value
sumXX += x * x
}

// Linear regression calculations
//toDo: use ARIMA instead of linear regression
// Linear regression calculations
slope := (float64(n)*sumXY - sumX*sumY) / (float64(n)*sumXX - sumX*sumX)
intercept := (sumY - slope*sumX) / float64(n)

Expand All @@ -46,7 +39,7 @@ func PrognoseNextDayPrice(prices []aggregator.BitcoinPrice, config aggregator.Co
}

func determineTrend(slope float64) string {
if math.Abs(slope) > 0.01 { // Threshold for significant trend
if math.Abs(slope) > 0.1 { // Threshold for significant trend
if slope > 0 {
return "upwards"
} else {
Expand Down
56 changes: 34 additions & 22 deletions test/price-prognosis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,30 @@ package test

import (
"testing"
"fmt"

aggregator "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-aggregator"
preprocessing "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-preprocessing"
prognosis "github.com/RamazanKara/bitcoin-price-aggregator-go/pkg/price-prognosis"
)

func generateSequentialPrices(num int, start, increment float64) []aggregator.BitcoinPrice {
var prices []aggregator.BitcoinPrice
for i := 0; i < num; i++ {
price := start + float64(i)*increment
prices = append(prices, aggregator.BitcoinPrice{Value: fmt.Sprintf("%.2f", price)})
}
return prices
}

func generateStablePrices(num int, value float64) []aggregator.BitcoinPrice {
var prices []aggregator.BitcoinPrice
for i := 0; i < num; i++ {
prices = append(prices, aggregator.BitcoinPrice{Value: fmt.Sprintf("%.2f", value)})
}
return prices
}

func TestPrognoseNextDayPrice(t *testing.T) {
testConfig := aggregator.ApiConfig()
currencySuffix := " " + testConfig.VsCurrency
Expand All @@ -20,48 +39,41 @@ func TestPrognoseNextDayPrice(t *testing.T) {
{
name: "Empty Prices",
prices: []aggregator.BitcoinPrice{},
expected: "0.00" + currencySuffix,
expected: "0.00",
trend: "",
},
{
name: "Upward Trend",
prices: []aggregator.BitcoinPrice{
{Value: "100.00"},
{Value: "200.00"},
{Value: "300.00"},
},
prices: generateSequentialPrices(30, 100.00, 10.00),
expected: "400.00" + currencySuffix,
trend: "upwards",
},
{
name: "Downward Trend",
prices: []aggregator.BitcoinPrice{
{Value: "300.00"},
{Value: "200.00"},
{Value: "100.00"},
},
expected: "0.00" + currencySuffix,
prices: generateSequentialPrices(30, 400.00, -10.00),
expected: "100.00" + currencySuffix,
trend: "downwards",
},
{
name: "Stable Trend",
prices: []aggregator.BitcoinPrice{
{Value: "200.00"},
{Value: "200.00"},
{Value: "200.00"},
},
expected: "200.00" + currencySuffix,
prices: generateSequentialPrices(30, 200.00, 0.001),
expected: "200.03" + currencySuffix,
trend: "stable",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
prognosis, trend, err := prognosis.PrognoseNextDayPrice(tc.prices, testConfig)
if len(tc.prices) == 0 && err == nil {
t.Error("Expected an error for empty price data")
preprocessedPrices, err := preprocessing.PreprocessData(tc.prices)
if err != nil {
t.Fatalf("Preprocessing failed: %v", err)
}

prognosis, trend, err := prognosis.PrognoseNextDayPrice(preprocessedPrices, testConfig)
if len(preprocessedPrices) == 0 && err == nil {
t.Error("Expected an error for empty or invalid preprocessed data")
}
if len(tc.prices) > 0 && err != nil {
if len(preprocessedPrices) > 0 && err != nil {
t.Errorf("Did not expect an error: %v", err)
}
if prognosis != tc.expected {
Expand Down

0 comments on commit 3fbbb18

Please sign in to comment.