Skip to content

Commit

Permalink
Merge local development into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
aoterolorenzo committed Sep 21, 2022
1 parent 5b0f335 commit c6274c8
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 172 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect
github.com/gizak/termui/v3 v3.1.0
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
github.com/goml/gobrain v0.0.0-20201212123421-2e2d98ca8249
github.com/joho/godotenv v1.3.0
github.com/maruel/panicparse v1.6.1 // indirect
github.com/mattn/go-runewidth v0.0.10 // indirect
Expand All @@ -16,6 +17,7 @@ require (
github.com/sdcoffey/techan v0.12.0
github.com/sirupsen/logrus v1.7.0
github.com/stretchr/testify v1.5.1
github.com/surenderthakran/gomind v0.0.0-20180731125518-a31b8878d726 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
github.com/urfave/cli/v2 v2.3.0
github.com/xhit/go-str2duration/v2 v2.0.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-telegram-bot-api/telegram-bot-api v1.0.0 h1:HXVtsZ+yINQeyyhPFAUU4yKmeN+iFhJ87jXZOC016gs=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
github.com/goml/gobrain v0.0.0-20201212123421-2e2d98ca8249 h1:Xst86cFqcrNSUxId+2A/o3NZUwm7H+H6bUcehmD2t4o=
github.com/goml/gobrain v0.0.0-20201212123421-2e2d98ca8249/go.mod h1:imJK2QRE3080lm54nE96nRHXv7EvvVMCbF5N2QdGa9I=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
Expand Down Expand Up @@ -75,6 +77,8 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/surenderthakran/gomind v0.0.0-20180731125518-a31b8878d726 h1:fyLGtdazAP/DjaKEtJDfhcVrnsSWhyQOz2f9cqFpbGU=
github.com/surenderthakran/gomind v0.0.0-20180731125518-a31b8878d726/go.mod h1:DidfmKqbyzLjf4slOxXQnD5pGiDmYDzR0K/v+PdKDJM=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
Expand Down
16 changes: 8 additions & 8 deletions local/simulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ func main() {
bs := binance.NewPaperService()
exchangeService := interfaces.ExchangeService(bs)

//lun1MarCustomStrategy := strategies.NewLun1MarCustomStrategy()
//lun5JulCustomStrategy := strategies.NewLun5JulCustomStrategy()
//MACDCustomStrategy := strategies.NewMACDCustomStrategy()
lun1MarCustomStrategy := strategies.NewLun1MarCustomStrategy("1h")
lun5JulCustomStrategy := strategies.NewLun5JulCustomStrategy("1h")
MACDCustomStrategy := strategies.NewMACDCustomStrategy("1h")
//stableStrategy := strategies.NewStableStrategy()
//stochRSICustomStrategy := strategies.NewStochRSICustomStrategy()
stochRSICustomStrategy := strategies.NewStochRSICustomStrategy("1h")
mixedStrategy1 := strategies.NewMixedStrategy1("1h")

selectedStrategies := []interfaces.Strategy{
//&MACDCustomStrategy,
//&lun1MarCustomStrategy,
//&stochRSICustomStrategy,
&MACDCustomStrategy,
&lun1MarCustomStrategy,
&stochRSICustomStrategy,
&mixedStrategy1,
//&lun5JulCustomStrategy,
&lun5JulCustomStrategy,
//&stableStrategy,
}

Expand Down
30 changes: 25 additions & 5 deletions providers/paper/paper_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,33 @@ func (paperService *PaperService) GetSeries(pair string, interval string, limit
limit = 1000
}
timeSeries := techan.TimeSeries{}
klines, err := paperService.binanceClient.NewKlinesService().Symbol(pair).
Interval(interval).Limit(limit).Do(context.Background())
if err != nil {
return timeSeries, err

intervalSeconds := helpers.StringIntervalToSeconds(interval)

provisionalLimit := limit % 1000
if provisionalLimit == 0 {
provisionalLimit = 1000
}
var startTime int64
var resultKlines []*binance.Kline
for iterations := 0; limit != 0; iterations++ {
startTime = time.Now().Unix() - int64(intervalSeconds)*int64(limit)
klines, err := paperService.binanceClient.NewKlinesService().Symbol(pair).
Interval(interval).Limit(provisionalLimit).StartTime(startTime * 1000).Do(context.Background())
if err != nil {
fmt.Println(err)
return timeSeries, err
}

for _, k := range klines {
resultKlines = append(resultKlines, k)
}

limit -= provisionalLimit
provisionalLimit = 1000
}

for _, k := range klines {
for _, k := range resultKlines {
period := techan.NewTimePeriod(time.Unix(k.OpenTime/1000, 0), time.Minute*15)
candle := techan.NewCandle(period)
candle.OpenPrice = big.NewFromString(k.Open)
Expand Down
65 changes: 39 additions & 26 deletions strategies/lun1mar_custom_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package strategies

import (
"fmt"
"github.com/sdcoffey/big"
"github.com/sdcoffey/techan"
"gitlab.com/aoterocom/AOCryptobot/helpers"
"gitlab.com/aoterocom/AOCryptobot/interfaces"
"gitlab.com/aoterocom/AOCryptobot/models/analytics"
"gitlab.com/aoterocom/AOCryptobot/strategies/indicators"
"reflect"
"strings"
"time"
)

type Lun1MarCustomStrategy struct {
Expand Down Expand Up @@ -95,15 +97,14 @@ func (s *Lun1MarCustomStrategy) PerformSimulation(pair string, exchangeService i
return strategyResults, err
}
series.Candles = series.Candles[:len(series.Candles)-omit]

highestBalance := -1.0
balance := 1000.0
balance := 2000.0
var buyRate float64
var sellRate float64
open := false
entryConstant := 0.0
entryStop := 0.2
jump := 0.005
jump := 0.008
selectedEntryConstant := 0.0
var bestProfitList []float64

Expand All @@ -114,7 +115,7 @@ func (s *Lun1MarCustomStrategy) PerformSimulation(pair string, exchangeService i
for ; entryConstant < entryStop; entryConstant += jump {

var profitList []float64
balance = 1000.0
balance = 2000.0
for i := 5; i < len(series.Candles); i++ {

candles := series.Candles[:i]
Expand Down Expand Up @@ -149,10 +150,10 @@ func (s *Lun1MarCustomStrategy) PerformSimulation(pair string, exchangeService i
}

//fmt.Printf("BEST CONSTANT COMBINATION FOUND: Entry Constant: %.8f Profit: %.4f%%\n",
// selectedEntryConstant, highestBalance*100/1000-100)
// selectedEntryConstant, highestBalance*100/2000-100)

strategyResults.Trend = series.Candles[len(series.Candles)-1].ClosePrice.Float() / series.Candles[0].ClosePrice.Float()
strategyResults.Profit = highestBalance*100/1000 - 100
strategyResults.Profit = highestBalance*100/2000 - 100
strategyResults.ProfitList = bestProfitList
strategyResults.Period = limit - omit
strategyResults.Constants = append(strategyResults.Constants, selectedEntryConstant)
Expand All @@ -165,40 +166,52 @@ func (s *Lun1MarCustomStrategy) Analyze(pair string, exchangeService interfaces.

helpers.Logger.Debugln(fmt.Sprintf("→ Analyzing %s", strings.Replace(reflect.TypeOf(s).String(), "*strategies.", "", 1)))

// Analyze last 1000 candles
result15m1000, err := s.PerformSimulation(pair, exchangeService, s.Interval, 500, 0, nil)
// Analyze last 2000 candles
result2000, err := s.PerformSimulation(pair, exchangeService, s.Interval, 2000, 0, nil)
if err != nil {
return nil, err
}
// Analyze last 500 candles
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result15m1000)
result15m500, err := s.PerformSimulation(pair, exchangeService, s.Interval, 240, 0, &result15m1000.Constants)
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result2000)
result500, err := s.PerformSimulation(pair, exchangeService, s.Interval, 500, 0, &result2000.Constants)
if err != nil {
return nil, err
}
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result15m500)
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result500)

sum := helpers.Sum(result2000.ProfitList)
strategyAnalysis.Mean = sum / float64(len(result2000.ProfitList))
strategyAnalysis.StdDev = helpers.StdDev(result2000.ProfitList, strategyAnalysis.Mean)
strategyAnalysis.PositivismAvgRatio = (helpers.PositiveNegativeRatio(result500.ProfitList) + helpers.PositiveNegativeRatio(result2000.ProfitList)) / 2

timeSeries := techan.TimeSeries{}
for i, profit := range result2000.ProfitList {
candle := techan.NewCandle(techan.TimePeriod{Start: time.Unix(int64(i-1), 0), End: time.Unix(int64(i-1), 0)})
candle.OpenPrice = big.NewDecimal(profit)
timeSeries.AddCandle(candle)
}

//Calculate profit mean and standard deviation
profits := []float64{result15m1000.Profit, result15m500.Profit}
sum := helpers.Sum(profits)
strategyAnalysis.Mean = sum / float64(len(profits))
strategyAnalysis.StdDev = helpers.StdDev(profits, strategyAnalysis.Mean)
strategyAnalysis.PositivismAvgRatio = (helpers.PositiveNegativeRatio(result15m500.ProfitList) + helpers.PositiveNegativeRatio(result15m1000.ProfitList)) / 2
lastCandleIndex := len(timeSeries.Candles) - 1
var lastMA big.Decimal
var lastlastMA big.Decimal
if lastCandleIndex >= 4 {
maIndicator := techan.NewSimpleMovingAverage(techan.NewOpenPriceIndicator(&timeSeries), 5)
lastMA = maIndicator.Calculate(lastCandleIndex)
lastlastMA = maIndicator.Calculate(lastCandleIndex - 1)
}

// Conditions to accept strategy:
if result15m1000.Profit > 3.2 && result15m500.Profit > 2.0 &&
(helpers.PositiveNegativeRatio(result15m500.ProfitList) >= 1.2 ||
(len(result15m500.ProfitList) == 0 && helpers.PositiveNegativeRatio(result15m1000.ProfitList) >= 1.2)) {
if lastCandleIndex >= 4 && result2000.Profit > 3.2 && result500.Profit > 1.0 && lastMA.Float() >= lastlastMA.Float() {

strategyAnalysis.IsCandidate = true
helpers.Logger.Debugln(fmt.Sprintf("️ Strategy is tradeable: 1000CandleProfit, %f 500CandleProfit %f, 60%% of the Mean %f, Std Deviation %f, 1000 Profit Ratio %f 500 Profit Ratio %f", result15m1000.Profit, result15m500.Profit,
strategyAnalysis.Mean/0.6, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result15m1000.ProfitList),
helpers.PositiveNegativeRatio(result15m500.ProfitList)))
helpers.Logger.Debugln(fmt.Sprintf("️ Strategy is tradeable: 2000CandleProfit, %f 500CandleProfit %f, Profit Mean %f, Std Deviation %f, 2000 Profit Ratio %f 500 Profit Ratio %f", result2000.Profit, result500.Profit,
strategyAnalysis.Mean, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result2000.ProfitList),
helpers.PositiveNegativeRatio(result500.ProfitList)))
} else {
strategyAnalysis.IsCandidate = false
helpers.Logger.Debugln(fmt.Sprintf("❌️ Strategy is NOT tradeable: 1000CandleProfit, %f 500CandleProfit %f, 60%% of the Mean %f, Std Deviation %f, 1000 Profit Ratio %f 500 Profit Ratio %f", result15m1000.Profit, result15m500.Profit,
strategyAnalysis.Mean/0.6, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result15m1000.ProfitList),
helpers.PositiveNegativeRatio(result15m500.ProfitList)))
helpers.Logger.Debugln(fmt.Sprintf("❌️ Strategy is NOT tradeable: 2000CandleProfit, %f 500CandleProfit %f, Profit Mean %f, Std Deviation %f, 2000 Profit Ratio %f 500 Profit Ratio %f", result2000.Profit, result500.Profit,
strategyAnalysis.Mean, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result2000.ProfitList),
helpers.PositiveNegativeRatio(result500.ProfitList)))
}

return &strategyAnalysis, nil
Expand Down
53 changes: 33 additions & 20 deletions strategies/lun5jul_custom_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package strategies

import (
"fmt"
"github.com/sdcoffey/big"
"github.com/sdcoffey/techan"
"gitlab.com/aoterocom/AOCryptobot/helpers"
"gitlab.com/aoterocom/AOCryptobot/interfaces"
Expand Down Expand Up @@ -164,40 +165,52 @@ func (s *Lun5JulCustomStrategy) Analyze(pair string, exchangeService interfaces.

helpers.Logger.Debugln(fmt.Sprintf("→ Analyzing %s", strings.Replace(reflect.TypeOf(s).String(), "*strategies.", "", 1)))

// Analyze last 1000 candles
result15m1000, err := s.PerformSimulation(pair, exchangeService, s.Interval, 500, 0, nil)
// Analyze last 2000 candles
result2000, err := s.PerformSimulation(pair, exchangeService, s.Interval, 2000, 0, nil)
if err != nil {
return nil, err
}
// Analyze last 500 candles
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result15m1000)
result15m500, err := s.PerformSimulation(pair, exchangeService, s.Interval, 240, 0, &result15m1000.Constants)
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result2000)
result500, err := s.PerformSimulation(pair, exchangeService, s.Interval, 500, 0, &result2000.Constants)
if err != nil {
return nil, err
}
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result15m500)
strategyAnalysis.StrategyResults = append(strategyAnalysis.StrategyResults, result500)

sum := helpers.Sum(result2000.ProfitList)
strategyAnalysis.Mean = sum / float64(len(result2000.ProfitList))
strategyAnalysis.StdDev = helpers.StdDev(result2000.ProfitList, strategyAnalysis.Mean)
strategyAnalysis.PositivismAvgRatio = (helpers.PositiveNegativeRatio(result500.ProfitList) + helpers.PositiveNegativeRatio(result2000.ProfitList)) / 2

timeSeries := techan.TimeSeries{}
for i, profit := range result2000.ProfitList {
candle := techan.NewCandle(techan.TimePeriod{Start: time.Unix(int64(i-1), 0), End: time.Unix(int64(i-1), 0)})
candle.OpenPrice = big.NewDecimal(profit)
timeSeries.AddCandle(candle)
}

//Calculate profit mean and standard deviation
profits := []float64{result15m1000.Profit, result15m500.Profit}
sum := helpers.Sum(profits)
strategyAnalysis.Mean = sum / float64(len(profits))
strategyAnalysis.StdDev = helpers.StdDev(profits, strategyAnalysis.Mean)
strategyAnalysis.PositivismAvgRatio = (helpers.PositiveNegativeRatio(result15m500.ProfitList) + helpers.PositiveNegativeRatio(result15m1000.ProfitList)) / 2
lastCandleIndex := len(timeSeries.Candles) - 1
var lastMA big.Decimal
var lastlastMA big.Decimal
if lastCandleIndex >= 4 {
maIndicator := techan.NewSimpleMovingAverage(techan.NewOpenPriceIndicator(&timeSeries), 5)
lastMA = maIndicator.Calculate(lastCandleIndex)
lastlastMA = maIndicator.Calculate(lastCandleIndex - 1)
}

// Conditions to accept strategy:
if result15m1000.Profit > 3.2 && result15m500.Profit > 2.0 &&
(helpers.PositiveNegativeRatio(result15m500.ProfitList) >= 1.2 ||
(len(result15m500.ProfitList) == 0 && helpers.PositiveNegativeRatio(result15m1000.ProfitList) >= 1.2)) {
if lastCandleIndex >= 4 && result2000.Profit > 3.2 && result500.Profit > 1.0 && lastMA.Float() >= lastlastMA.Float() {

strategyAnalysis.IsCandidate = true
helpers.Logger.Debugln(fmt.Sprintf("️ Strategy is tradeable: 1000CandleProfit, %f 500CandleProfit %f, 60%% of the Mean %f, Std Deviation %f, 1000 Profit Ratio %f 500 Profit Ratio %f", result15m1000.Profit, result15m500.Profit,
strategyAnalysis.Mean/0.6, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result15m1000.ProfitList),
helpers.PositiveNegativeRatio(result15m500.ProfitList)))
helpers.Logger.Debugln(fmt.Sprintf("️ Strategy is tradeable: 2000CandleProfit, %f 500CandleProfit %f, Profit Mean %f, Std Deviation %f, 2000 Profit Ratio %f 500 Profit Ratio %f", result2000.Profit, result500.Profit,
strategyAnalysis.Mean, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result2000.ProfitList),
helpers.PositiveNegativeRatio(result500.ProfitList)))
} else {
strategyAnalysis.IsCandidate = false
helpers.Logger.Debugln(fmt.Sprintf("❌️ Strategy is NOT tradeable: 1000CandleProfit, %f 500CandleProfit %f, 60%% of the Mean %f, Std Deviation %f, 1000 Profit Ratio %f 500 Profit Ratio %f", result15m1000.Profit, result15m500.Profit,
strategyAnalysis.Mean/0.6, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result15m1000.ProfitList),
helpers.PositiveNegativeRatio(result15m500.ProfitList)))
helpers.Logger.Debugln(fmt.Sprintf("❌️ Strategy is NOT tradeable: 2000CandleProfit, %f 500CandleProfit %f, Profit Mean %f, Std Deviation %f, 2000 Profit Ratio %f 500 Profit Ratio %f", result2000.Profit, result500.Profit,
strategyAnalysis.Mean, strategyAnalysis.StdDev, helpers.PositiveNegativeRatio(result2000.ProfitList),
helpers.PositiveNegativeRatio(result500.ProfitList)))
}

return &strategyAnalysis, nil
Expand Down
Loading

0 comments on commit c6274c8

Please sign in to comment.