kline/exchanges: automatic creation of unsupported candle intervals (#1091)

* kline: Add builder and testing

* Ideas

* kline: deploy builder functionality across GCT

* exchanges: implement across gct

* exchanges: Add tests and fix implementations before kline package testing and veri.

* kline: Add tests and start to fix ConvertToNewInterval

* kline: fix ConvertToNewInterval add tests

* kline: complete overarching tests now on to exchanges

* kline: finish exchange tests and implement limits

* exchanges: more fixes

* linter: fix

* engine: fix tests

* kraken: fix recent trades and other fixes

* zb: fix tests

* bithumb: fix empty insertion

* kline: refactor/optimize CreateKline function

* kline: remove the mooos!

* kline: prealloc CalculateCandleDateRanges

* linter: fix

* exchanges: prealloc extended

* fix whoopsie

* reverse fix because this is a whoopsie

* okx: fix risidual issues

* linter: fix

* kline: initial nits from @gloriouscode

* kline: rename builder -> request and cascade change

* linter: fix + test

* kline: update forced alignment on start and end times when CreateKlineRequest is called.

* nits: more more more

* NITS: Addressed

* tests: fix race issue

* Update exchanges/kline/request.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* kline: add method AddPadding() to automatically fill in holes in kline.Request functionality and reject if missing data when converting

* kline: Add params start and end to addPadding() to insert blanks in between block

* kline: remove test comment code as it's not needed anymore

* kline: fix lint and test

* kline: sort slice without extra bool check every iteration

* okx: fix issues with timeing and candles and such from niterinos & address typo

* Update exchanges/kline/kline.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: niterinos

* Update exchanges/poloniex/poloniex_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits now onto conflicts YAYA!!!

* Update exchanges/exchange_test.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits again

* thrasher: nitters

* thrasher: niterinos - adds partial flag for incomplete recent candles and fetching.

* kline: rm fmtizzle packageizzle

* glorious: nitters

* glorious: more niterinos

* fix last niterinos

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
This commit is contained in:
Ryan O'Hara-Reid
2023-01-17 16:22:33 +11:00
committed by GitHub
parent 72f36d70d1
commit 83cfefa45c
110 changed files with 11312 additions and 5768 deletions

View File

@@ -2447,11 +2447,11 @@ func (s *RPCServer) GetHistoricCandles(ctx context.Context, r *gctrpc.GetHistori
resp := gctrpc.GetHistoricCandlesResponse{
Interval: interval.Short(),
Pair: r.Pair,
Start: r.Start,
End: r.End,
Start: start.UTC().Format(common.SimpleTimeFormatWithTimezone),
End: end.UTC().Format(common.SimpleTimeFormatWithTimezone),
}
var klineItem kline.Item
var klineItem *kline.Item
if r.UseDb {
klineItem, err = kline.LoadFromDatabase(r.Exchange,
pair,
@@ -2459,34 +2459,20 @@ func (s *RPCServer) GetHistoricCandles(ctx context.Context, r *gctrpc.GetHistori
interval,
start,
end)
if err != nil {
return nil, err
}
} else {
if r.ExRequest {
klineItem, err = exch.GetHistoricCandlesExtended(ctx,
pair,
a,
start,
end,
interval)
klineItem, err = exch.GetHistoricCandlesExtended(ctx, pair, a, interval, start, end)
} else {
klineItem, err = exch.GetHistoricCandles(ctx,
pair,
a,
start,
end,
interval)
klineItem, err = exch.GetHistoricCandles(ctx, pair, a, interval, start, end)
}
}
if err != nil {
return nil, err
}
if r.FillMissingWithTrades {
var tradeDataKline *kline.Item
tradeDataKline, err = fillMissingCandlesWithStoredTrades(start, end, &klineItem)
tradeDataKline, err = fillMissingCandlesWithStoredTrades(start, end, klineItem)
if err != nil {
return nil, err
}
@@ -2496,17 +2482,18 @@ func (s *RPCServer) GetHistoricCandles(ctx context.Context, r *gctrpc.GetHistori
resp.Exchange = klineItem.Exchange
for i := range klineItem.Candles {
resp.Candle = append(resp.Candle, &gctrpc.Candle{
Time: klineItem.Candles[i].Time.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone),
Low: klineItem.Candles[i].Low,
High: klineItem.Candles[i].High,
Open: klineItem.Candles[i].Open,
Close: klineItem.Candles[i].Close,
Volume: klineItem.Candles[i].Volume,
Time: klineItem.Candles[i].Time.UTC().Format(common.SimpleTimeFormatWithTimezone),
Low: klineItem.Candles[i].Low,
High: klineItem.Candles[i].High,
Open: klineItem.Candles[i].Open,
Close: klineItem.Candles[i].Close,
Volume: klineItem.Candles[i].Volume,
IsPartial: klineItem.Candles[i].ValidationIssues == kline.PartialCandle,
})
}
if r.Sync && !r.UseDb {
_, err = kline.StoreInDatabase(&klineItem, r.Force)
_, err = kline.StoreInDatabase(klineItem, r.Force)
if err != nil {
if errors.Is(err, exchangeDB.ErrNoExchangeFound) {
return nil, errors.New("exchange was not found in database, you can seed existing data or insert a new exchange via the dbseed")
@@ -2533,7 +2520,7 @@ func fillMissingCandlesWithStoredTrades(startTime, endTime time.Time, klineItem
if ranges[i].HasDataInRange {
continue
}
var tradeCandles kline.Item
var tradeCandles *kline.Item
trades, err := trade.GetTradesInRange(
klineItem.Exchange,
klineItem.Asset.String(),
@@ -3260,17 +3247,16 @@ func (s *RPCServer) ConvertTradesToCandles(_ context.Context, r *gctrpc.ConvertT
return nil, err
}
var trades []trade.Data
trades, err = trade.GetTradesInRange(r.Exchange, r.AssetType, r.Pair.Base, r.Pair.Quote, start, end)
trades, err := trade.GetTradesInRange(r.Exchange, r.AssetType, r.Pair.Base, r.Pair.Quote, start, end)
if err != nil {
return nil, err
}
if len(trades) == 0 {
return nil, errNoTrades
}
interval := kline.Interval(r.TimeInterval)
var klineItem kline.Item
klineItem, err = trade.ConvertTradesToCandles(interval, trades...)
klineItem, err := trade.ConvertTradesToCandles(interval, trades...)
if err != nil {
return nil, err
}
@@ -3287,17 +3273,18 @@ func (s *RPCServer) ConvertTradesToCandles(_ context.Context, r *gctrpc.ConvertT
}
for i := range klineItem.Candles {
resp.Candle = append(resp.Candle, &gctrpc.Candle{
Time: klineItem.Candles[i].Time.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone),
Low: klineItem.Candles[i].Low,
High: klineItem.Candles[i].High,
Open: klineItem.Candles[i].Open,
Close: klineItem.Candles[i].Close,
Volume: klineItem.Candles[i].Volume,
Time: klineItem.Candles[i].Time.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone),
Low: klineItem.Candles[i].Low,
High: klineItem.Candles[i].High,
Open: klineItem.Candles[i].Open,
Close: klineItem.Candles[i].Close,
Volume: klineItem.Candles[i].Volume,
IsPartial: klineItem.Candles[i].ValidationIssues == kline.PartialCandle,
})
}
if r.Sync {
_, err = kline.StoreInDatabase(&klineItem, r.Force)
_, err = kline.StoreInDatabase(klineItem, r.Force)
if err != nil {
return nil, err
}
@@ -5023,19 +5010,11 @@ func (s *RPCServer) GetTechnicalAnalysis(ctx context.Context, r *gctrpc.GetTechn
return nil, err
}
klineInterval := kline.Interval(r.Interval)
err = exch.GetBase().ValidateKline(pair, as, klineInterval)
if err != nil {
return nil, err
}
klines, err := exch.GetHistoricCandlesExtended(ctx,
pair,
klines, err := exch.GetHistoricCandlesExtended(ctx, pair,
as,
kline.Interval(r.Interval),
r.Start.AsTime(),
r.End.AsTime(),
klineInterval)
r.End.AsTime())
if err != nil {
return nil, err
}
@@ -5102,15 +5081,19 @@ func (s *RPCServer) GetTechnicalAnalysis(ctx context.Context, r *gctrpc.GetTechn
return nil, err
}
var otherKlines kline.Item
var otherKlines *kline.Item
otherKlines, err = otherExch.GetHistoricCandlesExtended(ctx,
otherPair, otherAs, r.Start.AsTime(), r.End.AsTime(), klineInterval)
otherPair,
otherAs,
kline.Interval(r.Interval),
r.Start.AsTime(),
r.End.AsTime())
if err != nil {
return nil, err
}
var correlation []float64
correlation, err = klines.GetCorrelationCoefficient(&otherKlines, r.Period)
correlation, err = klines.GetCorrelationCoefficient(otherKlines, r.Period)
if err != nil {
return nil, err
}