technical_analysis: TWAP & VWAP + TA methods to candles and link to existing RPC server for GCTCLI prototyping (#970)

* kline: add weighted price helpers for candles

* twap/vwap: basic implementation and hook to rpc for protype

* ta: cont implementation. (WIP)

* kline: Add tests

* kline: add helpers

* ta: full impl.

* kline: remove support for macd and add in correlation-coefficient handling

* rpc: change naming convention

* linter: fix

* protolinter: fix

* linter: ++

* kline: reinstate macd handling after adding in check

* glorious: nits

* gctcl: linter

* Update exchanges/kline/weighted_price.go

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

* glorious: nits

* glorious: nits v2.0

* kline: fix test

* huobi-tests: shift from next quarter to this weeks contracts as they were erroring out in tests.

* btcmarkets: update supported kline intervals

* zb: fix test

* rpcserver: fix bug and tests

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
2022-07-08 15:21:56 +10:00
committed by GitHub
parent 68db4155bf
commit 7da745120f
21 changed files with 3509 additions and 325 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/common"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/timestamppb"
)
func clearScreen() error {
@@ -48,3 +49,8 @@ func negateLocalOffset(t time.Time) string {
return t.In(loc).Format(common.SimpleTimeFormat)
}
func negateLocalOffsetTS(t time.Time) *timestamppb.Timestamp {
_, offset := time.Now().Zone()
return timestamppb.New(t.Add(time.Duration(-offset) * time.Second))
}

View File

@@ -29,6 +29,7 @@ var (
certPath string
timeout time.Duration
exchangeCreds exchange.Credentials
verbose bool
)
const defaultTimeout = time.Second * 30
@@ -60,6 +61,9 @@ func setupClient(c *cli.Context) (*grpc.ClientConn, context.CancelFunc, error) {
flag, values := exchangeCreds.GetMetaData()
c.Context = metadata.AppendToOutgoingContext(c.Context, flag, values)
}
if verbose {
c.Context = metadata.AppendToOutgoingContext(c.Context, "verbose", "true")
}
conn, err := grpc.DialContext(c.Context, host, opts...)
return conn, cancel, err
}
@@ -137,6 +141,11 @@ func main() {
Usage: "override config API One Time Password (OTP) for request",
Destination: &exchangeCreds.OneTimePassword,
},
&cli.BoolFlag{
Name: "verbose",
Usage: "allows the request to generate a more verbose outputs server side",
Destination: &verbose,
},
}
app.Commands = []*cli.Command{
getInfoCommand,
@@ -203,6 +212,7 @@ func main() {
getFuturesPositionsCommand,
getCollateralCommand,
shutdownCommand,
technicalAnalysisCommand,
}
ctx, cancel := context.WithCancel(context.Background())

View File

@@ -0,0 +1,800 @@
package main
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/gctrpc"
"github.com/urfave/cli/v2"
)
var (
taStartTime string
taEndTime string
taGranularity int64
taPeriod int64
taFastPeriod int64
taSlowPeriod int64
taMovingAverageType string
taStdDevUp float64
taStdDevDown float64
)
var commonFlag = []cli.Flag{
&cli.StringFlag{
Name: "exchange",
Usage: "the exchange to act on",
},
&cli.StringFlag{
Name: "pair",
Usage: "currency pair",
},
&cli.StringFlag{
Name: "asset",
Usage: "asset",
},
&cli.Int64Flag{
Name: "granularity",
Aliases: []string{"g"},
Usage: klineMessage,
Value: 86400,
Destination: &taGranularity,
},
&cli.StringFlag{
Name: "start",
Usage: "the start date",
Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat),
Destination: &taStartTime,
},
&cli.StringFlag{
Name: "end",
Usage: "the end date",
Value: time.Now().Format(common.SimpleTimeFormat),
Destination: &taEndTime,
},
}
var (
periodFlag = &cli.Int64Flag{
Name: "period",
Usage: "denotes period (rolling window) for technical analysis",
Value: 9,
Destination: &taPeriod,
}
fastFlag = &cli.Int64Flag{
Name: "fastperiod",
Usage: "denotes fast period (ema) for macd generation",
Value: 12,
Destination: &taFastPeriod,
}
slowFlag = &cli.Int64Flag{
Name: "slowperiod",
Usage: "denotes slow period (ema) for macd generation",
Value: 26,
Destination: &taSlowPeriod,
}
stdDevUpFlag = &cli.Float64Flag{
Name: "stddevup",
Usage: "standard deviation limit for upper band",
Value: 1.5,
Destination: &taStdDevUp,
}
stdDevDownFlag = &cli.Float64Flag{
Name: "stddevdown",
Usage: "standard deviation limit for lower band",
Value: 1.5,
Destination: &taStdDevDown,
}
maTypeFlag = &cli.StringFlag{
Name: "movingaveragetype",
Usage: "defines the moving average type for underlying calculation ('ema'/'sma')",
Value: "sma",
Destination: &taMovingAverageType,
}
otherAssetFlag = []cli.Flag{
&cli.StringFlag{
Name: "comparisonexchange",
Usage: "the other exchange to compare to - if not supplied will default to initial exchange",
Aliases: []string{"ce", "cexchange", "oe", "otherexchange"},
},
&cli.StringFlag{
Name: "comparisonpair",
Usage: "the other currency pair",
Aliases: []string{"cp", "cpair", "op", "otherpair"},
},
&cli.StringFlag{
Name: "comparisonasset",
Usage: "the other asset - if not supplied will default to initial exchange",
Aliases: []string{"ca", "casset", "oa", "otherasset"},
},
}
)
var technicalAnalysisCommand = &cli.Command{
Name: "technicalanalysis",
Usage: "get techincal analysis command",
Aliases: []string{"ta"},
ArgsUsage: "<command> <args>",
Subcommands: []*cli.Command{
{
Name: "twap",
Usage: "returns the time weighted average price",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end>",
Flags: commonFlag,
Action: getTWAP,
},
{
Name: "vwap",
Usage: "returns the volume weighted average price",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end>",
Flags: commonFlag,
Action: getVWAP,
},
{
Name: "atr",
Usage: "returns the average true range",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period>",
Flags: append(commonFlag, periodFlag),
Action: getATR,
},
{
Name: "bbands",
Usage: "returns the bollinger bands",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period> <std deviation up> <std deviation down> <moving average type>",
Flags: append(commonFlag, periodFlag, stdDevUpFlag, stdDevDownFlag, maTypeFlag),
Action: getBollingerBands,
},
{
Name: "coco",
Usage: "returns the correlation-coefficient",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <other exchange> <other asset> <other pair>",
Flags: append(commonFlag, append([]cli.Flag{periodFlag}, otherAssetFlag...)...),
Action: getCoco,
},
{
Name: "sma",
Usage: "returns the simple moving average",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period>",
Flags: append(commonFlag, periodFlag),
Action: getSMA,
},
{
Name: "ema",
Usage: "returns the exponential moving average",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period>",
Flags: append(commonFlag, periodFlag),
Action: getEMA,
},
{
Name: "macd",
Usage: "returns the moving average convergence divergence",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period> <fast period> <slow period>",
Flags: append(commonFlag, periodFlag, fastFlag, slowFlag),
Action: getMACD,
},
{
Name: "mfi",
Usage: "returns the money flow index",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period>",
Flags: append(commonFlag, periodFlag),
Action: getMFI,
},
{
Name: "obv",
Usage: "returns the on balance volume",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end>",
Flags: commonFlag,
Action: getOBV,
},
{
Name: "rsi",
Usage: "returns the relative strength index",
ArgsUsage: "<exchange> <pair> <asset> <granularity> <start> <end> <period>",
Flags: append(commonFlag, periodFlag),
Action: getRSI,
},
},
}
func getTWAP(c *cli.Context) error {
return getTecnicalAnalysis(c, "TWAP")
}
func getVWAP(c *cli.Context) error {
return getTecnicalAnalysis(c, "VWAP")
}
func getATR(c *cli.Context) error {
return getTecnicalAnalysis(c, "ATR")
}
func getSMA(c *cli.Context) error {
return getTecnicalAnalysis(c, "SMA")
}
func getEMA(c *cli.Context) error {
return getTecnicalAnalysis(c, "EMA")
}
func getMFI(c *cli.Context) error {
return getTecnicalAnalysis(c, "MFI")
}
func getOBV(c *cli.Context) error {
return getTecnicalAnalysis(c, "OBV")
}
func getRSI(c *cli.Context) error {
return getTecnicalAnalysis(c, "RSI")
}
func getTecnicalAnalysis(c *cli.Context, algo string) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
return cli.ShowSubcommandHelp(c)
}
var exchange string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
var cpString string
if c.IsSet("pair") {
cpString = c.String("pair")
} else {
cpString = c.Args().Get(1)
}
pair, err := currency.NewPairFromString(cpString)
if err != nil {
return err
}
var asset string
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(2)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
if c.IsSet("granularity") {
taGranularity = c.Int64("granularity")
} else if c.Args().Get(3) != "" {
taGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
if err != nil {
return err
}
}
if !c.IsSet("start") {
if c.Args().Get(4) != "" {
taStartTime = c.Args().Get(4)
}
} else {
taStartTime, _ = c.Value("start").(string)
}
if !c.IsSet("end") {
if c.Args().Get(5) != "" {
taEndTime = c.Args().Get(5)
}
} else {
taEndTime, _ = c.Value("end").(string)
}
s, err := time.Parse(common.SimpleTimeFormat, taStartTime)
if err != nil {
return fmt.Errorf("invalid time format for start: %v", err)
}
e, err := time.Parse(common.SimpleTimeFormat, taEndTime)
if err != nil {
return fmt.Errorf("invalid time format for end: %v", err)
}
err = common.StartEndTimeCheck(s, e)
if err != nil {
return err
}
if !c.IsSet("period") {
if c.Args().Get(6) != "" {
taPeriod, err = strconv.ParseInt(c.Args().Get(6), 10, 64)
if err != nil {
return err
}
}
} else {
taPeriod, _ = c.Value("period").(int64)
}
conn, cancel, err := setupClient(c)
if err != nil {
return err
}
defer closeConn(conn, cancel)
req := &gctrpc.GetTechnicalAnalysisRequest{
Exchange: exchange,
Pair: &gctrpc.CurrencyPair{
Base: pair.Base.String(),
Quote: pair.Quote.String(),
},
AssetType: asset,
AlgorithmType: algo,
Interval: taGranularity * int64(time.Second),
Start: negateLocalOffsetTS(s),
End: negateLocalOffsetTS(e),
Period: taPeriod,
}
client := gctrpc.NewGoCryptoTraderServiceClient(conn)
result, err := client.GetTechnicalAnalysis(c.Context, req)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
func getBollingerBands(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
return cli.ShowSubcommandHelp(c)
}
var exchange string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
var cpString string
if c.IsSet("pair") {
cpString = c.String("pair")
} else {
cpString = c.Args().Get(1)
}
pair, err := currency.NewPairFromString(cpString)
if err != nil {
return err
}
var asset string
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(2)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
if c.IsSet("granularity") {
taGranularity = c.Int64("granularity")
} else if c.Args().Get(3) != "" {
taGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
if err != nil {
return err
}
}
if !c.IsSet("start") {
if c.Args().Get(4) != "" {
taStartTime = c.Args().Get(4)
}
} else {
taStartTime, _ = c.Value("start").(string)
}
if !c.IsSet("end") {
if c.Args().Get(5) != "" {
taEndTime = c.Args().Get(5)
}
} else {
taEndTime, _ = c.Value("end").(string)
}
s, err := time.Parse(common.SimpleTimeFormat, taStartTime)
if err != nil {
return fmt.Errorf("invalid time format for start: %v", err)
}
e, err := time.Parse(common.SimpleTimeFormat, taEndTime)
if err != nil {
return fmt.Errorf("invalid time format for end: %v", err)
}
err = common.StartEndTimeCheck(s, e)
if err != nil {
return err
}
if !c.IsSet("period") {
if c.Args().Get(6) != "" {
taPeriod, err = strconv.ParseInt(c.Args().Get(6), 10, 64)
if err != nil {
return err
}
}
} else {
taPeriod, _ = c.Value("period").(int64)
}
if !c.IsSet("stddevup") {
if c.Args().Get(7) != "" {
taStdDevUp, err = strconv.ParseFloat(c.Args().Get(7), 64)
if err != nil {
return err
}
}
} else {
taStdDevUp, _ = c.Value("stddevup").(float64)
}
if !c.IsSet("stddevdown") {
if c.Args().Get(8) != "" {
taStdDevDown, err = strconv.ParseFloat(c.Args().Get(8), 64)
if err != nil {
return err
}
}
} else {
taStdDevDown, _ = c.Value("stddevdown").(float64)
}
if !c.IsSet("movingaveragetype") && c.Args().Get(9) != "" {
taMovingAverageType = c.Args().Get(9)
} else {
taMovingAverageType, _ = c.Value("movingaveragetype").(string)
}
var maType int64
switch strings.ToLower(taMovingAverageType) {
case "sma":
case "ema":
maType = 1
default:
return errors.New("invalid moving average type")
}
conn, cancel, err := setupClient(c)
if err != nil {
return err
}
defer closeConn(conn, cancel)
req := &gctrpc.GetTechnicalAnalysisRequest{
Exchange: exchange,
Pair: &gctrpc.CurrencyPair{
Base: pair.Base.String(),
Quote: pair.Quote.String(),
},
AssetType: asset,
AlgorithmType: "BBANDS",
Interval: taGranularity * int64(time.Second),
Start: negateLocalOffsetTS(s),
End: negateLocalOffsetTS(e),
Period: taPeriod,
StandardDeviationUp: taStdDevUp,
StandardDeviationDown: taStdDevDown,
MovingAverageType: maType,
}
client := gctrpc.NewGoCryptoTraderServiceClient(conn)
result, err := client.GetTechnicalAnalysis(c.Context, req)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
func getMACD(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
return cli.ShowSubcommandHelp(c)
}
var exchange string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
var cpString string
if c.IsSet("pair") {
cpString = c.String("pair")
} else {
cpString = c.Args().Get(1)
}
pair, err := currency.NewPairFromString(cpString)
if err != nil {
return err
}
var asset string
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(2)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
if c.IsSet("granularity") {
taGranularity = c.Int64("granularity")
} else if c.Args().Get(3) != "" {
taGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
if err != nil {
return err
}
}
if !c.IsSet("start") {
if c.Args().Get(4) != "" {
taStartTime = c.Args().Get(4)
}
} else {
taStartTime, _ = c.Value("start").(string)
}
if !c.IsSet("end") {
if c.Args().Get(5) != "" {
taEndTime = c.Args().Get(5)
}
} else {
taEndTime, _ = c.Value("end").(string)
}
s, err := time.Parse(common.SimpleTimeFormat, taStartTime)
if err != nil {
return fmt.Errorf("invalid time format for start: %v", err)
}
e, err := time.Parse(common.SimpleTimeFormat, taEndTime)
if err != nil {
return fmt.Errorf("invalid time format for end: %v", err)
}
err = common.StartEndTimeCheck(s, e)
if err != nil {
return err
}
if !c.IsSet("period") {
if c.Args().Get(6) != "" {
taPeriod, err = strconv.ParseInt(c.Args().Get(6), 10, 64)
if err != nil {
return err
}
}
} else {
taPeriod, _ = c.Value("period").(int64)
}
if !c.IsSet("fastperiod") {
if c.Args().Get(7) != "" {
taFastPeriod, err = strconv.ParseInt(c.Args().Get(7), 10, 64)
if err != nil {
return err
}
}
} else {
taFastPeriod, _ = c.Value("fastperiod").(int64)
}
if !c.IsSet("slowperiod") {
if c.Args().Get(8) != "" {
taSlowPeriod, err = strconv.ParseInt(c.Args().Get(8), 10, 64)
if err != nil {
return err
}
}
} else {
taSlowPeriod, _ = c.Value("slowperiod").(int64)
}
conn, cancel, err := setupClient(c)
if err != nil {
return err
}
defer closeConn(conn, cancel)
req := &gctrpc.GetTechnicalAnalysisRequest{
Exchange: exchange,
Pair: &gctrpc.CurrencyPair{
Base: pair.Base.String(),
Quote: pair.Quote.String(),
},
AssetType: asset,
AlgorithmType: "MACD",
Interval: taGranularity * int64(time.Second),
Start: negateLocalOffsetTS(s),
End: negateLocalOffsetTS(e),
Period: taPeriod,
SlowPeriod: taSlowPeriod,
FastPeriod: taFastPeriod,
}
client := gctrpc.NewGoCryptoTraderServiceClient(conn)
result, err := client.GetTechnicalAnalysis(c.Context, req)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
func getCoco(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
return cli.ShowSubcommandHelp(c)
}
var exchange string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
var cpString string
if c.IsSet("pair") {
cpString = c.String("pair")
} else {
cpString = c.Args().Get(1)
}
pair, err := currency.NewPairFromString(cpString)
if err != nil {
return err
}
var asset string
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(2)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
if c.IsSet("granularity") {
taGranularity = c.Int64("granularity")
} else if c.Args().Get(3) != "" {
taGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
if err != nil {
return err
}
}
if !c.IsSet("start") {
if c.Args().Get(4) != "" {
taStartTime = c.Args().Get(4)
}
} else {
taStartTime, _ = c.Value("start").(string)
}
if !c.IsSet("end") {
if c.Args().Get(5) != "" {
taEndTime = c.Args().Get(5)
}
} else {
taEndTime, _ = c.Value("end").(string)
}
s, err := time.Parse(common.SimpleTimeFormat, taStartTime)
if err != nil {
return fmt.Errorf("invalid time format for start: %v", err)
}
e, err := time.Parse(common.SimpleTimeFormat, taEndTime)
if err != nil {
return fmt.Errorf("invalid time format for end: %v", err)
}
err = common.StartEndTimeCheck(s, e)
if err != nil {
return err
}
if !c.IsSet("period") {
if c.Args().Get(6) != "" {
taPeriod, err = strconv.ParseInt(c.Args().Get(6), 10, 64)
if err != nil {
return err
}
}
} else {
taPeriod, _ = c.Value("period").(int64)
}
var otherExchange string
if c.IsSet("comparisonexchange") {
otherExchange = c.String("comparisonexchange")
} else {
otherExchange = c.Args().Get(7)
}
var oCpString string
if c.IsSet("comparisonpair") {
oCpString = c.String("comparisonpair")
} else {
oCpString = c.Args().Get(8)
}
if oCpString == "" {
return errors.New("other pair is empty, to compare this must be specified")
}
otherPair, err := currency.NewPairFromString(oCpString)
if err != nil {
return err
}
var otherAsset string
if c.IsSet("comparisonasset") {
otherAsset = c.String("comparisonasset")
} else {
otherAsset = c.Args().Get(9)
}
otherAsset = strings.ToLower(otherAsset)
if otherAsset != "" && !validAsset(otherAsset) {
return errInvalidAsset
}
conn, cancel, err := setupClient(c)
if err != nil {
return err
}
defer closeConn(conn, cancel)
req := &gctrpc.GetTechnicalAnalysisRequest{
Exchange: exchange,
Pair: &gctrpc.CurrencyPair{
Base: pair.Base.String(),
Quote: pair.Quote.String(),
},
AssetType: asset,
AlgorithmType: "COCO",
Interval: taGranularity * int64(time.Second),
Start: negateLocalOffsetTS(s),
End: negateLocalOffsetTS(e),
Period: taPeriod,
OtherExchange: otherExchange,
OtherPair: &gctrpc.CurrencyPair{Base: otherPair.Base.String(), Quote: otherPair.Quote.String()},
OtherAssetType: otherAsset,
}
client := gctrpc.NewGoCryptoTraderServiceClient(conn)
result, err := client.GetTechnicalAnalysis(c.Context, req)
if err != nil {
return err
}
jsonOutput(result)
return nil
}

View File

@@ -19,6 +19,7 @@ import (
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/pquerna/otp/totp"
"github.com/shopspring/decimal"
"github.com/thrasher-corp/gct-ta/indicators"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/common/file"
@@ -36,6 +37,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
"github.com/thrasher-corp/gocryptotrader/gctrpc"
@@ -71,6 +73,7 @@ var (
errNoAccountInformation = errors.New("account information does not exist")
errShutdownNotAllowed = errors.New("shutting down this bot instance is not allowed via gRPC, please enable by command line flag --grpcshutdown or config.json field grpcAllowBotShutdown")
errGRPCShutdownSignalIsNil = errors.New("cannot shutdown, gRPC shutdown channel is nil")
errInvalidStrategy = errors.New("invalid strategy")
)
// RPCServer struct
@@ -108,7 +111,15 @@ func (s *RPCServer) authenticateClient(ctx context.Context) (context.Context, er
password != s.Config.RemoteControl.Password {
return ctx, fmt.Errorf("username/password mismatch")
}
return exchange.ParseCredentialsMetadata(ctx, md)
ctx, err = exchange.ParseCredentialsMetadata(ctx, md)
if err != nil {
return ctx, err
}
if _, ok := md["verbose"]; ok {
ctx = request.WithVerbose(ctx)
}
return ctx, nil
}
// StartRPCServer starts a gRPC server with TLS auth
@@ -4575,3 +4586,166 @@ func (s *RPCServer) Shutdown(_ context.Context, _ *gctrpc.ShutdownRequest) (*gct
s.Engine.GRPCShutdownSignal = nil
return &gctrpc.ShutdownResponse{}, nil
}
// GetTechnicalAnalysis using the requested technical analysis method will
// return a set(s) of signals for price action analysis.
func (s *RPCServer) GetTechnicalAnalysis(ctx context.Context, r *gctrpc.GetTechnicalAnalysisRequest) (*gctrpc.GetTechnicalAnalysisResponse, error) {
exch, err := s.GetExchangeByName(r.Exchange)
if err != nil {
return nil, err
}
as, err := asset.New(r.AssetType)
if err != nil {
return nil, err
}
pair, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
if err != nil {
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,
as,
r.Start.AsTime(),
r.End.AsTime(),
klineInterval)
if err != nil {
return nil, err
}
signals := make(map[string]*gctrpc.ListOfSignals)
switch strings.ToUpper(r.AlgorithmType) {
case "TWAP":
var price float64
price, err = klines.GetTWAP()
if err != nil {
return nil, err
}
signals["TWAP"] = &gctrpc.ListOfSignals{Signals: []float64{price}}
case "VWAP":
var prices []float64
prices, err = klines.GetVWAPs()
if err != nil {
return nil, err
}
signals["VWAP"] = &gctrpc.ListOfSignals{Signals: prices}
case "ATR":
var prices []float64
prices, err = klines.GetAverageTrueRange(r.Period)
if err != nil {
return nil, err
}
signals["ATR"] = &gctrpc.ListOfSignals{Signals: prices}
case "BBANDS":
var bollinger *kline.Bollinger
bollinger, err = klines.GetBollingerBands(r.Period,
r.StandardDeviationUp,
r.StandardDeviationDown,
indicators.MaType(r.MovingAverageType))
if err != nil {
return nil, err
}
signals["UPPER"] = &gctrpc.ListOfSignals{Signals: bollinger.Upper}
signals["MIDDLE"] = &gctrpc.ListOfSignals{Signals: bollinger.Middle}
signals["LOWER"] = &gctrpc.ListOfSignals{Signals: bollinger.Lower}
case "COCO":
otherExch := exch
if r.OtherExchange != "" {
otherExch, err = s.GetExchangeByName(r.OtherExchange)
if err != nil {
return nil, err
}
}
otherAs := as
if r.OtherAssetType != "" {
otherAs, err = asset.New(r.OtherAssetType)
if err != nil {
return nil, err
}
}
if r.OtherPair.String() == "" {
return nil, errors.New("other pair is empty, to compare this must be specified")
}
var otherPair currency.Pair
otherPair, err = currency.NewPairFromStrings(r.OtherPair.Base, r.OtherPair.Quote)
if err != nil {
return nil, err
}
var otherKlines kline.Item
otherKlines, err = otherExch.GetHistoricCandlesExtended(ctx,
otherPair, otherAs, r.Start.AsTime(), r.End.AsTime(), klineInterval)
if err != nil {
return nil, err
}
var correlation []float64
correlation, err = klines.GetCorrelationCoefficient(&otherKlines, r.Period)
if err != nil {
return nil, err
}
signals["COCO"] = &gctrpc.ListOfSignals{Signals: correlation}
case "SMA":
var prices []float64
prices, err = klines.GetSimpleMovingAverageOnClose(r.Period)
if err != nil {
return nil, err
}
signals["SMA"] = &gctrpc.ListOfSignals{Signals: prices}
case "EMA":
var prices []float64
prices, err = klines.GetExponentialMovingAverageOnClose(r.Period)
if err != nil {
return nil, err
}
signals["EMA"] = &gctrpc.ListOfSignals{Signals: prices}
case "MACD":
var macd *kline.MACD
macd, err = klines.GetMovingAverageConvergenceDivergenceOnClose(r.FastPeriod,
r.SlowPeriod,
r.Period)
if err != nil {
return nil, err
}
signals["MACD"] = &gctrpc.ListOfSignals{Signals: macd.Results}
signals["SIGNAL"] = &gctrpc.ListOfSignals{Signals: macd.SignalVals}
signals["HISTOGRAM"] = &gctrpc.ListOfSignals{Signals: macd.Histogram}
case "MFI":
var prices []float64
prices, err = klines.GetMoneyFlowIndex(r.Period)
if err != nil {
return nil, err
}
signals["MFI"] = &gctrpc.ListOfSignals{Signals: prices}
case "OBV":
var prices []float64
prices, err = klines.GetOnBalanceVolume()
if err != nil {
return nil, err
}
signals["OBV"] = &gctrpc.ListOfSignals{Signals: prices}
case "RSI":
var prices []float64
prices, err = klines.GetRelativeStrengthIndexOnClose(r.Period)
if err != nil {
return nil, err
}
signals["RSI"] = &gctrpc.ListOfSignals{Signals: prices}
default:
return nil, fmt.Errorf("%w '%s'", errInvalidStrategy, r.AlgorithmType)
}
return &gctrpc.GetTechnicalAnalysisResponse{Signals: signals}, nil
}

View File

@@ -72,22 +72,29 @@ func (f fExchange) GetHistoricCandles(ctx context.Context, p currency.Pair, a as
}, nil
}
func generateCandles(amount int, timeStart time.Time, interval kline.Interval) []kline.Candle {
candy := make([]kline.Candle, amount)
for x := 0; x < amount; x++ {
candy[x] = kline.Candle{
Time: timeStart,
Open: 1337,
High: 1337,
Low: 1337,
Close: 1337,
Volume: 1337,
}
timeStart = timeStart.Add(interval.Duration())
}
return candy
}
func (f fExchange) GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{
Exchange: fakeExchangeName,
Pair: p,
Asset: a,
Interval: interval,
Candles: []kline.Candle{
{
Time: timeStart,
Open: 1337,
High: 1337,
Low: 1337,
Close: 1337,
Volume: 1337,
},
},
Candles: generateCandles(33, timeStart, interval),
}, nil
}
@@ -2340,3 +2347,275 @@ func TestShutdown(t *testing.T) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetTechnicalAnalysis(t *testing.T) {
t.Parallel()
em := SetupExchangeManager()
exch, err := em.NewExchangeByName(testExchange)
if err != nil {
t.Fatal(err)
}
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-usd")
if !errors.Is(err, nil) {
t.Fatalf("received '%v', expected '%v'", err, nil)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.Futures] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
b.CurrencyPairs.Pairs[asset.Spot] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
b.Features.Enabled.Kline.Intervals = map[string]bool{
kline.OneDay.Word(): true,
}
em.Add(fExchange{IBotExchange: exch})
s := RPCServer{
Engine: &Engine{
ExchangeManager: em,
currencyStateManager: &CurrencyStateManager{
started: 1,
iExchangeManager: em,
},
},
}
_, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{})
if !errors.Is(err, ErrExchangeNameIsEmpty) {
t.Fatalf("received: '%v' but expected: '%v'", err, ErrExchangeNameIsEmpty)
}
_, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
})
if !errors.Is(err, asset.ErrNotSupported) {
t.Fatalf("received: '%v' but expected: '%v'", err, asset.ErrNotSupported)
}
_, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "upsideprofitcontract",
Pair: &gctrpc.CurrencyPair{},
})
if !errors.Is(err, kline.ErrValidatingParams) {
t.Fatalf("received: '%v' but expected: '%v'", err, kline.ErrValidatingParams)
}
_, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
})
if !errors.Is(err, errInvalidStrategy) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidStrategy)
}
resp, err := s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "twap",
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if resp.Signals["TWAP"].Signals[0] != 1337 {
t.Fatalf("received: '%v' but expected: '%v'", resp.Signals["TWAP"].Signals[0], 1337)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "vwap",
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["VWAP"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["VWAP"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "atr",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["ATR"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["ATR"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "bbands",
Period: 9,
StandardDeviationUp: 0.5,
StandardDeviationDown: 0.5,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["UPPER"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["UPPER"].Signals), 33)
}
if len(resp.Signals["MIDDLE"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["MIDDLE"].Signals), 33)
}
if len(resp.Signals["LOWER"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["LOWER"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
OtherPair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "COCO",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["COCO"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["COCO"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "sma",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["SMA"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["SMA"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "ema",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["EMA"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["EMA"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "macd",
Period: 9,
FastPeriod: 12,
SlowPeriod: 26,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["MACD"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["MACD"].Signals), 33)
}
if len(resp.Signals["SIGNAL"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["SIGNAL"].Signals), 33)
}
if len(resp.Signals["HISTOGRAM"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["HISTOGRAM"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "mfi",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["MFI"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["MFI"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "obv",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["OBV"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["OBV"].Signals), 33)
}
resp, err = s.GetTechnicalAnalysis(context.Background(), &gctrpc.GetTechnicalAnalysisRequest{
Exchange: fakeExchangeName,
AssetType: "spot",
Pair: &gctrpc.CurrencyPair{Base: "btc", Quote: "usd"},
Interval: int64(kline.OneDay),
AlgorithmType: "rsi",
Period: 9,
})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if len(resp.Signals["RSI"].Signals) != 33 {
t.Fatalf("received: '%v' but expected: '%v'", len(resp.Signals["RSI"].Signals), 33)
}
}

View File

@@ -114,9 +114,15 @@ func (b *BTCMarkets) SetDefaults() {
AutoPairUpdates: true,
Kline: kline.ExchangeCapabilitiesEnabled{
Intervals: map[string]bool{
kline.OneMin.Word(): true,
kline.OneHour.Word(): true,
kline.OneDay.Word(): true,
kline.OneMin.Word(): true,
kline.FiveMin.Word(): true,
kline.FifteenMin.Word(): true,
kline.ThirtyMin.Word(): true,
kline.OneHour.Word(): true,
kline.SixHour.Word(): true,
kline.OneDay.Word(): true,
kline.OneWeek.Word(): true,
kline.OneMonth.Word(): true,
},
ResultLimit: 1000,
},
@@ -978,8 +984,25 @@ func (b *BTCMarkets) ValidateCredentials(ctx context.Context, assetType asset.It
// FormatExchangeKlineInterval returns Interval to exchange formatted string
func (b *BTCMarkets) FormatExchangeKlineInterval(in kline.Interval) string {
if in == kline.OneDay {
switch in {
case kline.OneMin:
return "1m"
case kline.FiveMin:
return "5m"
case kline.FifteenMin:
return "15m"
case kline.ThirtyMin:
return "30m"
case kline.OneHour:
return "1h"
case kline.SixHour:
return "6h"
case kline.OneDay:
return "1d"
case kline.OneWeek:
return "1w"
case kline.OneMonth:
return "1mo"
}
return in.Short()
}

View File

@@ -988,26 +988,22 @@ func (b *Base) FormatExchangeKlineInterval(in kline.Interval) string {
return strconv.FormatFloat(in.Duration().Seconds(), 'f', 0, 64)
}
// ValidateKline confirms that the requested pair, asset & interval are supported and/or enabled by the requested exchange
// ValidateKline confirms that the requested pair, asset & interval are
// supported and/or enabled by the requested exchange.
func (b *Base) ValidateKline(pair currency.Pair, a asset.Item, interval kline.Interval) error {
var errorList []string
var err kline.Error
if b.CurrencyPairs.IsAssetEnabled(a) != nil {
err.Asset = a
errorList = append(errorList, "asset not enabled")
errorList = append(errorList, fmt.Sprintf("[%s] asset not enabled", a))
} else if !b.CurrencyPairs.Pairs[a].Enabled.Contains(pair, true) {
err.Pair = pair
errorList = append(errorList, "pair not enabled")
errorList = append(errorList, fmt.Sprintf("[%s] pair not enabled", pair))
}
if !b.klineIntervalEnabled(interval) {
err.Interval = interval
errorList = append(errorList, "interval not supported")
errorList = append(errorList, fmt.Sprintf("[%s] interval not supported", interval))
}
if len(errorList) > 0 {
err.Err = errors.New(strings.Join(errorList, ","))
return &err
return fmt.Errorf("%w: %v", kline.ErrValidatingParams, strings.Join(errorList, ", "))
}
return nil

View File

@@ -37,7 +37,7 @@ const (
var (
h HUOBI
wsSetupRan bool
futuresTestPair = currency.NewPair(currency.BTC, currency.NewCode("NQ"))
futuresTestPair = currency.NewPair(currency.BTC, currency.NewCode("CW")) // represents this week - NQ (next quarter) is erroring out.
)
func TestMain(m *testing.M) {
@@ -138,7 +138,7 @@ func TestFIndexPriceInfo(t *testing.T) {
func TestFContractPriceLimitations(t *testing.T) {
t.Parallel()
_, err := h.FContractPriceLimitations(context.Background(),
"BTC", "next_quarter", currency.EMPTYPAIR)
"BTC", "this_week", currency.EMPTYPAIR)
if err != nil {
t.Error(err)
}
@@ -147,7 +147,7 @@ func TestFContractPriceLimitations(t *testing.T) {
func TestFContractOpenInterest(t *testing.T) {
t.Parallel()
_, err := h.FContractOpenInterest(context.Background(),
"BTC", "next_quarter", currency.EMPTYPAIR)
"BTC", "this_week", currency.EMPTYPAIR)
if err != nil {
t.Error(err)
}
@@ -231,7 +231,7 @@ func TestFQueryTieredAdjustmentFactor(t *testing.T) {
func TestFQueryHisOpenInterest(t *testing.T) {
t.Parallel()
_, err := h.FQueryHisOpenInterest(context.Background(),
"BTC", "next_quarter", "60min", "cont", 3)
"BTC", "this_week", "60min", "cont", 3)
if err != nil {
t.Error(err)
}
@@ -2732,8 +2732,8 @@ func TestFormatFuturesPair(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if r != "BTC_NQ" {
t.Errorf("expected BTC_NQ, got %s", r)
if r != "BTC_CW" {
t.Errorf("expected BTC_CW, got %s", r)
}
availInstruments, err := h.FetchTradablePairs(context.Background(), asset.Futures)
if err != nil {

View File

@@ -222,7 +222,7 @@ func (k *Item) SortCandlesByTimestamp(desc bool) {
})
}
// FormatDates converts all date to UTC time
// FormatDates converts all dates to UTC time
func (k *Item) FormatDates() {
for x := range k.Candles {
k.Candles[x].Time = k.Candles[x].Time.UTC()
@@ -324,13 +324,15 @@ func TotalCandlesPerInterval(start, end time.Time, interval Interval) (out float
return -1
}
var oneYearDurationInNano = float64(OneYear.Duration().Nanoseconds())
// IntervalsPerYear helps determine the number of intervals in a year
// used in CAGR calculation to know the amount of time of an interval in a year
func (i *Interval) IntervalsPerYear() float64 {
if i.Duration() == 0 {
return 0
}
return float64(OneYear.Duration().Nanoseconds()) / float64(i.Duration().Nanoseconds())
return oneYearDurationInNano / float64(i.Duration().Nanoseconds())
}
// ConvertToNewInterval allows the scaling of candles to larger candles
@@ -557,10 +559,7 @@ func (h *IntervalRangeHolder) createDateSummaryRange(start, end time.Time, hasDa
// CreateIntervalTime is a simple helper function to set the time twice
func CreateIntervalTime(tt time.Time) IntervalTime {
return IntervalTime{
Time: tt,
Ticks: tt.Unix(),
}
return IntervalTime{Time: tt, Ticks: tt.Unix()}
}
// Equal allows for easier unix comparison

View File

@@ -262,31 +262,6 @@ func TestDurationToWord(t *testing.T) {
}
}
func TestKlineErrors(t *testing.T) {
t.Parallel()
v := Error{
Interval: OneYear,
Pair: currency.NewPair(currency.BTC, currency.AUD),
Err: errors.New("hello world"),
}
if v.Interval != OneYear {
t.Fatalf("expected OneYear received %v:", v.Interval)
}
if v.Pair != currency.NewPair(currency.BTC, currency.AUD) {
t.Fatalf("expected OneYear received %v:", v.Pair)
}
if v.Error() != "hello world" {
t.Fatal("expected error return received empty value")
}
if v.Unwrap().Error() != "hello world" {
t.Fatal("expected error return received empty value")
}
}
func TestTotalCandlesPerInterval(t *testing.T) {
t.Parallel()
start := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)

View File

@@ -52,6 +52,10 @@ var (
// ErrNotFoundAtTime returned when looking up a candle at a specific time
ErrNotFoundAtTime = errors.New("candle not found at time")
// ErrValidatingParams defines an error when the kline params are either not
// enabled or are invalid.
ErrValidatingParams = errors.New("kline param(s) are invalid")
// SupportedIntervals is a list of all supported intervals
SupportedIntervals = []Interval{
FifteenSecond,
@@ -131,24 +135,6 @@ type ExchangeCapabilitiesEnabled struct {
// Interval type for kline Interval usage
type Interval time.Duration
// Error struct to hold kline interval errors
type Error struct {
Asset asset.Item
Pair currency.Pair
Interval Interval
Err error
}
// Error returns short interval unsupported message
func (e *Error) Error() string {
return e.Err.Error()
}
// Unwrap returns interval unsupported message
func (e *Error) Unwrap() error {
return e.Err
}
// IntervalRangeHolder holds the entire range of intervals
// and the start end dates of everything
type IntervalRangeHolder struct {

View File

@@ -0,0 +1,354 @@
package kline
import (
"errors"
"fmt"
"github.com/thrasher-corp/gct-ta/indicators"
)
var (
errInvalidPeriod = errors.New("invalid period")
errNoData = errors.New("no data")
errInvalidDeviationMultiplier = errors.New("invalid deviation multiplier")
errNilOHLC = errors.New("nil OHLC data")
errInvalidDataSetLengths = errors.New("invalid data set lengths")
errNotEnoughData = errors.New("not enough data to derive signal")
)
// OHLC is a connector for technical analysis usage
type OHLC struct {
Open []float64
High []float64
Low []float64
Close []float64
Volume []float64
}
// GetOHLC returns the entire subset of candles as a friendly type for gct
// technical analysis usage.
func (k *Item) GetOHLC() *OHLC {
ohlc := &OHLC{
Open: make([]float64, len(k.Candles)),
High: make([]float64, len(k.Candles)),
Low: make([]float64, len(k.Candles)),
Close: make([]float64, len(k.Candles)),
Volume: make([]float64, len(k.Candles)),
}
for x := range k.Candles {
ohlc.Open[x] = k.Candles[x].Open
ohlc.High[x] = k.Candles[x].High
ohlc.Low[x] = k.Candles[x].Low
ohlc.Close[x] = k.Candles[x].Close
ohlc.Volume[x] = k.Candles[x].Volume
}
return ohlc
}
// GetAverageTrueRange returns the Average True Range for the given period.
func (k *Item) GetAverageTrueRange(period int64) ([]float64, error) {
return k.GetOHLC().GetAverageTrueRange(period)
}
// GetAverageTrueRange returns the Average True Range for the given period.
func (o *OHLC) GetAverageTrueRange(period int64) ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get average true range %w", errNilOHLC)
}
if period <= 0 {
return nil, fmt.Errorf("get average true range %w", errInvalidPeriod)
}
if len(o.High) == 0 {
return nil, fmt.Errorf("get average true range high %w", errNoData)
}
if len(o.Low) == 0 {
return nil, fmt.Errorf("get average true range low %w", errNoData)
}
if len(o.Close) == 0 {
return nil, fmt.Errorf("get average true range close %w", errNoData)
}
if int(period) > len(o.Close) {
return nil, fmt.Errorf("get average true range close %w exceeds data length, please reduce",
errInvalidPeriod)
}
return indicators.ATR(o.High, o.Low, o.Close, int(period)), nil
}
// GetBollingerBands returns Bollinger Bands for the given period.
func (k *Item) GetBollingerBands(period int64, nbDevUp, nbDevDown float64, m indicators.MaType) (*Bollinger, error) {
return k.GetOHLC().GetBollingerBands(period, nbDevUp, nbDevDown, m)
}
// Bollinger defines a return type for the bollinger bands
type Bollinger struct {
Upper []float64
Middle []float64
Lower []float64
}
// GetBollingerBands returns Bollinger Bands for the given period.
func (o *OHLC) GetBollingerBands(period int64, nbDevUp, nbDevDown float64, m indicators.MaType) (*Bollinger, error) {
if o == nil {
return nil, fmt.Errorf("get bollinger bands %w", errNilOHLC)
}
if period <= 0 {
return nil, fmt.Errorf("get bollinger bands %w", errInvalidPeriod)
}
if nbDevUp <= 0 {
return nil, fmt.Errorf("get bollinger bands %w upper limit", errInvalidDeviationMultiplier)
}
if nbDevDown <= 0 {
return nil, fmt.Errorf("get bollinger bands %w lower limit", errInvalidDeviationMultiplier)
}
if len(o.Close) == 0 {
return nil, fmt.Errorf("get bollinger bands close %w", errNoData)
}
if int(period) > len(o.Close) { // TODO: Investigate the panic when this protection is removed.
return nil, fmt.Errorf("get bollinger bands %w '%v' should not exceed close data length '%v'",
errInvalidPeriod, period, len(o.Close))
}
var bands Bollinger
bands.Upper, bands.Middle, bands.Lower = indicators.BBANDS(o.Close,
int(period),
nbDevUp,
nbDevDown,
m)
return &bands, nil
}
// GetCorrelationCoefficient returns GetCorrelation Coefficient against another
// candle data set for the given period.
func (k *Item) GetCorrelationCoefficient(other *Item, period int64) ([]float64, error) {
return k.GetOHLC().GetCorrelationCoefficient(other.GetOHLC(), period)
}
// GetCorrelationCoefficient returns GetCorrelation Coefficient against another
// candle data set for the given period.
func (o *OHLC) GetCorrelationCoefficient(other *OHLC, period int64) ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get correlation coefficient %w", errNilOHLC)
}
if period <= 0 {
return nil, fmt.Errorf("get correlation coefficient %w", errInvalidPeriod)
}
if period == 1 {
// TODO: Check correlation calculation.
return nil, fmt.Errorf("get correlation coefficient %w using period 1 results in NaN return",
errInvalidPeriod)
}
if other == nil {
return nil, fmt.Errorf("get correlation coefficient %w", errNilOHLC)
}
if len(o.Close) == 0 {
return nil, fmt.Errorf("get correlation coefficient close %w", errNoData)
}
if len(other.Close) == 0 {
return nil, fmt.Errorf("get correlation coefficient comparison close %w", errNoData)
}
if int(period) > len(o.Close) || int(period) > len(other.Close) {
return nil, fmt.Errorf("get correlation coefficient %w exceeds data length, please reduce",
errInvalidPeriod)
}
if len(o.Close) != len(other.Close) {
return nil,
fmt.Errorf("get correlation coefficient comparison close %w between data sets",
errInvalidDataSetLengths)
}
return indicators.CorrelationCoefficient(o.Close, other.Close, int(period)), nil
}
// GetSimpleMovingAverageOnClose returns MA the close prices set for the given
// period.
func (k *Item) GetSimpleMovingAverageOnClose(period int64) ([]float64, error) {
ohlc := k.GetOHLC()
return ohlc.GetSimpleMovingAverage(ohlc.Close, period)
}
// GetSimpleMovingAverage returns MA for the supplied price set for the given
// period.
func (o *OHLC) GetSimpleMovingAverage(option []float64, period int64) ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get simple moving average %w", errNilOHLC)
}
if period <= 0 {
return nil, fmt.Errorf("get simple moving average %w", errInvalidPeriod)
}
if len(option) == 0 {
return nil, fmt.Errorf("get simple moving average %w", errNoData)
}
if int(period) > len(option) {
return nil, fmt.Errorf("get simple moving average %w exceeds data length, please reduce",
errInvalidPeriod)
}
return indicators.SMA(option, int(period)), nil
}
// GetExponentialMovingAverageOnClose returns the EMA on the close price set for
// the given period.
func (k *Item) GetExponentialMovingAverageOnClose(period int64) ([]float64, error) {
ohlc := k.GetOHLC()
return ohlc.GetExponentialMovingAverage(ohlc.Close, period)
}
// GetExponentialMovingAverage returns the EMA on the supplied price set for the
// given period.
func (o *OHLC) GetExponentialMovingAverage(option []float64, period int64) ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get exponential moving average %w", errNilOHLC)
}
if period <= 0 {
return nil, fmt.Errorf("get exponential moving average %w", errInvalidPeriod)
}
if len(option) == 0 {
return nil, fmt.Errorf("get exponential moving average %w", errNoData)
}
if int(period) > len(option) {
return nil, fmt.Errorf("get exponential moving average %w exceeds data length, please reduce",
errInvalidPeriod)
}
return indicators.EMA(option, int(period)), nil
}
// MACD defines MACD values
type MACD struct {
Results []float64
SignalVals []float64
Histogram []float64
}
// GetMovingAverageConvergenceDivergenceOnClose returns the
// MACD (macd, signal period vals, histogram) for the given price
// set and the parameters fast, slow signal time periods.
func (k *Item) GetMovingAverageConvergenceDivergenceOnClose(fast, slow, signal int64) (*MACD, error) {
ohlc := k.GetOHLC()
return ohlc.GetMovingAverageConvergenceDivergence(ohlc.Close, fast, slow, signal)
}
// GetMovingAverageConvergenceDivergence returns the
// MACD (macd, signal period vals, histogram) for the given price
// set and the parameters fast, slow signal time periods.
func (o *OHLC) GetMovingAverageConvergenceDivergence(option []float64, fast, slow, signal int64) (*MACD, error) {
if o == nil {
return nil, fmt.Errorf("get macd %w", errNilOHLC)
}
if fast <= 0 {
return nil, fmt.Errorf("get macd %w fast", errInvalidPeriod)
}
if slow <= 0 {
return nil, fmt.Errorf("get macd %w slow", errInvalidPeriod)
}
if fast >= slow {
return nil, fmt.Errorf("get macd %w fast should not be equal or exceed slow", errInvalidPeriod)
}
if signal <= 0 {
return nil, fmt.Errorf("get macd %w signal", errInvalidPeriod)
}
if len(option) == 0 {
return nil, fmt.Errorf("get macd %w", errNoData)
}
if len(option) < int(slow+signal-2) {
return nil, fmt.Errorf("get macd %w %v data points are less than minimum %v length requirement derived from the slow %v and signal %v period subtract two, increase end date or scale down granularity",
errNotEnoughData,
len(option),
slow+signal-2,
slow,
signal)
}
var macd MACD
macd.Results, macd.SignalVals, macd.Histogram = indicators.MACD(option,
int(fast),
int(slow),
int(signal))
return &macd, nil
}
// GetMoneyFlowIndex returns Money Flow Index for the given period.
func (k *Item) GetMoneyFlowIndex(period int64) ([]float64, error) {
return k.GetOHLC().GetMoneyFlowIndex(period)
}
// GetMoneyFlowIndex returns Money Flow Index for the given period.
func (o *OHLC) GetMoneyFlowIndex(period int64) ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get money flow index %w", errNilOHLC)
}
if period <= 0 {
return nil, fmt.Errorf("get money flow index %w", errInvalidPeriod)
}
highLen := len(o.High)
if highLen == 0 {
return nil, fmt.Errorf("get money flow index %w for high", errNoData)
}
lowLen := len(o.Low)
if lowLen == 0 {
return nil, fmt.Errorf("get money flow index %w for low", errNoData)
}
closeLen := len(o.Close)
if closeLen == 0 {
return nil, fmt.Errorf("get money flow index %w for close", errNoData)
}
volLen := len(o.Volume)
if volLen == 0 {
return nil, fmt.Errorf("get money flow index %w for volume", errNoData)
}
if highLen != closeLen || lowLen != closeLen || volLen != closeLen {
// TODO: Investigate the panic when this protection is removed.
// This is very unstable with incorrect lengths.
return nil, fmt.Errorf("get money flow index %w", errInvalidDataSetLengths)
}
if int(period) >= len(o.Close) {
// TODO: Investigate the panic when this protection is removed.
return nil, fmt.Errorf("get money flow index %w '%v' should not exceed or equal close data length '%v'",
errInvalidPeriod, period, len(o.Close))
}
return indicators.MFI(o.High, o.Low, o.Close, o.Volume, int(period)), nil
}
// GetOnBalanceVolume returns On Balance Volume.
func (k *Item) GetOnBalanceVolume() ([]float64, error) {
return k.GetOHLC().GetOnBalanceVolume()
}
// GetOnBalanceVolume returns On Balance Volume.
func (o *OHLC) GetOnBalanceVolume() ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get on balance volume %w", errNilOHLC)
}
if len(o.Close) == 0 {
return nil, fmt.Errorf("get on balance volume %w for close", errNoData)
}
if len(o.Volume) == 0 {
return nil, fmt.Errorf("get on balance volume %w for volume", errNoData)
}
return indicators.OBV(o.Close, o.Volume), nil
}
// GetRelativeStrengthIndexOnClose returns the relative strength index from the
// given price set and period.
func (k *Item) GetRelativeStrengthIndexOnClose(period int64) ([]float64, error) {
ohlc := k.GetOHLC()
return ohlc.GetRelativeStrengthIndex(ohlc.Close, period)
}
// GetRelativeStrengthIndex returns the relative strength index from the the
// given price set and period.
func (o *OHLC) GetRelativeStrengthIndex(option []float64, period int64) ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get relative strength index %w", errNilOHLC)
}
if period <= 1 {
return nil, fmt.Errorf("get relative strength index %w cannot be equal or below 1", errInvalidPeriod)
}
if len(option) <= 2 {
// TODO: Check why 2 data points causes panic.
return nil, fmt.Errorf("get relative strength index %w, requires atleast 3 data points", errNotEnoughData)
}
if int(period) > len(option) {
return nil, fmt.Errorf("get exponential moving average %w exceeds data length, please reduce",
errInvalidPeriod)
}
return indicators.RSI(option, int(period)), nil
}

View File

@@ -0,0 +1,429 @@
package kline
import (
"errors"
"testing"
)
func TestGetOHLC(t *testing.T) {
t.Parallel()
if (&Item{Candles: []Candle{{Open: 1337}}}).GetOHLC() == nil {
t.Fatal("unexpected value")
}
}
func TestGetAverageTrueRange(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetAverageTrueRange(0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetAverageTrueRange(0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetAverageTrueRange(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.High = append(ohlc.High, 1337)
_, err = ohlc.GetAverageTrueRange(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Low = append(ohlc.Low, 1337)
_, err = ohlc.GetAverageTrueRange(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Close = append(ohlc.Close, 1337)
_, err = ohlc.GetAverageTrueRange(9)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetAverageTrueRange(1)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{High: 1337, Low: 1337, Close: 1337}}}
_, err = wrap.GetAverageTrueRange(1)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetBollingerBands(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetBollingerBands(0, 0, 0, 5)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetBollingerBands(0, 0, 0, 5)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetBollingerBands(9, 0, 0, 5)
if !errors.Is(err, errInvalidDeviationMultiplier) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidDeviationMultiplier)
}
_, err = ohlc.GetBollingerBands(9, 1, 0, 5)
if !errors.Is(err, errInvalidDeviationMultiplier) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidDeviationMultiplier)
}
_, err = ohlc.GetBollingerBands(9, 1, 1, 5)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Close = append(ohlc.Close, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337)
_, err = ohlc.GetBollingerBands(10, 1, 1, 5)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetBollingerBands(9, 1, 1, 5)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}}}
_, err = wrap.GetBollingerBands(9, 1, 1, 5)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetCorrelationCoefficient(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetCorrelationCoefficient(nil, 0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetCorrelationCoefficient(nil, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetCorrelationCoefficient(nil, 1)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetCorrelationCoefficient(nil, 2)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
_, err = ohlc.GetCorrelationCoefficient(&OHLC{}, 9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Close = append(ohlc.Close, 1337, 1337)
_, err = ohlc.GetCorrelationCoefficient(&OHLC{}, 9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
_, err = ohlc.GetCorrelationCoefficient(&OHLC{Close: []float64{1337}}, 2)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
ohlc.Close = append(ohlc.Close, 1337)
_, err = ohlc.GetCorrelationCoefficient(&OHLC{Close: []float64{1337, 1337}}, 2)
if !errors.Is(err, errInvalidDataSetLengths) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidDataSetLengths)
}
_, err = ohlc.GetCorrelationCoefficient(&OHLC{Close: []float64{1337, 1337, 1337}}, 2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{Close: 1337}, {Close: 1337}, {Close: 1337}}}
_, err = wrap.GetCorrelationCoefficient(&Item{Candles: []Candle{{Close: 1337}, {Close: 1337}, {Close: 1337}}}, 2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetSimpleMovingAverage(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetSimpleMovingAverage(nil, 0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetSimpleMovingAverage(nil, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetSimpleMovingAverage(nil, 9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
_, err = ohlc.GetSimpleMovingAverage([]float64{1337}, 9)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetSimpleMovingAverage([]float64{1337, 1337}, 2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{Close: 1337}, {Close: 1337}}}
_, err = wrap.GetSimpleMovingAverageOnClose(2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetExponentialMovingAverage(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetExponentialMovingAverage(nil, 0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetExponentialMovingAverage(nil, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetExponentialMovingAverage(nil, 9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
_, err = ohlc.GetExponentialMovingAverage([]float64{1337}, 9)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetExponentialMovingAverage([]float64{1337, 1337, 1337}, 2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{Close: 1337}, {Close: 1337}, {Close: 1337}}}
_, err = wrap.GetExponentialMovingAverageOnClose(2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetMovingAverageConvergenceDivergence(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetMovingAverageConvergenceDivergence(nil, 0, 0, 0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetMovingAverageConvergenceDivergence(nil, 0, 0, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetMovingAverageConvergenceDivergence(nil, 1, 0, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetMovingAverageConvergenceDivergence(nil, 1, 1, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetMovingAverageConvergenceDivergence(nil, 1, 2, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetMovingAverageConvergenceDivergence(nil, 1, 2, 1)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
_, err = ohlc.GetMovingAverageConvergenceDivergence([]float64{1337}, 1, 2, 2)
if !errors.Is(err, errNotEnoughData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNotEnoughData)
}
_, err = ohlc.GetMovingAverageConvergenceDivergence([]float64{1337, 1337, 1337, 1337, 1337, 1337, 1337, 1337}, 1, 2, 1)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}, {Close: 1337}}}
_, err = wrap.GetMovingAverageConvergenceDivergenceOnClose(1, 2, 1)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetMoneyFlowIndex(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetMoneyFlowIndex(0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetMoneyFlowIndex(0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetMoneyFlowIndex(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.High = append(ohlc.High, 1337, 1337, 1337, 1337, 1337, 1337)
_, err = ohlc.GetMoneyFlowIndex(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Low = append(ohlc.Low, 1337, 1337, 1337, 1337, 1337, 1337)
_, err = ohlc.GetMoneyFlowIndex(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Close = append(ohlc.Close, 1337, 1337, 1337, 1337, 1337, 1337)
_, err = ohlc.GetMoneyFlowIndex(9)
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Volume = append(ohlc.Volume, 1337, 1337, 1337, 1337, 1337)
_, err = ohlc.GetMoneyFlowIndex(5)
if !errors.Is(err, errInvalidDataSetLengths) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidDataSetLengths)
}
ohlc.Volume = append(ohlc.Volume, 1337)
_, err = ohlc.GetMoneyFlowIndex(6)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetMoneyFlowIndex(3)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{
{Close: 1337, High: 1337, Low: 1337, Volume: 1337},
{Close: 1337, High: 1337, Low: 1337, Volume: 1337},
{Close: 1337, High: 1337, Low: 1337, Volume: 1337},
}}
_, err = wrap.GetMoneyFlowIndex(2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetOnBalanceVolume(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetOnBalanceVolume()
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetOnBalanceVolume()
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Close = append(ohlc.Close, 1337, 1337, 1337, 1337, 1337, 1337)
_, err = ohlc.GetOnBalanceVolume()
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Volume = append(ohlc.Volume, 0.00000001)
_, err = ohlc.GetOnBalanceVolume()
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
wrap := Item{Candles: []Candle{{Close: 1337, Volume: 1337}}}
_, err = wrap.GetOnBalanceVolume()
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}
func TestGetRelativeStrengthIndex(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetRelativeStrengthIndex(nil, 0)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetRelativeStrengthIndex(nil, 0)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
_, err = ohlc.GetRelativeStrengthIndex(nil, 9)
if !errors.Is(err, errNotEnoughData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNotEnoughData)
}
_, err = ohlc.GetRelativeStrengthIndex([]float64{1337, 1337, 1337}, 9)
if !errors.Is(err, errInvalidPeriod) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidPeriod)
}
wrap := Item{Candles: []Candle{{Close: 1337}, {Close: 1337}, {Close: 1337}}}
_, err = wrap.GetRelativeStrengthIndexOnClose(2)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
}

View File

@@ -0,0 +1,137 @@
package kline
import (
"errors"
"fmt"
)
var (
errInvalidElement = errors.New("invalid element")
errElementExceedsDataLength = errors.New("element exceeds data length")
errDataLengthMismatch = errors.New("data length mismatch")
)
// GetAveragePrice returns the average price from the open, high, low and close
func (c *Candle) GetAveragePrice() float64 {
return (c.Open + c.High + c.Low + c.Close) / 4
}
// GetAveragePrice returns the average price from the open, high, low and close
func (o *OHLC) GetAveragePrice(element int) (float64, error) {
if o == nil {
return 0, fmt.Errorf("get average price %w", errNilOHLC)
}
if element < 0 {
return 0, fmt.Errorf("get average price %w", errInvalidElement)
}
check := element + 1
if check > len(o.Open) || check > len(o.High) || check > len(o.Low) || check > len(o.Close) {
return 0, fmt.Errorf("get average price %w", errElementExceedsDataLength)
}
return (o.Open[element] + o.High[element] + o.Low[element] + o.Close[element]) / 4, nil
}
// GetTWAP returns the time weighted average price for the specified period.
// NOTE: This assumes the most recent price is at the tail end of the slice.
// Based off: https://blog.quantinsti.com/twap/
// Only returns one item as all other items are just the average price.
func (k *Item) GetTWAP() (float64, error) {
if len(k.Candles) == 0 {
return 0, fmt.Errorf("get twap %w", errNoData)
}
var cumAveragePrice float64
for x := range k.Candles {
cumAveragePrice += k.Candles[x].GetAveragePrice()
}
return cumAveragePrice / float64(len(k.Candles)), nil
}
// GetTWAP returns the time weighted average price for the specified period.
func (o *OHLC) GetTWAP() (float64, error) {
if o == nil {
return 0, fmt.Errorf("get twap %w", errNilOHLC)
}
if len(o.Open) == 0 || len(o.High) == 0 || len(o.Low) == 0 || len(o.Close) == 0 {
return 0, fmt.Errorf("get twap %w", errNoData)
}
if len(o.Open) != len(o.High) || len(o.Open) != len(o.Low) || len(o.Open) != len(o.Close) {
return 0, fmt.Errorf("get twap %w", errDataLengthMismatch)
}
var cumAveragePrice float64
for x := range o.Close {
avgPrice, err := o.GetAveragePrice(x)
if err != nil {
return 0, fmt.Errorf("get twap %w", err)
}
cumAveragePrice += avgPrice
}
return cumAveragePrice / float64(len(o.Close)), nil
}
// GetTypicalPrice returns the typical average price from the high, low and
// close values.
func (c *Candle) GetTypicalPrice() float64 {
return (c.High + c.Low + c.Close) / 3
}
// GetTypicalPrice returns the typical average price from the high, low and
// close values.
func (o *OHLC) GetTypicalPrice(element int) (float64, error) {
if o == nil {
return 0, fmt.Errorf("get typical price %w", errNilOHLC)
}
if element < 0 {
return 0, fmt.Errorf("get typical price %w", errInvalidElement)
}
check := element + 1
if check > len(o.High) || check > len(o.Low) || check > len(o.Close) {
return 0, fmt.Errorf("get typical price %w", errElementExceedsDataLength)
}
return (o.High[element] + o.Low[element] + o.Close[element]) / 3, nil
}
// GetVWAPs returns the Volume Weighted Averages prices which are the cumulative
// average price with respect to the volume.
// NOTE: This assumes candles are sorted by time
// Based off: https://blog.quantinsti.com/vwap-strategy/
func (k *Item) GetVWAPs() ([]float64, error) {
if len(k.Candles) == 0 {
return nil, fmt.Errorf("get vwap %w", errNoData)
}
store := make([]float64, len(k.Candles))
var cumTotal, cumVolume float64
for x := range k.Candles {
cumTotal += k.Candles[x].GetTypicalPrice() * k.Candles[x].Volume
cumVolume += k.Candles[x].Volume
store[x] = cumTotal / cumVolume
}
return store, nil
}
// GetVWAPs returns the Volume Weighted Averages prices which are the cumulative
// average price with respect to the volume.
func (o *OHLC) GetVWAPs() ([]float64, error) {
if o == nil {
return nil, fmt.Errorf("get vwap %w", errNilOHLC)
}
if len(o.Open) == 0 || len(o.High) == 0 || len(o.Low) == 0 || len(o.Close) == 0 {
return nil, fmt.Errorf("get vwap %w", errNoData)
}
if len(o.Open) != len(o.High) || len(o.Open) != len(o.Low) || len(o.Open) != len(o.Close) {
return nil, fmt.Errorf("get vwap %w", errDataLengthMismatch)
}
store := make([]float64, len(o.High))
var cumTotal, cumVolume float64
for x := range o.High {
typPrice, err := o.GetTypicalPrice(x)
if err != nil {
return nil, fmt.Errorf("get vwap %w", err)
}
cumTotal += typPrice * o.Volume[x]
cumVolume += o.Volume[x]
store[x] = cumTotal / cumVolume
}
return store, nil
}

View File

@@ -0,0 +1,313 @@
package kline
import (
"errors"
"testing"
"time"
)
func TestGetAveragePrice(t *testing.T) {
t.Parallel()
c := Candle{}
if c.GetAveragePrice() != 0 {
t.Fatal("unexpected value")
}
c.High = 20
if c.GetAveragePrice() != 5 {
t.Fatal("unexpected value")
}
}
func TestGetAveragePrice_OHLC(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetAveragePrice(-1)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetAveragePrice(-1)
if !errors.Is(err, errInvalidElement) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidElement)
}
_, err = ohlc.GetAveragePrice(0)
if !errors.Is(err, errElementExceedsDataLength) {
t.Fatalf("received: '%v' but expected: '%v'", err, errElementExceedsDataLength)
}
ohlc.High = append(ohlc.High, 20)
ohlc.Open = append(ohlc.Open, 0)
ohlc.Low = append(ohlc.Low, 0)
ohlc.Close = append(ohlc.Close, 0)
avgPrice, err := ohlc.GetAveragePrice(0)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if avgPrice != 5 {
t.Fatal("unexpected value")
}
}
var twapdataset = []Candle{
{Time: time.Date(2020, 6, 17, 0, 0, 0, 0, time.UTC), Close: 351.59, Open: 355.15, High: 355.40, Low: 351.09},
{Time: time.Date(2020, 6, 16, 0, 0, 0, 0, time.UTC), Close: 352.08, Open: 351.46, High: 353.20, Low: 344.72},
{Time: time.Date(2020, 6, 15, 0, 0, 0, 0, time.UTC), Close: 342.99, Open: 333.25, High: 345.68, Low: 332.58},
{Time: time.Date(2020, 6, 12, 0, 0, 0, 0, time.UTC), Close: 338.80, Open: 344.72, High: 347.80, Low: 334.22},
{Time: time.Date(2020, 6, 11, 0, 0, 0, 0, time.UTC), Close: 335.90, Open: 349.31, High: 351.06, Low: 335.48},
{Time: time.Date(2020, 6, 10, 0, 0, 0, 0, time.UTC), Close: 352.84, Open: 347.90, High: 354.77, Low: 346.09},
{Time: time.Date(2020, 6, 9, 0, 0, 0, 0, time.UTC), Close: 343.99, Open: 332.14, High: 345.61, Low: 332.01},
{Time: time.Date(2020, 6, 8, 0, 0, 0, 0, time.UTC), Close: 333.46, Open: 330.25, High: 333.60, Low: 327.32},
{Time: time.Date(2020, 6, 5, 0, 0, 0, 0, time.UTC), Close: 331.50, Open: 323.35, High: 331.75, Low: 323.23},
{Time: time.Date(2020, 6, 4, 0, 0, 0, 0, time.UTC), Close: 322.32, Open: 324.39, High: 325.62, Low: 320.78},
{Time: time.Date(2020, 6, 3, 0, 0, 0, 0, time.UTC), Close: 325.12, Open: 324.66, High: 326.20, Low: 322.30},
{Time: time.Date(2020, 6, 2, 0, 0, 0, 0, time.UTC), Close: 323.34, Open: 320.75, High: 323.44, Low: 318.93},
{Time: time.Date(2020, 6, 1, 0, 0, 0, 0, time.UTC), Close: 321.85, Open: 317.75, High: 322.35, Low: 317.21},
{Time: time.Date(2020, 5, 29, 0, 0, 0, 0, time.UTC), Close: 317.94, Open: 319.25, High: 321.15, Low: 316.47},
{Time: time.Date(2020, 5, 28, 0, 0, 0, 0, time.UTC), Close: 318.25, Open: 316.77, High: 323.44, Low: 315.63},
{Time: time.Date(2020, 5, 27, 0, 0, 0, 0, time.UTC), Close: 318.11, Open: 316.14, High: 318.71, Low: 313.09},
{Time: time.Date(2020, 5, 26, 0, 0, 0, 0, time.UTC), Close: 316.73, Open: 323.50, High: 324.24, Low: 316.50},
{Time: time.Date(2020, 5, 22, 0, 0, 0, 0, time.UTC), Close: 318.89, Open: 315.77, High: 319.23, Low: 315.35},
{Time: time.Date(2020, 5, 21, 0, 0, 0, 0, time.UTC), Close: 316.85, Open: 318.66, High: 320.89, Low: 315.87},
{Time: time.Date(2020, 5, 20, 0, 0, 0, 0, time.UTC), Close: 319.23, Open: 316.68, High: 319.52, Low: 316.20},
{Time: time.Date(2020, 5, 19, 0, 0, 0, 0, time.UTC), Close: 313.14, Open: 315.03, High: 318.52, Low: 313.01},
{Time: time.Date(2020, 5, 18, 0, 0, 0, 0, time.UTC), Close: 314.96, Open: 313.17, High: 316.50, Low: 310.32},
}
func TestGetTWAP_OHLC(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetTWAP()
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetTWAP()
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Open = append(ohlc.Open, 20)
ohlc.High = append(ohlc.High, 20)
ohlc.Low = append(ohlc.Low, 20)
ohlc.Close = append(ohlc.Close, 20, 20)
_, err = ohlc.GetTWAP()
if !errors.Is(err, errDataLengthMismatch) {
t.Fatalf("received: '%v' but expected: '%v'", err, errDataLengthMismatch)
}
i := Item{}
i.Candles = twapdataset
ohlc = i.GetOHLC()
twap, err := ohlc.GetTWAP()
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if twap != 328.147840909091 {
t.Fatal("unexpected value returned from data-set")
}
}
func TestGetTWAP(t *testing.T) {
t.Parallel()
candles := Item{}
if _, err := candles.GetTWAP(); !errors.Is(err, errNoData) {
t.Fatal(err)
}
candles.Candles = twapdataset
twap, err := candles.GetTWAP()
if err != nil {
t.Fatal(err)
}
if twap != 328.147840909091 {
t.Fatal("unexpected value returned from data-set")
}
}
var vwapdataset = []Candle{
{Time: time.Date(2019, 10, 10, 9, 31, 0, 0, time.UTC), Open: 245.2903, High: 245.516, Low: 244.7652, Close: 244.8702, Volume: 103033},
{Time: time.Date(2019, 10, 10, 9, 32, 0, 0, time.UTC), Open: 245.0807, High: 245.0807, Low: 244.55, Close: 244.66, Volume: 21168},
{Time: time.Date(2019, 10, 10, 9, 33, 0, 0, time.UTC), Open: 244.58, High: 245.8, Low: 244.55, Close: 245.6, Volume: 36544},
{Time: time.Date(2019, 10, 10, 9, 34, 0, 0, time.UTC), Open: 245.7097, High: 246.09, Low: 245.57, Close: 245.92, Volume: 30057},
{Time: time.Date(2019, 10, 10, 9, 35, 0, 0, time.UTC), Open: 245.62, High: 245.62, Low: 245.62, Close: 245.62, Volume: 26301},
{Time: time.Date(2019, 10, 10, 9, 36, 0, 0, time.UTC), Open: 245.7126, High: 246.44, Low: 245.7126, Close: 246.188, Volume: 31494},
{Time: time.Date(2019, 10, 10, 9, 37, 0, 0, time.UTC), Open: 246.46, High: 246.46, Low: 246.45, Close: 246.45, Volume: 24271},
{Time: time.Date(2019, 10, 10, 9, 38, 0, 0, time.UTC), Open: 246.755, High: 246.755, Low: 246.25, Close: 246.25, Volume: 37951},
{Time: time.Date(2019, 10, 10, 9, 39, 0, 0, time.UTC), Open: 246.2818, High: 246.655, Low: 246.2818, Close: 246.655, Volume: 15324},
{Time: time.Date(2019, 10, 10, 9, 40, 0, 0, time.UTC), Open: 246.78, High: 246.78, Low: 246.56, Close: 246.762, Volume: 23285},
{Time: time.Date(2019, 10, 10, 9, 41, 0, 0, time.UTC), Open: 246.75, High: 246.75, Low: 246.38, Close: 246.5, Volume: 23365},
{Time: time.Date(2019, 10, 10, 9, 42, 0, 0, time.UTC), Open: 246.17, High: 246.17, Low: 246.17, Close: 246.17, Volume: 16130},
{Time: time.Date(2019, 10, 10, 9, 43, 0, 0, time.UTC), Open: 246.135, High: 246.135, Low: 245.82, Close: 245.82, Volume: 27227},
{Time: time.Date(2019, 10, 10, 9, 44, 0, 0, time.UTC), Open: 245.9335, High: 245.9335, Low: 245.91, Close: 245.91, Volume: 14464},
{Time: time.Date(2019, 10, 10, 9, 45, 0, 0, time.UTC), Open: 246.41, High: 246.41, Low: 246.41, Close: 246.41, Volume: 17156},
{Time: time.Date(2019, 10, 10, 9, 46, 0, 0, time.UTC), Open: 246.44, High: 246.46, Low: 246.1683, Close: 246.1683, Volume: 23938},
{Time: time.Date(2019, 10, 10, 9, 47, 0, 0, time.UTC), Open: 246.2857, High: 246.57, Low: 246.2857, Close: 246.57, Volume: 70833},
{Time: time.Date(2019, 10, 10, 9, 48, 0, 0, time.UTC), Open: 246.6, High: 247.47, Low: 246.6, Close: 247.47, Volume: 59743},
{Time: time.Date(2019, 10, 10, 9, 49, 0, 0, time.UTC), Open: 247.49, High: 247.65, Low: 247.49, Close: 247.65, Volume: 71995},
{Time: time.Date(2019, 10, 10, 9, 50, 0, 0, time.UTC), Open: 247.685, High: 247.801, Low: 247.65, Close: 247.69, Volume: 46038},
{Time: time.Date(2019, 10, 10, 9, 51, 0, 0, time.UTC), Open: 247.95, High: 248.74, Low: 247.95, Close: 248.74, Volume: 103773},
{Time: time.Date(2019, 10, 10, 9, 52, 0, 0, time.UTC), Open: 248.56, High: 248.56, Low: 247.95, Close: 247.95, Volume: 73810},
{Time: time.Date(2019, 10, 10, 9, 53, 0, 0, time.UTC), Open: 247.93, High: 247.93, Low: 247.6614, Close: 247.6614, Volume: 29784},
{Time: time.Date(2019, 10, 10, 9, 54, 0, 0, time.UTC), Open: 247.74, High: 247.76, Low: 247.65, Close: 247.76, Volume: 37138},
{Time: time.Date(2019, 10, 10, 9, 55, 0, 0, time.UTC), Open: 247.93, High: 248.03, Low: 247.93, Close: 248.03, Volume: 53166},
{Time: time.Date(2019, 10, 10, 9, 56, 0, 0, time.UTC), Open: 247.91, High: 248.44, Low: 247.91, Close: 248.44, Volume: 40789},
{Time: time.Date(2019, 10, 10, 9, 57, 0, 0, time.UTC), Open: 248.52, High: 248.52, Low: 248.3154, Close: 248.3154, Volume: 51988},
{Time: time.Date(2019, 10, 10, 9, 58, 0, 0, time.UTC), Open: 248.4409, High: 248.62, Low: 248.4409, Close: 248.62, Volume: 53405},
{Time: time.Date(2019, 10, 10, 9, 59, 0, 0, time.UTC), Open: 248.9199, High: 248.9199, Low: 248.9199, Close: 248.9199, Volume: 85348},
{Time: time.Date(2019, 10, 10, 10, 0, 0, 0, time.UTC), Open: 248.91, High: 249.08, Low: 248.42, Close: 248.72, Volume: 58270},
}
func TestGetVWAPs(t *testing.T) {
t.Parallel()
candles := Item{}
if _, err := candles.GetVWAPs(); !errors.Is(err, errNoData) {
t.Fatal(err)
}
candles.Candles = vwapdataset
vwap, err := candles.GetVWAPs()
if err != nil {
t.Fatal(err)
}
assert(t, vwap[0], 245.05046666666664)
assert(t, vwap[1], 245.00156932123465)
assert(t, vwap[2], 245.07320400593073)
assert(t, vwap[3], 245.19714781780763)
assert(t, vwap[4], 245.248374356565)
assert(t, vwap[5], 245.35797872352975)
assert(t, vwap[6], 245.45540807301208)
assert(t, vwap[7], 245.57298124760712)
assert(t, vwap[8], 245.61797546720302)
assert(t, vwap[9], 245.6901232761351)
assert(t, vwap[10], 245.7435986712912)
assert(t, vwap[11], 245.76128302894574)
assert(t, vwap[12], 245.771994363731)
assert(t, vwap[13], 245.7768929849006)
assert(t, vwap[14], 245.80115004533573)
assert(t, vwap[15], 245.82471633454026)
assert(t, vwap[16], 245.90964645148168)
assert(t, vwap[17], 246.0356579876492)
assert(t, vwap[18], 246.20233204964117)
assert(t, vwap[19], 246.29892677543359)
assert(t, vwap[20], 246.57315726207088)
assert(t, vwap[21], 246.70305234595537)
assert(t, vwap[22], 246.73669536160304)
assert(t, vwap[23], 246.7746731036053)
assert(t, vwap[24], 246.83849361010806)
assert(t, vwap[25], 246.89338504378165)
assert(t, vwap[26], 246.96313273581723)
assert(t, vwap[27], 247.03640100225914)
assert(t, vwap[28], 247.16505290840146)
assert(t, vwap[29], 247.23522648930867)
}
func TestGetVWAPs_OHLC(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetVWAPs()
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetVWAPs()
if !errors.Is(err, errNoData) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNoData)
}
ohlc.Open = append(ohlc.Open, 20)
ohlc.High = append(ohlc.High, 20)
ohlc.Low = append(ohlc.Low, 20)
ohlc.Close = append(ohlc.Close, 20, 20)
_, err = ohlc.GetVWAPs()
if !errors.Is(err, errDataLengthMismatch) {
t.Fatalf("received: '%v' but expected: '%v'", err, errDataLengthMismatch)
}
ohlc = (&Item{Candles: vwapdataset}).GetOHLC()
vwap, err := ohlc.GetVWAPs()
if err != nil {
t.Fatal(err)
}
assert(t, vwap[0], 245.05046666666664)
assert(t, vwap[1], 245.00156932123465)
assert(t, vwap[2], 245.07320400593073)
assert(t, vwap[3], 245.19714781780763)
assert(t, vwap[4], 245.248374356565)
assert(t, vwap[5], 245.35797872352975)
assert(t, vwap[6], 245.45540807301208)
assert(t, vwap[7], 245.57298124760712)
assert(t, vwap[8], 245.61797546720302)
assert(t, vwap[9], 245.6901232761351)
assert(t, vwap[10], 245.7435986712912)
assert(t, vwap[11], 245.76128302894574)
assert(t, vwap[12], 245.771994363731)
assert(t, vwap[13], 245.7768929849006)
assert(t, vwap[14], 245.80115004533573)
assert(t, vwap[15], 245.82471633454026)
assert(t, vwap[16], 245.90964645148168)
assert(t, vwap[17], 246.0356579876492)
assert(t, vwap[18], 246.20233204964117)
assert(t, vwap[19], 246.29892677543359)
assert(t, vwap[20], 246.57315726207088)
assert(t, vwap[21], 246.70305234595537)
assert(t, vwap[22], 246.73669536160304)
assert(t, vwap[23], 246.7746731036053)
assert(t, vwap[24], 246.83849361010806)
assert(t, vwap[25], 246.89338504378165)
assert(t, vwap[26], 246.96313273581723)
assert(t, vwap[27], 247.03640100225914)
assert(t, vwap[28], 247.16505290840146)
assert(t, vwap[29], 247.23522648930867)
}
func TestGetTypicalPrice_OHLC(t *testing.T) {
t.Parallel()
var ohlc *OHLC
_, err := ohlc.GetTypicalPrice(-1)
if !errors.Is(err, errNilOHLC) {
t.Fatalf("received: '%v' but expected: '%v'", err, errNilOHLC)
}
ohlc = &OHLC{}
_, err = ohlc.GetTypicalPrice(-1)
if !errors.Is(err, errInvalidElement) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidElement)
}
_, err = ohlc.GetTypicalPrice(0)
if !errors.Is(err, errElementExceedsDataLength) {
t.Fatalf("received: '%v' but expected: '%v'", err, errElementExceedsDataLength)
}
ohlc.High = append(ohlc.High, 15)
ohlc.Low = append(ohlc.Low, 0)
ohlc.Close = append(ohlc.Close, 0)
avgPrice, err := ohlc.GetTypicalPrice(0)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
if avgPrice != 5 {
t.Fatal("unexpected value")
}
}
func assert(t *testing.T, received, expected float64) {
t.Helper()
if received != expected {
t.Fatalf("received: '%v' but expected: '%v'", received, expected)
}
}

View File

@@ -989,7 +989,7 @@ func TestValidateCandlesRequest(t *testing.T) {
t.Error(err)
}
_, err = z.validateCandlesRequest(currency.EMPTYPAIR, asset.Spot, time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC), time.Date(2020, 1, 1, 1, 1, 1, 3, time.UTC), kline.OneHour)
if err != nil && err.Error() != "pair not enabled" {
if !errors.Is(err, kline.ErrValidatingParams) {
t.Error(err)
}
var p currency.Pair

View File

@@ -11768,6 +11768,267 @@ func (*ShutdownResponse) Descriptor() ([]byte, []int) {
return file_rpc_proto_rawDescGZIP(), []int{179}
}
type GetTechnicalAnalysisRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
AlgorithmType string `protobuf:"bytes,4,opt,name=algorithm_type,json=algorithmType,proto3" json:"algorithm_type,omitempty"`
Interval int64 `protobuf:"varint,5,opt,name=interval,proto3" json:"interval,omitempty"`
Start *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=start,proto3" json:"start,omitempty"`
End *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=end,proto3" json:"end,omitempty"`
Period int64 `protobuf:"varint,8,opt,name=period,proto3" json:"period,omitempty"`
FastPeriod int64 `protobuf:"varint,9,opt,name=fast_period,json=fastPeriod,proto3" json:"fast_period,omitempty"`
SlowPeriod int64 `protobuf:"varint,10,opt,name=slow_period,json=slowPeriod,proto3" json:"slow_period,omitempty"`
StandardDeviationUp float64 `protobuf:"fixed64,11,opt,name=standard_deviation_up,json=standardDeviationUp,proto3" json:"standard_deviation_up,omitempty"`
StandardDeviationDown float64 `protobuf:"fixed64,12,opt,name=standard_deviation_down,json=standardDeviationDown,proto3" json:"standard_deviation_down,omitempty"`
MovingAverageType int64 `protobuf:"varint,13,opt,name=moving_average_type,json=movingAverageType,proto3" json:"moving_average_type,omitempty"`
OtherExchange string `protobuf:"bytes,14,opt,name=other_exchange,json=otherExchange,proto3" json:"other_exchange,omitempty"`
OtherPair *CurrencyPair `protobuf:"bytes,15,opt,name=other_pair,json=otherPair,proto3" json:"other_pair,omitempty"`
OtherAssetType string `protobuf:"bytes,16,opt,name=other_asset_type,json=otherAssetType,proto3" json:"other_asset_type,omitempty"`
}
func (x *GetTechnicalAnalysisRequest) Reset() {
*x = GetTechnicalAnalysisRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_rpc_proto_msgTypes[180]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetTechnicalAnalysisRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetTechnicalAnalysisRequest) ProtoMessage() {}
func (x *GetTechnicalAnalysisRequest) ProtoReflect() protoreflect.Message {
mi := &file_rpc_proto_msgTypes[180]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetTechnicalAnalysisRequest.ProtoReflect.Descriptor instead.
func (*GetTechnicalAnalysisRequest) Descriptor() ([]byte, []int) {
return file_rpc_proto_rawDescGZIP(), []int{180}
}
func (x *GetTechnicalAnalysisRequest) GetExchange() string {
if x != nil {
return x.Exchange
}
return ""
}
func (x *GetTechnicalAnalysisRequest) GetPair() *CurrencyPair {
if x != nil {
return x.Pair
}
return nil
}
func (x *GetTechnicalAnalysisRequest) GetAssetType() string {
if x != nil {
return x.AssetType
}
return ""
}
func (x *GetTechnicalAnalysisRequest) GetAlgorithmType() string {
if x != nil {
return x.AlgorithmType
}
return ""
}
func (x *GetTechnicalAnalysisRequest) GetInterval() int64 {
if x != nil {
return x.Interval
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetStart() *timestamppb.Timestamp {
if x != nil {
return x.Start
}
return nil
}
func (x *GetTechnicalAnalysisRequest) GetEnd() *timestamppb.Timestamp {
if x != nil {
return x.End
}
return nil
}
func (x *GetTechnicalAnalysisRequest) GetPeriod() int64 {
if x != nil {
return x.Period
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetFastPeriod() int64 {
if x != nil {
return x.FastPeriod
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetSlowPeriod() int64 {
if x != nil {
return x.SlowPeriod
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetStandardDeviationUp() float64 {
if x != nil {
return x.StandardDeviationUp
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetStandardDeviationDown() float64 {
if x != nil {
return x.StandardDeviationDown
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetMovingAverageType() int64 {
if x != nil {
return x.MovingAverageType
}
return 0
}
func (x *GetTechnicalAnalysisRequest) GetOtherExchange() string {
if x != nil {
return x.OtherExchange
}
return ""
}
func (x *GetTechnicalAnalysisRequest) GetOtherPair() *CurrencyPair {
if x != nil {
return x.OtherPair
}
return nil
}
func (x *GetTechnicalAnalysisRequest) GetOtherAssetType() string {
if x != nil {
return x.OtherAssetType
}
return ""
}
type ListOfSignals struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Signals []float64 `protobuf:"fixed64,1,rep,packed,name=signals,proto3" json:"signals,omitempty"`
}
func (x *ListOfSignals) Reset() {
*x = ListOfSignals{}
if protoimpl.UnsafeEnabled {
mi := &file_rpc_proto_msgTypes[181]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListOfSignals) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListOfSignals) ProtoMessage() {}
func (x *ListOfSignals) ProtoReflect() protoreflect.Message {
mi := &file_rpc_proto_msgTypes[181]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListOfSignals.ProtoReflect.Descriptor instead.
func (*ListOfSignals) Descriptor() ([]byte, []int) {
return file_rpc_proto_rawDescGZIP(), []int{181}
}
func (x *ListOfSignals) GetSignals() []float64 {
if x != nil {
return x.Signals
}
return nil
}
type GetTechnicalAnalysisResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Signals map[string]*ListOfSignals `protobuf:"bytes,1,rep,name=signals,proto3" json:"signals,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *GetTechnicalAnalysisResponse) Reset() {
*x = GetTechnicalAnalysisResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_rpc_proto_msgTypes[182]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetTechnicalAnalysisResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetTechnicalAnalysisResponse) ProtoMessage() {}
func (x *GetTechnicalAnalysisResponse) ProtoReflect() protoreflect.Message {
mi := &file_rpc_proto_msgTypes[182]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetTechnicalAnalysisResponse.ProtoReflect.Descriptor instead.
func (*GetTechnicalAnalysisResponse) Descriptor() ([]byte, []int) {
return file_rpc_proto_rawDescGZIP(), []int{182}
}
func (x *GetTechnicalAnalysisResponse) GetSignals() map[string]*ListOfSignals {
if x != nil {
return x.Signals
}
return nil
}
var File_rpc_proto protoreflect.FileDescriptor
var file_rpc_proto_rawDesc = []byte{
@@ -13396,7 +13657,64 @@ var file_rpc_proto_rawDesc = []byte{
0x53, 0x70, 0x6f, 0x74, 0x4d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x68,
0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x12, 0x0a,
0x10, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x32, 0xec, 0x59, 0x0a, 0x15, 0x47, 0x6f, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x54, 0x72,
0x65, 0x22, 0xa1, 0x05, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63,
0x61, 0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a,
0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63,
0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69,
0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74,
0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73,
0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69,
0x74, 0x68, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a,
0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x74, 0x61,
0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x03, 0x65,
0x6e, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x65, 0x72,
0x69, 0x6f, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f,
0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64,
0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x61, 0x73, 0x74, 0x50, 0x65, 0x72, 0x69,
0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f,
0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x6c, 0x6f, 0x77, 0x50, 0x65, 0x72,
0x69, 0x6f, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f,
0x64, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x70, 0x18, 0x0b, 0x20, 0x01,
0x28, 0x01, 0x52, 0x13, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x76, 0x69,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x74, 0x61, 0x6e, 0x64,
0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x6f,
0x77, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x15, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61,
0x72, 0x64, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x6f, 0x77, 0x6e, 0x12,
0x2e, 0x0a, 0x13, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67,
0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6d, 0x6f,
0x76, 0x69, 0x6e, 0x67, 0x41, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
0x25, 0x0a, 0x0e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x45, 0x78,
0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f,
0x70, 0x61, 0x69, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74,
0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72,
0x52, 0x09, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x6f,
0x74, 0x68, 0x65, 0x72, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x41, 0x73, 0x73, 0x65,
0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x66, 0x53,
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x01, 0x52, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73,
0x22, 0xbe, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61,
0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x4b, 0x0a, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54,
0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x1a, 0x51,
0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x15, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x66, 0x53,
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x32, 0xf2, 0x5a, 0x0a, 0x15, 0x47, 0x6f, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x54, 0x72,
0x61, 0x64, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x07, 0x47,
0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
@@ -14115,10 +14433,18 @@ var file_rpc_proto_rawDesc = []byte{
0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f,
0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e,
0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74,
0x68, 0x72, 0x61, 0x73, 0x68, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x67, 0x6f, 0x63,
0x72, 0x79, 0x70, 0x74, 0x6f, 0x74, 0x72, 0x61, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x63, 0x74, 0x72,
0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x12, 0x83, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61,
0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x12, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72,
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x41,
0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24,
0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x63, 0x68, 0x6e,
0x69, 0x63, 0x61, 0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76,
0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x61, 0x6e,
0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x68, 0x72, 0x61, 0x73, 0x68, 0x65, 0x72, 0x2d, 0x63, 0x6f,
0x72, 0x70, 0x2f, 0x67, 0x6f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x74, 0x72, 0x61, 0x64, 0x65,
0x72, 0x2f, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -14133,7 +14459,7 @@ func file_rpc_proto_rawDescGZIP() []byte {
return file_rpc_proto_rawDescData
}
var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 193)
var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 197)
var file_rpc_proto_goTypes = []interface{}{
(*GetInfoRequest)(nil), // 0: gctrpc.GetInfoRequest
(*GetInfoResponse)(nil), // 1: gctrpc.GetInfoResponse
@@ -14315,29 +14641,33 @@ var file_rpc_proto_goTypes = []interface{}{
(*CollateralUsedBreakdown)(nil), // 177: gctrpc.CollateralUsedBreakdown
(*ShutdownRequest)(nil), // 178: gctrpc.ShutdownRequest
(*ShutdownResponse)(nil), // 179: gctrpc.ShutdownResponse
nil, // 180: gctrpc.GetInfoResponse.SubsystemStatusEntry
nil, // 181: gctrpc.GetInfoResponse.RpcEndpointsEntry
nil, // 182: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry
nil, // 183: gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry
nil, // 184: gctrpc.GetRPCEndpointsResponse.EndpointsEntry
nil, // 185: gctrpc.GetExchangeOTPsResponse.OtpCodesEntry
nil, // 186: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry
nil, // 187: gctrpc.OnlineCoins.CoinsEntry
nil, // 188: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry
nil, // 189: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry
nil, // 190: gctrpc.Orders.OrderStatusEntry
nil, // 191: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry
nil, // 192: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry
(*timestamppb.Timestamp)(nil), // 193: google.protobuf.Timestamp
(*GetTechnicalAnalysisRequest)(nil), // 180: gctrpc.GetTechnicalAnalysisRequest
(*ListOfSignals)(nil), // 181: gctrpc.ListOfSignals
(*GetTechnicalAnalysisResponse)(nil), // 182: gctrpc.GetTechnicalAnalysisResponse
nil, // 183: gctrpc.GetInfoResponse.SubsystemStatusEntry
nil, // 184: gctrpc.GetInfoResponse.RpcEndpointsEntry
nil, // 185: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry
nil, // 186: gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry
nil, // 187: gctrpc.GetRPCEndpointsResponse.EndpointsEntry
nil, // 188: gctrpc.GetExchangeOTPsResponse.OtpCodesEntry
nil, // 189: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry
nil, // 190: gctrpc.OnlineCoins.CoinsEntry
nil, // 191: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry
nil, // 192: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry
nil, // 193: gctrpc.Orders.OrderStatusEntry
nil, // 194: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry
nil, // 195: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry
nil, // 196: gctrpc.GetTechnicalAnalysisResponse.SignalsEntry
(*timestamppb.Timestamp)(nil), // 197: google.protobuf.Timestamp
}
var file_rpc_proto_depIdxs = []int32{
180, // 0: gctrpc.GetInfoResponse.subsystem_status:type_name -> gctrpc.GetInfoResponse.SubsystemStatusEntry
181, // 1: gctrpc.GetInfoResponse.rpc_endpoints:type_name -> gctrpc.GetInfoResponse.RpcEndpointsEntry
182, // 2: gctrpc.GetCommunicationRelayersResponse.communication_relayers:type_name -> gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry
183, // 3: gctrpc.GetSusbsytemsResponse.subsystems_status:type_name -> gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry
184, // 4: gctrpc.GetRPCEndpointsResponse.endpoints:type_name -> gctrpc.GetRPCEndpointsResponse.EndpointsEntry
185, // 5: gctrpc.GetExchangeOTPsResponse.otp_codes:type_name -> gctrpc.GetExchangeOTPsResponse.OtpCodesEntry
186, // 6: gctrpc.GetExchangeInfoResponse.supported_assets:type_name -> gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry
183, // 0: gctrpc.GetInfoResponse.subsystem_status:type_name -> gctrpc.GetInfoResponse.SubsystemStatusEntry
184, // 1: gctrpc.GetInfoResponse.rpc_endpoints:type_name -> gctrpc.GetInfoResponse.RpcEndpointsEntry
185, // 2: gctrpc.GetCommunicationRelayersResponse.communication_relayers:type_name -> gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry
186, // 3: gctrpc.GetSusbsytemsResponse.subsystems_status:type_name -> gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry
187, // 4: gctrpc.GetRPCEndpointsResponse.endpoints:type_name -> gctrpc.GetRPCEndpointsResponse.EndpointsEntry
188, // 5: gctrpc.GetExchangeOTPsResponse.otp_codes:type_name -> gctrpc.GetExchangeOTPsResponse.OtpCodesEntry
189, // 6: gctrpc.GetExchangeInfoResponse.supported_assets:type_name -> gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry
21, // 7: gctrpc.GetTickerRequest.pair:type_name -> gctrpc.CurrencyPair
21, // 8: gctrpc.TickerResponse.pair:type_name -> gctrpc.CurrencyPair
22, // 9: gctrpc.Tickers.tickers:type_name -> gctrpc.TickerResponse
@@ -14352,12 +14682,12 @@ var file_rpc_proto_depIdxs = []int32{
33, // 18: gctrpc.GetAccountInfoResponse.accounts:type_name -> gctrpc.Account
38, // 19: gctrpc.GetPortfolioResponse.portfolio:type_name -> gctrpc.PortfolioAddress
43, // 20: gctrpc.OfflineCoins.addresses:type_name -> gctrpc.OfflineCoinSummary
187, // 21: gctrpc.OnlineCoins.coins:type_name -> gctrpc.OnlineCoins.CoinsEntry
190, // 21: gctrpc.OnlineCoins.coins:type_name -> gctrpc.OnlineCoins.CoinsEntry
42, // 22: gctrpc.GetPortfolioSummaryResponse.coin_totals:type_name -> gctrpc.Coin
42, // 23: gctrpc.GetPortfolioSummaryResponse.coins_offline:type_name -> gctrpc.Coin
188, // 24: gctrpc.GetPortfolioSummaryResponse.coins_offline_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry
191, // 24: gctrpc.GetPortfolioSummaryResponse.coins_offline_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry
42, // 25: gctrpc.GetPortfolioSummaryResponse.coins_online:type_name -> gctrpc.Coin
189, // 26: gctrpc.GetPortfolioSummaryResponse.coins_online_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry
192, // 26: gctrpc.GetPortfolioSummaryResponse.coins_online_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry
51, // 27: gctrpc.GetForexProvidersResponse.forex_providers:type_name -> gctrpc.ForexProvider
54, // 28: gctrpc.GetForexRatesResponse.forex_rates:type_name -> gctrpc.ForexRatesConversion
57, // 29: gctrpc.OrderDetails.trades:type_name -> gctrpc.TradeHistory
@@ -14371,7 +14701,7 @@ var file_rpc_proto_depIdxs = []int32{
21, // 37: gctrpc.WhaleBombRequest.pair:type_name -> gctrpc.CurrencyPair
21, // 38: gctrpc.CancelOrderRequest.pair:type_name -> gctrpc.CurrencyPair
21, // 39: gctrpc.CancelBatchOrdersRequest.pair:type_name -> gctrpc.CurrencyPair
190, // 40: gctrpc.Orders.order_status:type_name -> gctrpc.Orders.OrderStatusEntry
193, // 40: gctrpc.Orders.order_status:type_name -> gctrpc.Orders.OrderStatusEntry
69, // 41: gctrpc.CancelBatchOrdersResponse.orders:type_name -> gctrpc.Orders
69, // 42: gctrpc.CancelAllOrdersResponse.orders:type_name -> gctrpc.Orders
74, // 43: gctrpc.GetEventsResponse.condition_params:type_name -> gctrpc.ConditionParams
@@ -14379,16 +14709,16 @@ var file_rpc_proto_depIdxs = []int32{
74, // 45: gctrpc.AddEventRequest.condition_params:type_name -> gctrpc.ConditionParams
21, // 46: gctrpc.AddEventRequest.pair:type_name -> gctrpc.CurrencyPair
80, // 47: gctrpc.DepositAddresses.addresses:type_name -> gctrpc.DepositAddress
191, // 48: gctrpc.GetCryptocurrencyDepositAddressesResponse.addresses:type_name -> gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry
194, // 48: gctrpc.GetCryptocurrencyDepositAddressesResponse.addresses:type_name -> gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry
95, // 49: gctrpc.WithdrawalEventByIDResponse.event:type_name -> gctrpc.WithdrawalEventResponse
95, // 50: gctrpc.WithdrawalEventsByExchangeResponse.event:type_name -> gctrpc.WithdrawalEventResponse
96, // 51: gctrpc.WithdrawalEventResponse.exchange:type_name -> gctrpc.WithdrawlExchangeEvent
97, // 52: gctrpc.WithdrawalEventResponse.request:type_name -> gctrpc.WithdrawalRequestEvent
193, // 53: gctrpc.WithdrawalEventResponse.created_at:type_name -> google.protobuf.Timestamp
193, // 54: gctrpc.WithdrawalEventResponse.updated_at:type_name -> google.protobuf.Timestamp
197, // 53: gctrpc.WithdrawalEventResponse.created_at:type_name -> google.protobuf.Timestamp
197, // 54: gctrpc.WithdrawalEventResponse.updated_at:type_name -> google.protobuf.Timestamp
98, // 55: gctrpc.WithdrawalRequestEvent.fiat:type_name -> gctrpc.FiatWithdrawalEvent
99, // 56: gctrpc.WithdrawalRequestEvent.crypto:type_name -> gctrpc.CryptoWithdrawalEvent
192, // 57: gctrpc.GetExchangePairsResponse.supported_assets:type_name -> gctrpc.GetExchangePairsResponse.SupportedAssetsEntry
195, // 57: gctrpc.GetExchangePairsResponse.supported_assets:type_name -> gctrpc.GetExchangePairsResponse.SupportedAssetsEntry
21, // 58: gctrpc.SetExchangePairRequest.pairs:type_name -> gctrpc.CurrencyPair
21, // 59: gctrpc.GetOrderbookStreamRequest.pair:type_name -> gctrpc.CurrencyPair
21, // 60: gctrpc.GetTickerStreamRequest.pair:type_name -> gctrpc.CurrencyPair
@@ -14425,214 +14755,222 @@ var file_rpc_proto_depIdxs = []int32{
175, // 91: gctrpc.GetCollateralResponse.currency_breakdown:type_name -> gctrpc.CollateralForCurrency
176, // 92: gctrpc.GetCollateralResponse.position_breakdown:type_name -> gctrpc.CollateralByPosition
177, // 93: gctrpc.CollateralForCurrency.used_breakdown:type_name -> gctrpc.CollateralUsedBreakdown
9, // 94: gctrpc.GetInfoResponse.RpcEndpointsEntry.value:type_name -> gctrpc.RPCEndpoint
3, // 95: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry.value:type_name -> gctrpc.CommunicationRelayer
9, // 96: gctrpc.GetRPCEndpointsResponse.EndpointsEntry.value:type_name -> gctrpc.RPCEndpoint
18, // 97: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported
44, // 98: gctrpc.OnlineCoins.CoinsEntry.value:type_name -> gctrpc.OnlineCoinSummary
45, // 99: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry.value:type_name -> gctrpc.OfflineCoins
46, // 100: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry.value:type_name -> gctrpc.OnlineCoins
81, // 101: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry.value:type_name -> gctrpc.DepositAddresses
18, // 102: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported
0, // 103: gctrpc.GoCryptoTraderService.GetInfo:input_type -> gctrpc.GetInfoRequest
6, // 104: gctrpc.GoCryptoTraderService.GetSubsystems:input_type -> gctrpc.GetSubsystemsRequest
5, // 105: gctrpc.GoCryptoTraderService.EnableSubsystem:input_type -> gctrpc.GenericSubsystemRequest
5, // 106: gctrpc.GoCryptoTraderService.DisableSubsystem:input_type -> gctrpc.GenericSubsystemRequest
8, // 107: gctrpc.GoCryptoTraderService.GetRPCEndpoints:input_type -> gctrpc.GetRPCEndpointsRequest
2, // 108: gctrpc.GoCryptoTraderService.GetCommunicationRelayers:input_type -> gctrpc.GetCommunicationRelayersRequest
12, // 109: gctrpc.GoCryptoTraderService.GetExchanges:input_type -> gctrpc.GetExchangesRequest
11, // 110: gctrpc.GoCryptoTraderService.DisableExchange:input_type -> gctrpc.GenericExchangeNameRequest
11, // 111: gctrpc.GoCryptoTraderService.GetExchangeInfo:input_type -> gctrpc.GenericExchangeNameRequest
11, // 112: gctrpc.GoCryptoTraderService.GetExchangeOTPCode:input_type -> gctrpc.GenericExchangeNameRequest
15, // 113: gctrpc.GoCryptoTraderService.GetExchangeOTPCodes:input_type -> gctrpc.GetExchangeOTPsRequest
11, // 114: gctrpc.GoCryptoTraderService.EnableExchange:input_type -> gctrpc.GenericExchangeNameRequest
20, // 115: gctrpc.GoCryptoTraderService.GetTicker:input_type -> gctrpc.GetTickerRequest
23, // 116: gctrpc.GoCryptoTraderService.GetTickers:input_type -> gctrpc.GetTickersRequest
26, // 117: gctrpc.GoCryptoTraderService.GetOrderbook:input_type -> gctrpc.GetOrderbookRequest
29, // 118: gctrpc.GoCryptoTraderService.GetOrderbooks:input_type -> gctrpc.GetOrderbooksRequest
32, // 119: gctrpc.GoCryptoTraderService.GetAccountInfo:input_type -> gctrpc.GetAccountInfoRequest
32, // 120: gctrpc.GoCryptoTraderService.UpdateAccountInfo:input_type -> gctrpc.GetAccountInfoRequest
32, // 121: gctrpc.GoCryptoTraderService.GetAccountInfoStream:input_type -> gctrpc.GetAccountInfoRequest
36, // 122: gctrpc.GoCryptoTraderService.GetConfig:input_type -> gctrpc.GetConfigRequest
39, // 123: gctrpc.GoCryptoTraderService.GetPortfolio:input_type -> gctrpc.GetPortfolioRequest
41, // 124: gctrpc.GoCryptoTraderService.GetPortfolioSummary:input_type -> gctrpc.GetPortfolioSummaryRequest
48, // 125: gctrpc.GoCryptoTraderService.AddPortfolioAddress:input_type -> gctrpc.AddPortfolioAddressRequest
49, // 126: gctrpc.GoCryptoTraderService.RemovePortfolioAddress:input_type -> gctrpc.RemovePortfolioAddressRequest
50, // 127: gctrpc.GoCryptoTraderService.GetForexProviders:input_type -> gctrpc.GetForexProvidersRequest
53, // 128: gctrpc.GoCryptoTraderService.GetForexRates:input_type -> gctrpc.GetForexRatesRequest
58, // 129: gctrpc.GoCryptoTraderService.GetOrders:input_type -> gctrpc.GetOrdersRequest
60, // 130: gctrpc.GoCryptoTraderService.GetOrder:input_type -> gctrpc.GetOrderRequest
61, // 131: gctrpc.GoCryptoTraderService.SubmitOrder:input_type -> gctrpc.SubmitOrderRequest
64, // 132: gctrpc.GoCryptoTraderService.SimulateOrder:input_type -> gctrpc.SimulateOrderRequest
66, // 133: gctrpc.GoCryptoTraderService.WhaleBomb:input_type -> gctrpc.WhaleBombRequest
67, // 134: gctrpc.GoCryptoTraderService.CancelOrder:input_type -> gctrpc.CancelOrderRequest
68, // 135: gctrpc.GoCryptoTraderService.CancelBatchOrders:input_type -> gctrpc.CancelBatchOrdersRequest
71, // 136: gctrpc.GoCryptoTraderService.CancelAllOrders:input_type -> gctrpc.CancelAllOrdersRequest
73, // 137: gctrpc.GoCryptoTraderService.GetEvents:input_type -> gctrpc.GetEventsRequest
76, // 138: gctrpc.GoCryptoTraderService.AddEvent:input_type -> gctrpc.AddEventRequest
78, // 139: gctrpc.GoCryptoTraderService.RemoveEvent:input_type -> gctrpc.RemoveEventRequest
79, // 140: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddresses:input_type -> gctrpc.GetCryptocurrencyDepositAddressesRequest
83, // 141: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddress:input_type -> gctrpc.GetCryptocurrencyDepositAddressRequest
85, // 142: gctrpc.GoCryptoTraderService.GetAvailableTransferChains:input_type -> gctrpc.GetAvailableTransferChainsRequest
87, // 143: gctrpc.GoCryptoTraderService.WithdrawFiatFunds:input_type -> gctrpc.WithdrawFiatRequest
88, // 144: gctrpc.GoCryptoTraderService.WithdrawCryptocurrencyFunds:input_type -> gctrpc.WithdrawCryptoRequest
90, // 145: gctrpc.GoCryptoTraderService.WithdrawalEventByID:input_type -> gctrpc.WithdrawalEventByIDRequest
92, // 146: gctrpc.GoCryptoTraderService.WithdrawalEventsByExchange:input_type -> gctrpc.WithdrawalEventsByExchangeRequest
93, // 147: gctrpc.GoCryptoTraderService.WithdrawalEventsByDate:input_type -> gctrpc.WithdrawalEventsByDateRequest
100, // 148: gctrpc.GoCryptoTraderService.GetLoggerDetails:input_type -> gctrpc.GetLoggerDetailsRequest
102, // 149: gctrpc.GoCryptoTraderService.SetLoggerDetails:input_type -> gctrpc.SetLoggerDetailsRequest
103, // 150: gctrpc.GoCryptoTraderService.GetExchangePairs:input_type -> gctrpc.GetExchangePairsRequest
105, // 151: gctrpc.GoCryptoTraderService.SetExchangePair:input_type -> gctrpc.SetExchangePairRequest
106, // 152: gctrpc.GoCryptoTraderService.GetOrderbookStream:input_type -> gctrpc.GetOrderbookStreamRequest
107, // 153: gctrpc.GoCryptoTraderService.GetExchangeOrderbookStream:input_type -> gctrpc.GetExchangeOrderbookStreamRequest
108, // 154: gctrpc.GoCryptoTraderService.GetTickerStream:input_type -> gctrpc.GetTickerStreamRequest
109, // 155: gctrpc.GoCryptoTraderService.GetExchangeTickerStream:input_type -> gctrpc.GetExchangeTickerStreamRequest
110, // 156: gctrpc.GoCryptoTraderService.GetAuditEvent:input_type -> gctrpc.GetAuditEventRequest
121, // 157: gctrpc.GoCryptoTraderService.GCTScriptExecute:input_type -> gctrpc.GCTScriptExecuteRequest
126, // 158: gctrpc.GoCryptoTraderService.GCTScriptUpload:input_type -> gctrpc.GCTScriptUploadRequest
127, // 159: gctrpc.GoCryptoTraderService.GCTScriptReadScript:input_type -> gctrpc.GCTScriptReadScriptRequest
124, // 160: gctrpc.GoCryptoTraderService.GCTScriptStatus:input_type -> gctrpc.GCTScriptStatusRequest
128, // 161: gctrpc.GoCryptoTraderService.GCTScriptQuery:input_type -> gctrpc.GCTScriptQueryRequest
122, // 162: gctrpc.GoCryptoTraderService.GCTScriptStop:input_type -> gctrpc.GCTScriptStopRequest
123, // 163: gctrpc.GoCryptoTraderService.GCTScriptStopAll:input_type -> gctrpc.GCTScriptStopAllRequest
125, // 164: gctrpc.GoCryptoTraderService.GCTScriptListAll:input_type -> gctrpc.GCTScriptListAllRequest
129, // 165: gctrpc.GoCryptoTraderService.GCTScriptAutoLoadToggle:input_type -> gctrpc.GCTScriptAutoLoadRequest
116, // 166: gctrpc.GoCryptoTraderService.GetHistoricCandles:input_type -> gctrpc.GetHistoricCandlesRequest
133, // 167: gctrpc.GoCryptoTraderService.SetExchangeAsset:input_type -> gctrpc.SetExchangeAssetRequest
134, // 168: gctrpc.GoCryptoTraderService.SetAllExchangePairs:input_type -> gctrpc.SetExchangeAllPairsRequest
135, // 169: gctrpc.GoCryptoTraderService.UpdateExchangeSupportedPairs:input_type -> gctrpc.UpdateExchangeSupportedPairsRequest
136, // 170: gctrpc.GoCryptoTraderService.GetExchangeAssets:input_type -> gctrpc.GetExchangeAssetsRequest
138, // 171: gctrpc.GoCryptoTraderService.WebsocketGetInfo:input_type -> gctrpc.WebsocketGetInfoRequest
140, // 172: gctrpc.GoCryptoTraderService.WebsocketSetEnabled:input_type -> gctrpc.WebsocketSetEnabledRequest
141, // 173: gctrpc.GoCryptoTraderService.WebsocketGetSubscriptions:input_type -> gctrpc.WebsocketGetSubscriptionsRequest
144, // 174: gctrpc.GoCryptoTraderService.WebsocketSetProxy:input_type -> gctrpc.WebsocketSetProxyRequest
145, // 175: gctrpc.GoCryptoTraderService.WebsocketSetURL:input_type -> gctrpc.WebsocketSetURLRequest
112, // 176: gctrpc.GoCryptoTraderService.GetRecentTrades:input_type -> gctrpc.GetSavedTradesRequest
112, // 177: gctrpc.GoCryptoTraderService.GetHistoricTrades:input_type -> gctrpc.GetSavedTradesRequest
112, // 178: gctrpc.GoCryptoTraderService.GetSavedTrades:input_type -> gctrpc.GetSavedTradesRequest
115, // 179: gctrpc.GoCryptoTraderService.ConvertTradesToCandles:input_type -> gctrpc.ConvertTradesToCandlesRequest
146, // 180: gctrpc.GoCryptoTraderService.FindMissingSavedCandleIntervals:input_type -> gctrpc.FindMissingCandlePeriodsRequest
147, // 181: gctrpc.GoCryptoTraderService.FindMissingSavedTradeIntervals:input_type -> gctrpc.FindMissingTradePeriodsRequest
149, // 182: gctrpc.GoCryptoTraderService.SetExchangeTradeProcessing:input_type -> gctrpc.SetExchangeTradeProcessingRequest
150, // 183: gctrpc.GoCryptoTraderService.UpsertDataHistoryJob:input_type -> gctrpc.UpsertDataHistoryJobRequest
154, // 184: gctrpc.GoCryptoTraderService.GetDataHistoryJobDetails:input_type -> gctrpc.GetDataHistoryJobDetailsRequest
0, // 185: gctrpc.GoCryptoTraderService.GetActiveDataHistoryJobs:input_type -> gctrpc.GetInfoRequest
158, // 186: gctrpc.GoCryptoTraderService.GetDataHistoryJobsBetween:input_type -> gctrpc.GetDataHistoryJobsBetweenRequest
154, // 187: gctrpc.GoCryptoTraderService.GetDataHistoryJobSummary:input_type -> gctrpc.GetDataHistoryJobDetailsRequest
159, // 188: gctrpc.GoCryptoTraderService.SetDataHistoryJobStatus:input_type -> gctrpc.SetDataHistoryJobStatusRequest
160, // 189: gctrpc.GoCryptoTraderService.UpdateDataHistoryJobPrerequisite:input_type -> gctrpc.UpdateDataHistoryJobPrerequisiteRequest
58, // 190: gctrpc.GoCryptoTraderService.GetManagedOrders:input_type -> gctrpc.GetOrdersRequest
161, // 191: gctrpc.GoCryptoTraderService.ModifyOrder:input_type -> gctrpc.ModifyOrderRequest
163, // 192: gctrpc.GoCryptoTraderService.CurrencyStateGetAll:input_type -> gctrpc.CurrencyStateGetAllRequest
164, // 193: gctrpc.GoCryptoTraderService.CurrencyStateTrading:input_type -> gctrpc.CurrencyStateTradingRequest
167, // 194: gctrpc.GoCryptoTraderService.CurrencyStateDeposit:input_type -> gctrpc.CurrencyStateDepositRequest
166, // 195: gctrpc.GoCryptoTraderService.CurrencyStateWithdraw:input_type -> gctrpc.CurrencyStateWithdrawRequest
165, // 196: gctrpc.GoCryptoTraderService.CurrencyStateTradingPair:input_type -> gctrpc.CurrencyStateTradingPairRequest
170, // 197: gctrpc.GoCryptoTraderService.GetFuturesPositions:input_type -> gctrpc.GetFuturesPositionsRequest
173, // 198: gctrpc.GoCryptoTraderService.GetCollateral:input_type -> gctrpc.GetCollateralRequest
178, // 199: gctrpc.GoCryptoTraderService.Shutdown:input_type -> gctrpc.ShutdownRequest
1, // 200: gctrpc.GoCryptoTraderService.GetInfo:output_type -> gctrpc.GetInfoResponse
7, // 201: gctrpc.GoCryptoTraderService.GetSubsystems:output_type -> gctrpc.GetSusbsytemsResponse
132, // 202: gctrpc.GoCryptoTraderService.EnableSubsystem:output_type -> gctrpc.GenericResponse
132, // 203: gctrpc.GoCryptoTraderService.DisableSubsystem:output_type -> gctrpc.GenericResponse
10, // 204: gctrpc.GoCryptoTraderService.GetRPCEndpoints:output_type -> gctrpc.GetRPCEndpointsResponse
4, // 205: gctrpc.GoCryptoTraderService.GetCommunicationRelayers:output_type -> gctrpc.GetCommunicationRelayersResponse
13, // 206: gctrpc.GoCryptoTraderService.GetExchanges:output_type -> gctrpc.GetExchangesResponse
132, // 207: gctrpc.GoCryptoTraderService.DisableExchange:output_type -> gctrpc.GenericResponse
19, // 208: gctrpc.GoCryptoTraderService.GetExchangeInfo:output_type -> gctrpc.GetExchangeInfoResponse
14, // 209: gctrpc.GoCryptoTraderService.GetExchangeOTPCode:output_type -> gctrpc.GetExchangeOTPResponse
16, // 210: gctrpc.GoCryptoTraderService.GetExchangeOTPCodes:output_type -> gctrpc.GetExchangeOTPsResponse
132, // 211: gctrpc.GoCryptoTraderService.EnableExchange:output_type -> gctrpc.GenericResponse
22, // 212: gctrpc.GoCryptoTraderService.GetTicker:output_type -> gctrpc.TickerResponse
25, // 213: gctrpc.GoCryptoTraderService.GetTickers:output_type -> gctrpc.GetTickersResponse
28, // 214: gctrpc.GoCryptoTraderService.GetOrderbook:output_type -> gctrpc.OrderbookResponse
31, // 215: gctrpc.GoCryptoTraderService.GetOrderbooks:output_type -> gctrpc.GetOrderbooksResponse
35, // 216: gctrpc.GoCryptoTraderService.GetAccountInfo:output_type -> gctrpc.GetAccountInfoResponse
35, // 217: gctrpc.GoCryptoTraderService.UpdateAccountInfo:output_type -> gctrpc.GetAccountInfoResponse
35, // 218: gctrpc.GoCryptoTraderService.GetAccountInfoStream:output_type -> gctrpc.GetAccountInfoResponse
37, // 219: gctrpc.GoCryptoTraderService.GetConfig:output_type -> gctrpc.GetConfigResponse
40, // 220: gctrpc.GoCryptoTraderService.GetPortfolio:output_type -> gctrpc.GetPortfolioResponse
47, // 221: gctrpc.GoCryptoTraderService.GetPortfolioSummary:output_type -> gctrpc.GetPortfolioSummaryResponse
132, // 222: gctrpc.GoCryptoTraderService.AddPortfolioAddress:output_type -> gctrpc.GenericResponse
132, // 223: gctrpc.GoCryptoTraderService.RemovePortfolioAddress:output_type -> gctrpc.GenericResponse
52, // 224: gctrpc.GoCryptoTraderService.GetForexProviders:output_type -> gctrpc.GetForexProvidersResponse
55, // 225: gctrpc.GoCryptoTraderService.GetForexRates:output_type -> gctrpc.GetForexRatesResponse
59, // 226: gctrpc.GoCryptoTraderService.GetOrders:output_type -> gctrpc.GetOrdersResponse
56, // 227: gctrpc.GoCryptoTraderService.GetOrder:output_type -> gctrpc.OrderDetails
63, // 228: gctrpc.GoCryptoTraderService.SubmitOrder:output_type -> gctrpc.SubmitOrderResponse
65, // 229: gctrpc.GoCryptoTraderService.SimulateOrder:output_type -> gctrpc.SimulateOrderResponse
65, // 230: gctrpc.GoCryptoTraderService.WhaleBomb:output_type -> gctrpc.SimulateOrderResponse
132, // 231: gctrpc.GoCryptoTraderService.CancelOrder:output_type -> gctrpc.GenericResponse
70, // 232: gctrpc.GoCryptoTraderService.CancelBatchOrders:output_type -> gctrpc.CancelBatchOrdersResponse
72, // 233: gctrpc.GoCryptoTraderService.CancelAllOrders:output_type -> gctrpc.CancelAllOrdersResponse
75, // 234: gctrpc.GoCryptoTraderService.GetEvents:output_type -> gctrpc.GetEventsResponse
77, // 235: gctrpc.GoCryptoTraderService.AddEvent:output_type -> gctrpc.AddEventResponse
132, // 236: gctrpc.GoCryptoTraderService.RemoveEvent:output_type -> gctrpc.GenericResponse
82, // 237: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddresses:output_type -> gctrpc.GetCryptocurrencyDepositAddressesResponse
84, // 238: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddress:output_type -> gctrpc.GetCryptocurrencyDepositAddressResponse
86, // 239: gctrpc.GoCryptoTraderService.GetAvailableTransferChains:output_type -> gctrpc.GetAvailableTransferChainsResponse
89, // 240: gctrpc.GoCryptoTraderService.WithdrawFiatFunds:output_type -> gctrpc.WithdrawResponse
89, // 241: gctrpc.GoCryptoTraderService.WithdrawCryptocurrencyFunds:output_type -> gctrpc.WithdrawResponse
91, // 242: gctrpc.GoCryptoTraderService.WithdrawalEventByID:output_type -> gctrpc.WithdrawalEventByIDResponse
94, // 243: gctrpc.GoCryptoTraderService.WithdrawalEventsByExchange:output_type -> gctrpc.WithdrawalEventsByExchangeResponse
94, // 244: gctrpc.GoCryptoTraderService.WithdrawalEventsByDate:output_type -> gctrpc.WithdrawalEventsByExchangeResponse
101, // 245: gctrpc.GoCryptoTraderService.GetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse
101, // 246: gctrpc.GoCryptoTraderService.SetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse
104, // 247: gctrpc.GoCryptoTraderService.GetExchangePairs:output_type -> gctrpc.GetExchangePairsResponse
132, // 248: gctrpc.GoCryptoTraderService.SetExchangePair:output_type -> gctrpc.GenericResponse
28, // 249: gctrpc.GoCryptoTraderService.GetOrderbookStream:output_type -> gctrpc.OrderbookResponse
28, // 250: gctrpc.GoCryptoTraderService.GetExchangeOrderbookStream:output_type -> gctrpc.OrderbookResponse
22, // 251: gctrpc.GoCryptoTraderService.GetTickerStream:output_type -> gctrpc.TickerResponse
22, // 252: gctrpc.GoCryptoTraderService.GetExchangeTickerStream:output_type -> gctrpc.TickerResponse
111, // 253: gctrpc.GoCryptoTraderService.GetAuditEvent:output_type -> gctrpc.GetAuditEventResponse
132, // 254: gctrpc.GoCryptoTraderService.GCTScriptExecute:output_type -> gctrpc.GenericResponse
132, // 255: gctrpc.GoCryptoTraderService.GCTScriptUpload:output_type -> gctrpc.GenericResponse
131, // 256: gctrpc.GoCryptoTraderService.GCTScriptReadScript:output_type -> gctrpc.GCTScriptQueryResponse
130, // 257: gctrpc.GoCryptoTraderService.GCTScriptStatus:output_type -> gctrpc.GCTScriptStatusResponse
131, // 258: gctrpc.GoCryptoTraderService.GCTScriptQuery:output_type -> gctrpc.GCTScriptQueryResponse
132, // 259: gctrpc.GoCryptoTraderService.GCTScriptStop:output_type -> gctrpc.GenericResponse
132, // 260: gctrpc.GoCryptoTraderService.GCTScriptStopAll:output_type -> gctrpc.GenericResponse
130, // 261: gctrpc.GoCryptoTraderService.GCTScriptListAll:output_type -> gctrpc.GCTScriptStatusResponse
132, // 262: gctrpc.GoCryptoTraderService.GCTScriptAutoLoadToggle:output_type -> gctrpc.GenericResponse
117, // 263: gctrpc.GoCryptoTraderService.GetHistoricCandles:output_type -> gctrpc.GetHistoricCandlesResponse
132, // 264: gctrpc.GoCryptoTraderService.SetExchangeAsset:output_type -> gctrpc.GenericResponse
132, // 265: gctrpc.GoCryptoTraderService.SetAllExchangePairs:output_type -> gctrpc.GenericResponse
132, // 266: gctrpc.GoCryptoTraderService.UpdateExchangeSupportedPairs:output_type -> gctrpc.GenericResponse
137, // 267: gctrpc.GoCryptoTraderService.GetExchangeAssets:output_type -> gctrpc.GetExchangeAssetsResponse
139, // 268: gctrpc.GoCryptoTraderService.WebsocketGetInfo:output_type -> gctrpc.WebsocketGetInfoResponse
132, // 269: gctrpc.GoCryptoTraderService.WebsocketSetEnabled:output_type -> gctrpc.GenericResponse
143, // 270: gctrpc.GoCryptoTraderService.WebsocketGetSubscriptions:output_type -> gctrpc.WebsocketGetSubscriptionsResponse
132, // 271: gctrpc.GoCryptoTraderService.WebsocketSetProxy:output_type -> gctrpc.GenericResponse
132, // 272: gctrpc.GoCryptoTraderService.WebsocketSetURL:output_type -> gctrpc.GenericResponse
114, // 273: gctrpc.GoCryptoTraderService.GetRecentTrades:output_type -> gctrpc.SavedTradesResponse
114, // 274: gctrpc.GoCryptoTraderService.GetHistoricTrades:output_type -> gctrpc.SavedTradesResponse
114, // 275: gctrpc.GoCryptoTraderService.GetSavedTrades:output_type -> gctrpc.SavedTradesResponse
117, // 276: gctrpc.GoCryptoTraderService.ConvertTradesToCandles:output_type -> gctrpc.GetHistoricCandlesResponse
148, // 277: gctrpc.GoCryptoTraderService.FindMissingSavedCandleIntervals:output_type -> gctrpc.FindMissingIntervalsResponse
148, // 278: gctrpc.GoCryptoTraderService.FindMissingSavedTradeIntervals:output_type -> gctrpc.FindMissingIntervalsResponse
132, // 279: gctrpc.GoCryptoTraderService.SetExchangeTradeProcessing:output_type -> gctrpc.GenericResponse
153, // 280: gctrpc.GoCryptoTraderService.UpsertDataHistoryJob:output_type -> gctrpc.UpsertDataHistoryJobResponse
155, // 281: gctrpc.GoCryptoTraderService.GetDataHistoryJobDetails:output_type -> gctrpc.DataHistoryJob
157, // 282: gctrpc.GoCryptoTraderService.GetActiveDataHistoryJobs:output_type -> gctrpc.DataHistoryJobs
157, // 283: gctrpc.GoCryptoTraderService.GetDataHistoryJobsBetween:output_type -> gctrpc.DataHistoryJobs
155, // 284: gctrpc.GoCryptoTraderService.GetDataHistoryJobSummary:output_type -> gctrpc.DataHistoryJob
132, // 285: gctrpc.GoCryptoTraderService.SetDataHistoryJobStatus:output_type -> gctrpc.GenericResponse
132, // 286: gctrpc.GoCryptoTraderService.UpdateDataHistoryJobPrerequisite:output_type -> gctrpc.GenericResponse
59, // 287: gctrpc.GoCryptoTraderService.GetManagedOrders:output_type -> gctrpc.GetOrdersResponse
162, // 288: gctrpc.GoCryptoTraderService.ModifyOrder:output_type -> gctrpc.ModifyOrderResponse
168, // 289: gctrpc.GoCryptoTraderService.CurrencyStateGetAll:output_type -> gctrpc.CurrencyStateResponse
132, // 290: gctrpc.GoCryptoTraderService.CurrencyStateTrading:output_type -> gctrpc.GenericResponse
132, // 291: gctrpc.GoCryptoTraderService.CurrencyStateDeposit:output_type -> gctrpc.GenericResponse
132, // 292: gctrpc.GoCryptoTraderService.CurrencyStateWithdraw:output_type -> gctrpc.GenericResponse
132, // 293: gctrpc.GoCryptoTraderService.CurrencyStateTradingPair:output_type -> gctrpc.GenericResponse
171, // 294: gctrpc.GoCryptoTraderService.GetFuturesPositions:output_type -> gctrpc.GetFuturesPositionsResponse
174, // 295: gctrpc.GoCryptoTraderService.GetCollateral:output_type -> gctrpc.GetCollateralResponse
179, // 296: gctrpc.GoCryptoTraderService.Shutdown:output_type -> gctrpc.ShutdownResponse
200, // [200:297] is the sub-list for method output_type
103, // [103:200] is the sub-list for method input_type
103, // [103:103] is the sub-list for extension type_name
103, // [103:103] is the sub-list for extension extendee
0, // [0:103] is the sub-list for field type_name
21, // 94: gctrpc.GetTechnicalAnalysisRequest.pair:type_name -> gctrpc.CurrencyPair
197, // 95: gctrpc.GetTechnicalAnalysisRequest.start:type_name -> google.protobuf.Timestamp
197, // 96: gctrpc.GetTechnicalAnalysisRequest.end:type_name -> google.protobuf.Timestamp
21, // 97: gctrpc.GetTechnicalAnalysisRequest.other_pair:type_name -> gctrpc.CurrencyPair
196, // 98: gctrpc.GetTechnicalAnalysisResponse.signals:type_name -> gctrpc.GetTechnicalAnalysisResponse.SignalsEntry
9, // 99: gctrpc.GetInfoResponse.RpcEndpointsEntry.value:type_name -> gctrpc.RPCEndpoint
3, // 100: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry.value:type_name -> gctrpc.CommunicationRelayer
9, // 101: gctrpc.GetRPCEndpointsResponse.EndpointsEntry.value:type_name -> gctrpc.RPCEndpoint
18, // 102: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported
44, // 103: gctrpc.OnlineCoins.CoinsEntry.value:type_name -> gctrpc.OnlineCoinSummary
45, // 104: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry.value:type_name -> gctrpc.OfflineCoins
46, // 105: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry.value:type_name -> gctrpc.OnlineCoins
81, // 106: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry.value:type_name -> gctrpc.DepositAddresses
18, // 107: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported
181, // 108: gctrpc.GetTechnicalAnalysisResponse.SignalsEntry.value:type_name -> gctrpc.ListOfSignals
0, // 109: gctrpc.GoCryptoTraderService.GetInfo:input_type -> gctrpc.GetInfoRequest
6, // 110: gctrpc.GoCryptoTraderService.GetSubsystems:input_type -> gctrpc.GetSubsystemsRequest
5, // 111: gctrpc.GoCryptoTraderService.EnableSubsystem:input_type -> gctrpc.GenericSubsystemRequest
5, // 112: gctrpc.GoCryptoTraderService.DisableSubsystem:input_type -> gctrpc.GenericSubsystemRequest
8, // 113: gctrpc.GoCryptoTraderService.GetRPCEndpoints:input_type -> gctrpc.GetRPCEndpointsRequest
2, // 114: gctrpc.GoCryptoTraderService.GetCommunicationRelayers:input_type -> gctrpc.GetCommunicationRelayersRequest
12, // 115: gctrpc.GoCryptoTraderService.GetExchanges:input_type -> gctrpc.GetExchangesRequest
11, // 116: gctrpc.GoCryptoTraderService.DisableExchange:input_type -> gctrpc.GenericExchangeNameRequest
11, // 117: gctrpc.GoCryptoTraderService.GetExchangeInfo:input_type -> gctrpc.GenericExchangeNameRequest
11, // 118: gctrpc.GoCryptoTraderService.GetExchangeOTPCode:input_type -> gctrpc.GenericExchangeNameRequest
15, // 119: gctrpc.GoCryptoTraderService.GetExchangeOTPCodes:input_type -> gctrpc.GetExchangeOTPsRequest
11, // 120: gctrpc.GoCryptoTraderService.EnableExchange:input_type -> gctrpc.GenericExchangeNameRequest
20, // 121: gctrpc.GoCryptoTraderService.GetTicker:input_type -> gctrpc.GetTickerRequest
23, // 122: gctrpc.GoCryptoTraderService.GetTickers:input_type -> gctrpc.GetTickersRequest
26, // 123: gctrpc.GoCryptoTraderService.GetOrderbook:input_type -> gctrpc.GetOrderbookRequest
29, // 124: gctrpc.GoCryptoTraderService.GetOrderbooks:input_type -> gctrpc.GetOrderbooksRequest
32, // 125: gctrpc.GoCryptoTraderService.GetAccountInfo:input_type -> gctrpc.GetAccountInfoRequest
32, // 126: gctrpc.GoCryptoTraderService.UpdateAccountInfo:input_type -> gctrpc.GetAccountInfoRequest
32, // 127: gctrpc.GoCryptoTraderService.GetAccountInfoStream:input_type -> gctrpc.GetAccountInfoRequest
36, // 128: gctrpc.GoCryptoTraderService.GetConfig:input_type -> gctrpc.GetConfigRequest
39, // 129: gctrpc.GoCryptoTraderService.GetPortfolio:input_type -> gctrpc.GetPortfolioRequest
41, // 130: gctrpc.GoCryptoTraderService.GetPortfolioSummary:input_type -> gctrpc.GetPortfolioSummaryRequest
48, // 131: gctrpc.GoCryptoTraderService.AddPortfolioAddress:input_type -> gctrpc.AddPortfolioAddressRequest
49, // 132: gctrpc.GoCryptoTraderService.RemovePortfolioAddress:input_type -> gctrpc.RemovePortfolioAddressRequest
50, // 133: gctrpc.GoCryptoTraderService.GetForexProviders:input_type -> gctrpc.GetForexProvidersRequest
53, // 134: gctrpc.GoCryptoTraderService.GetForexRates:input_type -> gctrpc.GetForexRatesRequest
58, // 135: gctrpc.GoCryptoTraderService.GetOrders:input_type -> gctrpc.GetOrdersRequest
60, // 136: gctrpc.GoCryptoTraderService.GetOrder:input_type -> gctrpc.GetOrderRequest
61, // 137: gctrpc.GoCryptoTraderService.SubmitOrder:input_type -> gctrpc.SubmitOrderRequest
64, // 138: gctrpc.GoCryptoTraderService.SimulateOrder:input_type -> gctrpc.SimulateOrderRequest
66, // 139: gctrpc.GoCryptoTraderService.WhaleBomb:input_type -> gctrpc.WhaleBombRequest
67, // 140: gctrpc.GoCryptoTraderService.CancelOrder:input_type -> gctrpc.CancelOrderRequest
68, // 141: gctrpc.GoCryptoTraderService.CancelBatchOrders:input_type -> gctrpc.CancelBatchOrdersRequest
71, // 142: gctrpc.GoCryptoTraderService.CancelAllOrders:input_type -> gctrpc.CancelAllOrdersRequest
73, // 143: gctrpc.GoCryptoTraderService.GetEvents:input_type -> gctrpc.GetEventsRequest
76, // 144: gctrpc.GoCryptoTraderService.AddEvent:input_type -> gctrpc.AddEventRequest
78, // 145: gctrpc.GoCryptoTraderService.RemoveEvent:input_type -> gctrpc.RemoveEventRequest
79, // 146: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddresses:input_type -> gctrpc.GetCryptocurrencyDepositAddressesRequest
83, // 147: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddress:input_type -> gctrpc.GetCryptocurrencyDepositAddressRequest
85, // 148: gctrpc.GoCryptoTraderService.GetAvailableTransferChains:input_type -> gctrpc.GetAvailableTransferChainsRequest
87, // 149: gctrpc.GoCryptoTraderService.WithdrawFiatFunds:input_type -> gctrpc.WithdrawFiatRequest
88, // 150: gctrpc.GoCryptoTraderService.WithdrawCryptocurrencyFunds:input_type -> gctrpc.WithdrawCryptoRequest
90, // 151: gctrpc.GoCryptoTraderService.WithdrawalEventByID:input_type -> gctrpc.WithdrawalEventByIDRequest
92, // 152: gctrpc.GoCryptoTraderService.WithdrawalEventsByExchange:input_type -> gctrpc.WithdrawalEventsByExchangeRequest
93, // 153: gctrpc.GoCryptoTraderService.WithdrawalEventsByDate:input_type -> gctrpc.WithdrawalEventsByDateRequest
100, // 154: gctrpc.GoCryptoTraderService.GetLoggerDetails:input_type -> gctrpc.GetLoggerDetailsRequest
102, // 155: gctrpc.GoCryptoTraderService.SetLoggerDetails:input_type -> gctrpc.SetLoggerDetailsRequest
103, // 156: gctrpc.GoCryptoTraderService.GetExchangePairs:input_type -> gctrpc.GetExchangePairsRequest
105, // 157: gctrpc.GoCryptoTraderService.SetExchangePair:input_type -> gctrpc.SetExchangePairRequest
106, // 158: gctrpc.GoCryptoTraderService.GetOrderbookStream:input_type -> gctrpc.GetOrderbookStreamRequest
107, // 159: gctrpc.GoCryptoTraderService.GetExchangeOrderbookStream:input_type -> gctrpc.GetExchangeOrderbookStreamRequest
108, // 160: gctrpc.GoCryptoTraderService.GetTickerStream:input_type -> gctrpc.GetTickerStreamRequest
109, // 161: gctrpc.GoCryptoTraderService.GetExchangeTickerStream:input_type -> gctrpc.GetExchangeTickerStreamRequest
110, // 162: gctrpc.GoCryptoTraderService.GetAuditEvent:input_type -> gctrpc.GetAuditEventRequest
121, // 163: gctrpc.GoCryptoTraderService.GCTScriptExecute:input_type -> gctrpc.GCTScriptExecuteRequest
126, // 164: gctrpc.GoCryptoTraderService.GCTScriptUpload:input_type -> gctrpc.GCTScriptUploadRequest
127, // 165: gctrpc.GoCryptoTraderService.GCTScriptReadScript:input_type -> gctrpc.GCTScriptReadScriptRequest
124, // 166: gctrpc.GoCryptoTraderService.GCTScriptStatus:input_type -> gctrpc.GCTScriptStatusRequest
128, // 167: gctrpc.GoCryptoTraderService.GCTScriptQuery:input_type -> gctrpc.GCTScriptQueryRequest
122, // 168: gctrpc.GoCryptoTraderService.GCTScriptStop:input_type -> gctrpc.GCTScriptStopRequest
123, // 169: gctrpc.GoCryptoTraderService.GCTScriptStopAll:input_type -> gctrpc.GCTScriptStopAllRequest
125, // 170: gctrpc.GoCryptoTraderService.GCTScriptListAll:input_type -> gctrpc.GCTScriptListAllRequest
129, // 171: gctrpc.GoCryptoTraderService.GCTScriptAutoLoadToggle:input_type -> gctrpc.GCTScriptAutoLoadRequest
116, // 172: gctrpc.GoCryptoTraderService.GetHistoricCandles:input_type -> gctrpc.GetHistoricCandlesRequest
133, // 173: gctrpc.GoCryptoTraderService.SetExchangeAsset:input_type -> gctrpc.SetExchangeAssetRequest
134, // 174: gctrpc.GoCryptoTraderService.SetAllExchangePairs:input_type -> gctrpc.SetExchangeAllPairsRequest
135, // 175: gctrpc.GoCryptoTraderService.UpdateExchangeSupportedPairs:input_type -> gctrpc.UpdateExchangeSupportedPairsRequest
136, // 176: gctrpc.GoCryptoTraderService.GetExchangeAssets:input_type -> gctrpc.GetExchangeAssetsRequest
138, // 177: gctrpc.GoCryptoTraderService.WebsocketGetInfo:input_type -> gctrpc.WebsocketGetInfoRequest
140, // 178: gctrpc.GoCryptoTraderService.WebsocketSetEnabled:input_type -> gctrpc.WebsocketSetEnabledRequest
141, // 179: gctrpc.GoCryptoTraderService.WebsocketGetSubscriptions:input_type -> gctrpc.WebsocketGetSubscriptionsRequest
144, // 180: gctrpc.GoCryptoTraderService.WebsocketSetProxy:input_type -> gctrpc.WebsocketSetProxyRequest
145, // 181: gctrpc.GoCryptoTraderService.WebsocketSetURL:input_type -> gctrpc.WebsocketSetURLRequest
112, // 182: gctrpc.GoCryptoTraderService.GetRecentTrades:input_type -> gctrpc.GetSavedTradesRequest
112, // 183: gctrpc.GoCryptoTraderService.GetHistoricTrades:input_type -> gctrpc.GetSavedTradesRequest
112, // 184: gctrpc.GoCryptoTraderService.GetSavedTrades:input_type -> gctrpc.GetSavedTradesRequest
115, // 185: gctrpc.GoCryptoTraderService.ConvertTradesToCandles:input_type -> gctrpc.ConvertTradesToCandlesRequest
146, // 186: gctrpc.GoCryptoTraderService.FindMissingSavedCandleIntervals:input_type -> gctrpc.FindMissingCandlePeriodsRequest
147, // 187: gctrpc.GoCryptoTraderService.FindMissingSavedTradeIntervals:input_type -> gctrpc.FindMissingTradePeriodsRequest
149, // 188: gctrpc.GoCryptoTraderService.SetExchangeTradeProcessing:input_type -> gctrpc.SetExchangeTradeProcessingRequest
150, // 189: gctrpc.GoCryptoTraderService.UpsertDataHistoryJob:input_type -> gctrpc.UpsertDataHistoryJobRequest
154, // 190: gctrpc.GoCryptoTraderService.GetDataHistoryJobDetails:input_type -> gctrpc.GetDataHistoryJobDetailsRequest
0, // 191: gctrpc.GoCryptoTraderService.GetActiveDataHistoryJobs:input_type -> gctrpc.GetInfoRequest
158, // 192: gctrpc.GoCryptoTraderService.GetDataHistoryJobsBetween:input_type -> gctrpc.GetDataHistoryJobsBetweenRequest
154, // 193: gctrpc.GoCryptoTraderService.GetDataHistoryJobSummary:input_type -> gctrpc.GetDataHistoryJobDetailsRequest
159, // 194: gctrpc.GoCryptoTraderService.SetDataHistoryJobStatus:input_type -> gctrpc.SetDataHistoryJobStatusRequest
160, // 195: gctrpc.GoCryptoTraderService.UpdateDataHistoryJobPrerequisite:input_type -> gctrpc.UpdateDataHistoryJobPrerequisiteRequest
58, // 196: gctrpc.GoCryptoTraderService.GetManagedOrders:input_type -> gctrpc.GetOrdersRequest
161, // 197: gctrpc.GoCryptoTraderService.ModifyOrder:input_type -> gctrpc.ModifyOrderRequest
163, // 198: gctrpc.GoCryptoTraderService.CurrencyStateGetAll:input_type -> gctrpc.CurrencyStateGetAllRequest
164, // 199: gctrpc.GoCryptoTraderService.CurrencyStateTrading:input_type -> gctrpc.CurrencyStateTradingRequest
167, // 200: gctrpc.GoCryptoTraderService.CurrencyStateDeposit:input_type -> gctrpc.CurrencyStateDepositRequest
166, // 201: gctrpc.GoCryptoTraderService.CurrencyStateWithdraw:input_type -> gctrpc.CurrencyStateWithdrawRequest
165, // 202: gctrpc.GoCryptoTraderService.CurrencyStateTradingPair:input_type -> gctrpc.CurrencyStateTradingPairRequest
170, // 203: gctrpc.GoCryptoTraderService.GetFuturesPositions:input_type -> gctrpc.GetFuturesPositionsRequest
173, // 204: gctrpc.GoCryptoTraderService.GetCollateral:input_type -> gctrpc.GetCollateralRequest
178, // 205: gctrpc.GoCryptoTraderService.Shutdown:input_type -> gctrpc.ShutdownRequest
180, // 206: gctrpc.GoCryptoTraderService.GetTechnicalAnalysis:input_type -> gctrpc.GetTechnicalAnalysisRequest
1, // 207: gctrpc.GoCryptoTraderService.GetInfo:output_type -> gctrpc.GetInfoResponse
7, // 208: gctrpc.GoCryptoTraderService.GetSubsystems:output_type -> gctrpc.GetSusbsytemsResponse
132, // 209: gctrpc.GoCryptoTraderService.EnableSubsystem:output_type -> gctrpc.GenericResponse
132, // 210: gctrpc.GoCryptoTraderService.DisableSubsystem:output_type -> gctrpc.GenericResponse
10, // 211: gctrpc.GoCryptoTraderService.GetRPCEndpoints:output_type -> gctrpc.GetRPCEndpointsResponse
4, // 212: gctrpc.GoCryptoTraderService.GetCommunicationRelayers:output_type -> gctrpc.GetCommunicationRelayersResponse
13, // 213: gctrpc.GoCryptoTraderService.GetExchanges:output_type -> gctrpc.GetExchangesResponse
132, // 214: gctrpc.GoCryptoTraderService.DisableExchange:output_type -> gctrpc.GenericResponse
19, // 215: gctrpc.GoCryptoTraderService.GetExchangeInfo:output_type -> gctrpc.GetExchangeInfoResponse
14, // 216: gctrpc.GoCryptoTraderService.GetExchangeOTPCode:output_type -> gctrpc.GetExchangeOTPResponse
16, // 217: gctrpc.GoCryptoTraderService.GetExchangeOTPCodes:output_type -> gctrpc.GetExchangeOTPsResponse
132, // 218: gctrpc.GoCryptoTraderService.EnableExchange:output_type -> gctrpc.GenericResponse
22, // 219: gctrpc.GoCryptoTraderService.GetTicker:output_type -> gctrpc.TickerResponse
25, // 220: gctrpc.GoCryptoTraderService.GetTickers:output_type -> gctrpc.GetTickersResponse
28, // 221: gctrpc.GoCryptoTraderService.GetOrderbook:output_type -> gctrpc.OrderbookResponse
31, // 222: gctrpc.GoCryptoTraderService.GetOrderbooks:output_type -> gctrpc.GetOrderbooksResponse
35, // 223: gctrpc.GoCryptoTraderService.GetAccountInfo:output_type -> gctrpc.GetAccountInfoResponse
35, // 224: gctrpc.GoCryptoTraderService.UpdateAccountInfo:output_type -> gctrpc.GetAccountInfoResponse
35, // 225: gctrpc.GoCryptoTraderService.GetAccountInfoStream:output_type -> gctrpc.GetAccountInfoResponse
37, // 226: gctrpc.GoCryptoTraderService.GetConfig:output_type -> gctrpc.GetConfigResponse
40, // 227: gctrpc.GoCryptoTraderService.GetPortfolio:output_type -> gctrpc.GetPortfolioResponse
47, // 228: gctrpc.GoCryptoTraderService.GetPortfolioSummary:output_type -> gctrpc.GetPortfolioSummaryResponse
132, // 229: gctrpc.GoCryptoTraderService.AddPortfolioAddress:output_type -> gctrpc.GenericResponse
132, // 230: gctrpc.GoCryptoTraderService.RemovePortfolioAddress:output_type -> gctrpc.GenericResponse
52, // 231: gctrpc.GoCryptoTraderService.GetForexProviders:output_type -> gctrpc.GetForexProvidersResponse
55, // 232: gctrpc.GoCryptoTraderService.GetForexRates:output_type -> gctrpc.GetForexRatesResponse
59, // 233: gctrpc.GoCryptoTraderService.GetOrders:output_type -> gctrpc.GetOrdersResponse
56, // 234: gctrpc.GoCryptoTraderService.GetOrder:output_type -> gctrpc.OrderDetails
63, // 235: gctrpc.GoCryptoTraderService.SubmitOrder:output_type -> gctrpc.SubmitOrderResponse
65, // 236: gctrpc.GoCryptoTraderService.SimulateOrder:output_type -> gctrpc.SimulateOrderResponse
65, // 237: gctrpc.GoCryptoTraderService.WhaleBomb:output_type -> gctrpc.SimulateOrderResponse
132, // 238: gctrpc.GoCryptoTraderService.CancelOrder:output_type -> gctrpc.GenericResponse
70, // 239: gctrpc.GoCryptoTraderService.CancelBatchOrders:output_type -> gctrpc.CancelBatchOrdersResponse
72, // 240: gctrpc.GoCryptoTraderService.CancelAllOrders:output_type -> gctrpc.CancelAllOrdersResponse
75, // 241: gctrpc.GoCryptoTraderService.GetEvents:output_type -> gctrpc.GetEventsResponse
77, // 242: gctrpc.GoCryptoTraderService.AddEvent:output_type -> gctrpc.AddEventResponse
132, // 243: gctrpc.GoCryptoTraderService.RemoveEvent:output_type -> gctrpc.GenericResponse
82, // 244: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddresses:output_type -> gctrpc.GetCryptocurrencyDepositAddressesResponse
84, // 245: gctrpc.GoCryptoTraderService.GetCryptocurrencyDepositAddress:output_type -> gctrpc.GetCryptocurrencyDepositAddressResponse
86, // 246: gctrpc.GoCryptoTraderService.GetAvailableTransferChains:output_type -> gctrpc.GetAvailableTransferChainsResponse
89, // 247: gctrpc.GoCryptoTraderService.WithdrawFiatFunds:output_type -> gctrpc.WithdrawResponse
89, // 248: gctrpc.GoCryptoTraderService.WithdrawCryptocurrencyFunds:output_type -> gctrpc.WithdrawResponse
91, // 249: gctrpc.GoCryptoTraderService.WithdrawalEventByID:output_type -> gctrpc.WithdrawalEventByIDResponse
94, // 250: gctrpc.GoCryptoTraderService.WithdrawalEventsByExchange:output_type -> gctrpc.WithdrawalEventsByExchangeResponse
94, // 251: gctrpc.GoCryptoTraderService.WithdrawalEventsByDate:output_type -> gctrpc.WithdrawalEventsByExchangeResponse
101, // 252: gctrpc.GoCryptoTraderService.GetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse
101, // 253: gctrpc.GoCryptoTraderService.SetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse
104, // 254: gctrpc.GoCryptoTraderService.GetExchangePairs:output_type -> gctrpc.GetExchangePairsResponse
132, // 255: gctrpc.GoCryptoTraderService.SetExchangePair:output_type -> gctrpc.GenericResponse
28, // 256: gctrpc.GoCryptoTraderService.GetOrderbookStream:output_type -> gctrpc.OrderbookResponse
28, // 257: gctrpc.GoCryptoTraderService.GetExchangeOrderbookStream:output_type -> gctrpc.OrderbookResponse
22, // 258: gctrpc.GoCryptoTraderService.GetTickerStream:output_type -> gctrpc.TickerResponse
22, // 259: gctrpc.GoCryptoTraderService.GetExchangeTickerStream:output_type -> gctrpc.TickerResponse
111, // 260: gctrpc.GoCryptoTraderService.GetAuditEvent:output_type -> gctrpc.GetAuditEventResponse
132, // 261: gctrpc.GoCryptoTraderService.GCTScriptExecute:output_type -> gctrpc.GenericResponse
132, // 262: gctrpc.GoCryptoTraderService.GCTScriptUpload:output_type -> gctrpc.GenericResponse
131, // 263: gctrpc.GoCryptoTraderService.GCTScriptReadScript:output_type -> gctrpc.GCTScriptQueryResponse
130, // 264: gctrpc.GoCryptoTraderService.GCTScriptStatus:output_type -> gctrpc.GCTScriptStatusResponse
131, // 265: gctrpc.GoCryptoTraderService.GCTScriptQuery:output_type -> gctrpc.GCTScriptQueryResponse
132, // 266: gctrpc.GoCryptoTraderService.GCTScriptStop:output_type -> gctrpc.GenericResponse
132, // 267: gctrpc.GoCryptoTraderService.GCTScriptStopAll:output_type -> gctrpc.GenericResponse
130, // 268: gctrpc.GoCryptoTraderService.GCTScriptListAll:output_type -> gctrpc.GCTScriptStatusResponse
132, // 269: gctrpc.GoCryptoTraderService.GCTScriptAutoLoadToggle:output_type -> gctrpc.GenericResponse
117, // 270: gctrpc.GoCryptoTraderService.GetHistoricCandles:output_type -> gctrpc.GetHistoricCandlesResponse
132, // 271: gctrpc.GoCryptoTraderService.SetExchangeAsset:output_type -> gctrpc.GenericResponse
132, // 272: gctrpc.GoCryptoTraderService.SetAllExchangePairs:output_type -> gctrpc.GenericResponse
132, // 273: gctrpc.GoCryptoTraderService.UpdateExchangeSupportedPairs:output_type -> gctrpc.GenericResponse
137, // 274: gctrpc.GoCryptoTraderService.GetExchangeAssets:output_type -> gctrpc.GetExchangeAssetsResponse
139, // 275: gctrpc.GoCryptoTraderService.WebsocketGetInfo:output_type -> gctrpc.WebsocketGetInfoResponse
132, // 276: gctrpc.GoCryptoTraderService.WebsocketSetEnabled:output_type -> gctrpc.GenericResponse
143, // 277: gctrpc.GoCryptoTraderService.WebsocketGetSubscriptions:output_type -> gctrpc.WebsocketGetSubscriptionsResponse
132, // 278: gctrpc.GoCryptoTraderService.WebsocketSetProxy:output_type -> gctrpc.GenericResponse
132, // 279: gctrpc.GoCryptoTraderService.WebsocketSetURL:output_type -> gctrpc.GenericResponse
114, // 280: gctrpc.GoCryptoTraderService.GetRecentTrades:output_type -> gctrpc.SavedTradesResponse
114, // 281: gctrpc.GoCryptoTraderService.GetHistoricTrades:output_type -> gctrpc.SavedTradesResponse
114, // 282: gctrpc.GoCryptoTraderService.GetSavedTrades:output_type -> gctrpc.SavedTradesResponse
117, // 283: gctrpc.GoCryptoTraderService.ConvertTradesToCandles:output_type -> gctrpc.GetHistoricCandlesResponse
148, // 284: gctrpc.GoCryptoTraderService.FindMissingSavedCandleIntervals:output_type -> gctrpc.FindMissingIntervalsResponse
148, // 285: gctrpc.GoCryptoTraderService.FindMissingSavedTradeIntervals:output_type -> gctrpc.FindMissingIntervalsResponse
132, // 286: gctrpc.GoCryptoTraderService.SetExchangeTradeProcessing:output_type -> gctrpc.GenericResponse
153, // 287: gctrpc.GoCryptoTraderService.UpsertDataHistoryJob:output_type -> gctrpc.UpsertDataHistoryJobResponse
155, // 288: gctrpc.GoCryptoTraderService.GetDataHistoryJobDetails:output_type -> gctrpc.DataHistoryJob
157, // 289: gctrpc.GoCryptoTraderService.GetActiveDataHistoryJobs:output_type -> gctrpc.DataHistoryJobs
157, // 290: gctrpc.GoCryptoTraderService.GetDataHistoryJobsBetween:output_type -> gctrpc.DataHistoryJobs
155, // 291: gctrpc.GoCryptoTraderService.GetDataHistoryJobSummary:output_type -> gctrpc.DataHistoryJob
132, // 292: gctrpc.GoCryptoTraderService.SetDataHistoryJobStatus:output_type -> gctrpc.GenericResponse
132, // 293: gctrpc.GoCryptoTraderService.UpdateDataHistoryJobPrerequisite:output_type -> gctrpc.GenericResponse
59, // 294: gctrpc.GoCryptoTraderService.GetManagedOrders:output_type -> gctrpc.GetOrdersResponse
162, // 295: gctrpc.GoCryptoTraderService.ModifyOrder:output_type -> gctrpc.ModifyOrderResponse
168, // 296: gctrpc.GoCryptoTraderService.CurrencyStateGetAll:output_type -> gctrpc.CurrencyStateResponse
132, // 297: gctrpc.GoCryptoTraderService.CurrencyStateTrading:output_type -> gctrpc.GenericResponse
132, // 298: gctrpc.GoCryptoTraderService.CurrencyStateDeposit:output_type -> gctrpc.GenericResponse
132, // 299: gctrpc.GoCryptoTraderService.CurrencyStateWithdraw:output_type -> gctrpc.GenericResponse
132, // 300: gctrpc.GoCryptoTraderService.CurrencyStateTradingPair:output_type -> gctrpc.GenericResponse
171, // 301: gctrpc.GoCryptoTraderService.GetFuturesPositions:output_type -> gctrpc.GetFuturesPositionsResponse
174, // 302: gctrpc.GoCryptoTraderService.GetCollateral:output_type -> gctrpc.GetCollateralResponse
179, // 303: gctrpc.GoCryptoTraderService.Shutdown:output_type -> gctrpc.ShutdownResponse
182, // 304: gctrpc.GoCryptoTraderService.GetTechnicalAnalysis:output_type -> gctrpc.GetTechnicalAnalysisResponse
207, // [207:305] is the sub-list for method output_type
109, // [109:207] is the sub-list for method input_type
109, // [109:109] is the sub-list for extension type_name
109, // [109:109] is the sub-list for extension extendee
0, // [0:109] is the sub-list for field type_name
}
func init() { file_rpc_proto_init() }
@@ -16801,6 +17139,42 @@ func file_rpc_proto_init() {
return nil
}
}
file_rpc_proto_msgTypes[180].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetTechnicalAnalysisRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_rpc_proto_msgTypes[181].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListOfSignals); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_rpc_proto_msgTypes[182].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetTechnicalAnalysisResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -16808,7 +17182,7 @@ func file_rpc_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_rpc_proto_rawDesc,
NumEnums: 0,
NumMessages: 193,
NumMessages: 197,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -3113,6 +3113,42 @@ func local_request_GoCryptoTraderService_Shutdown_0(ctx context.Context, marshal
}
var (
filter_GoCryptoTraderService_GetTechnicalAnalysis_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_GoCryptoTraderService_GetTechnicalAnalysis_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetTechnicalAnalysisRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTraderService_GetTechnicalAnalysis_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.GetTechnicalAnalysis(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_GoCryptoTraderService_GetTechnicalAnalysis_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetTechnicalAnalysisRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTraderService_GetTechnicalAnalysis_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.GetTechnicalAnalysis(ctx, &protoReq)
return msg, metadata, err
}
// RegisterGoCryptoTraderServiceHandlerServer registers the http handlers for service GoCryptoTraderService to "mux".
// UnaryRPC :call GoCryptoTraderServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -5345,6 +5381,30 @@ func RegisterGoCryptoTraderServiceHandlerServer(ctx context.Context, mux *runtim
})
mux.Handle("GET", pattern_GoCryptoTraderService_GetTechnicalAnalysis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTraderService/GetTechnicalAnalysis", runtime.WithHTTPPathPattern("/v1/gettechnicalanalysis"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_GoCryptoTraderService_GetTechnicalAnalysis_0(ctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_GoCryptoTraderService_GetTechnicalAnalysis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -7423,6 +7483,27 @@ func RegisterGoCryptoTraderServiceHandlerClient(ctx context.Context, mux *runtim
})
mux.Handle("GET", pattern_GoCryptoTraderService_GetTechnicalAnalysis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTraderService/GetTechnicalAnalysis", runtime.WithHTTPPathPattern("/v1/gettechnicalanalysis"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_GoCryptoTraderService_GetTechnicalAnalysis_0(ctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_GoCryptoTraderService_GetTechnicalAnalysis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -7620,6 +7701,8 @@ var (
pattern_GoCryptoTraderService_GetCollateral_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getcollateral"}, ""))
pattern_GoCryptoTraderService_Shutdown_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "shutdown"}, ""))
pattern_GoCryptoTraderService_GetTechnicalAnalysis_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "gettechnicalanalysis"}, ""))
)
var (
@@ -7816,4 +7899,6 @@ var (
forward_GoCryptoTraderService_GetCollateral_0 = runtime.ForwardResponseMessage
forward_GoCryptoTraderService_Shutdown_0 = runtime.ForwardResponseMessage
forward_GoCryptoTraderService_GetTechnicalAnalysis_0 = runtime.ForwardResponseMessage
)

View File

@@ -1119,6 +1119,33 @@ message ShutdownRequest {}
message ShutdownResponse {}
message GetTechnicalAnalysisRequest {
string exchange = 1;
CurrencyPair pair = 2;
string asset_type = 3;
string algorithm_type = 4;
int64 interval = 5;
google.protobuf.Timestamp start = 6;
google.protobuf.Timestamp end = 7;
int64 period = 8;
int64 fast_period = 9;
int64 slow_period = 10;
double standard_deviation_up = 11;
double standard_deviation_down = 12;
int64 moving_average_type = 13;
string other_exchange = 14;
CurrencyPair other_pair = 15;
string other_asset_type = 16;
}
message ListOfSignals {
repeated double signals = 1;
}
message GetTechnicalAnalysisResponse {
map<string, ListOfSignals> signals = 1;
}
service GoCryptoTraderService {
rpc GetInfo(GetInfoRequest) returns (GetInfoResponse) {
option (google.api.http) = {
@@ -1722,4 +1749,9 @@ service GoCryptoTraderService {
get: "/v1/shutdown"
};
}
rpc GetTechnicalAnalysis(GetTechnicalAnalysisRequest) returns (GetTechnicalAnalysisResponse) {
option (google.api.http) = {
get: "/v1/gettechnicalanalysis"
};
}
}

View File

@@ -2577,6 +2577,159 @@
]
}
},
"/v1/gettechnicalanalysis": {
"get": {
"operationId": "GoCryptoTraderService_GetTechnicalAnalysis",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/gctrpcGetTechnicalAnalysisResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "exchange",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "pair.delimiter",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "pair.base",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "pair.quote",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "assetType",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "algorithmType",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "interval",
"in": "query",
"required": false,
"type": "string",
"format": "int64"
},
{
"name": "start",
"in": "query",
"required": false,
"type": "string",
"format": "date-time"
},
{
"name": "end",
"in": "query",
"required": false,
"type": "string",
"format": "date-time"
},
{
"name": "period",
"in": "query",
"required": false,
"type": "string",
"format": "int64"
},
{
"name": "fastPeriod",
"in": "query",
"required": false,
"type": "string",
"format": "int64"
},
{
"name": "slowPeriod",
"in": "query",
"required": false,
"type": "string",
"format": "int64"
},
{
"name": "standardDeviationUp",
"in": "query",
"required": false,
"type": "number",
"format": "double"
},
{
"name": "standardDeviationDown",
"in": "query",
"required": false,
"type": "number",
"format": "double"
},
{
"name": "movingAverageType",
"in": "query",
"required": false,
"type": "string",
"format": "int64"
},
{
"name": "otherExchange",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "otherPair.delimiter",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "otherPair.base",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "otherPair.quote",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "otherAssetType",
"in": "query",
"required": false,
"type": "string"
}
],
"tags": [
"GoCryptoTraderService"
]
}
},
"/v1/getticker": {
"post": {
"operationId": "GoCryptoTraderService_GetTicker",
@@ -4989,6 +5142,17 @@
}
}
},
"gctrpcGetTechnicalAnalysisResponse": {
"type": "object",
"properties": {
"signals": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/gctrpcListOfSignals"
}
}
}
},
"gctrpcGetTickerRequest": {
"type": "object",
"properties": {
@@ -5014,6 +5178,18 @@
}
}
},
"gctrpcListOfSignals": {
"type": "object",
"properties": {
"signals": {
"type": "array",
"items": {
"type": "number",
"format": "double"
}
}
}
},
"gctrpcModifyOrderResponse": {
"type": "object",
"properties": {

View File

@@ -119,6 +119,7 @@ type GoCryptoTraderServiceClient interface {
GetFuturesPositions(ctx context.Context, in *GetFuturesPositionsRequest, opts ...grpc.CallOption) (*GetFuturesPositionsResponse, error)
GetCollateral(ctx context.Context, in *GetCollateralRequest, opts ...grpc.CallOption) (*GetCollateralResponse, error)
Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error)
GetTechnicalAnalysis(ctx context.Context, in *GetTechnicalAnalysisRequest, opts ...grpc.CallOption) (*GetTechnicalAnalysisResponse, error)
}
type goCryptoTraderServiceClient struct {
@@ -1140,6 +1141,15 @@ func (c *goCryptoTraderServiceClient) Shutdown(ctx context.Context, in *Shutdown
return out, nil
}
func (c *goCryptoTraderServiceClient) GetTechnicalAnalysis(ctx context.Context, in *GetTechnicalAnalysisRequest, opts ...grpc.CallOption) (*GetTechnicalAnalysisResponse, error) {
out := new(GetTechnicalAnalysisResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTraderService/GetTechnicalAnalysis", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// GoCryptoTraderServiceServer is the server API for GoCryptoTraderService service.
// All implementations must embed UnimplementedGoCryptoTraderServiceServer
// for forward compatibility
@@ -1241,6 +1251,7 @@ type GoCryptoTraderServiceServer interface {
GetFuturesPositions(context.Context, *GetFuturesPositionsRequest) (*GetFuturesPositionsResponse, error)
GetCollateral(context.Context, *GetCollateralRequest) (*GetCollateralResponse, error)
Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error)
GetTechnicalAnalysis(context.Context, *GetTechnicalAnalysisRequest) (*GetTechnicalAnalysisResponse, error)
mustEmbedUnimplementedGoCryptoTraderServiceServer()
}
@@ -1539,6 +1550,9 @@ func (UnimplementedGoCryptoTraderServiceServer) GetCollateral(context.Context, *
func (UnimplementedGoCryptoTraderServiceServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
}
func (UnimplementedGoCryptoTraderServiceServer) GetTechnicalAnalysis(context.Context, *GetTechnicalAnalysisRequest) (*GetTechnicalAnalysisResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTechnicalAnalysis not implemented")
}
func (UnimplementedGoCryptoTraderServiceServer) mustEmbedUnimplementedGoCryptoTraderServiceServer() {}
// UnsafeGoCryptoTraderServiceServer may be embedded to opt out of forward compatibility for this service.
@@ -3316,6 +3330,24 @@ func _GoCryptoTraderService_Shutdown_Handler(srv interface{}, ctx context.Contex
return interceptor(ctx, in, info, handler)
}
func _GoCryptoTraderService_GetTechnicalAnalysis_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetTechnicalAnalysisRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GoCryptoTraderServiceServer).GetTechnicalAnalysis(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/gctrpc.GoCryptoTraderService/GetTechnicalAnalysis",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GoCryptoTraderServiceServer).GetTechnicalAnalysis(ctx, req.(*GetTechnicalAnalysisRequest))
}
return interceptor(ctx, in, info, handler)
}
// GoCryptoTraderService_ServiceDesc is the grpc.ServiceDesc for GoCryptoTraderService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -3687,6 +3719,10 @@ var GoCryptoTraderService_ServiceDesc = grpc.ServiceDesc{
MethodName: "Shutdown",
Handler: _GoCryptoTraderService_Shutdown_Handler,
},
{
MethodName: "GetTechnicalAnalysis",
Handler: _GoCryptoTraderService_GetTechnicalAnalysis_Handler,
},
},
Streams: []grpc.StreamDesc{
{