Documentation ¶
Index ¶
- Constants
- Variables
- func Code(e *zerolog.Event, code string)
- func Loop(ctx context.Context, d *Dealer, e exchange.IBotExchange, s Strategy) error
- func ModifyOrder(ctx context.Context, d *Dealer, e exchange.IBotExchange, mod order.Modify) (ans order.ModifyResponse, err error)
- func ModifyToCancel(mod order.Modify) order.Cancel
- func ModifyToSubmit(mod order.Modify) order.Submit
- func Msg(e *zerolog.Event)
- func OpenWebsocket(e exchange.IBotExchange) (*stream.Websocket, error)
- func Stream(ctx context.Context, d *Dealer, e exchange.IBotExchange, s Strategy) error
- func Ticker(p interface{}) ticker.Price
- func What(e *zerolog.Event, what string)
- type Array
- type AugmentConfigFunc
- type AwakenLogger
- type BalancesStrategy
- func (b *BalancesStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
- func (b *BalancesStrategy) ExchangeHoldings(exchangeName string) (*ExchangeHoldings, error)
- func (b *BalancesStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
- func (b *BalancesStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
- func (b *BalancesStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
- func (b *BalancesStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
- func (b *BalancesStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
- func (b *BalancesStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
- func (b *BalancesStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
- func (b *BalancesStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
- func (b *BalancesStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
- func (b *BalancesStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
- func (b *BalancesStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
- type Builder
- func (b *Builder) Augment(f AugmentConfigFunc) *Builder
- func (b *Builder) Balances(refresh time.Duration) *Builder
- func (b Builder) Build(ctx context.Context) (*Dealer, error)
- func (b *Builder) CustomExchange(name string, f ExchangeFactory) *Builder
- func (b *Builder) Reporter(r Reporter) *Builder
- func (b *Builder) Settings(s engine.Settings) *Builder
- type CircularArray
- func (a *CircularArray) At(index int) interface{}
- func (a *CircularArray) Floats() []float64
- func (a *CircularArray) Index(i int) int
- func (a *CircularArray) Last() interface{}
- func (a *CircularArray) LastFloat() float64
- func (a *CircularArray) LastIndex() int
- func (a *CircularArray) Len() int
- func (a *CircularArray) Push(x interface{})
- type CurrencyBalance
- type Dealer
- func (bot *Dealer) ActivateAsset(e exchange.IBotExchange, a asset.Item) error
- func (bot *Dealer) ActivatePair(e exchange.IBotExchange, a asset.Item, p currency.Pair) error
- func (bot *Dealer) AddHistorian(exchangeName, eventName string, interval time.Duration, stateLength int, ...) error
- func (bot *Dealer) CancelOrder(ctx context.Context, exchangeOrName interface{}, x order.Cancel) error
- func (bot *Dealer) GetActiveOrders(ctx context.Context, exchangeOrName interface{}, ...) ([]order.Detail, error)
- func (bot *Dealer) GetEnabledPairAssetType(e exchange.IBotExchange, c currency.Pair) (asset.Item, error)
- func (bot *Dealer) GetExchangeByName(name string) (exchange.IBotExchange, error)
- func (bot *Dealer) GetExchanges() []exchange.IBotExchange
- func (bot *Dealer) GetOrderValue(exchangeName, orderID string) (OrderValue, bool)
- func (bot *Dealer) ModifyOrder(ctx context.Context, exchangeOrName interface{}, mod order.Modify) (order.ModifyResponse, error)
- func (bot *Dealer) OnOrder(e exchange.IBotExchange, x order.Detail)
- func (bot *Dealer) ReportEvent(m Metric, labels ...string)
- func (bot *Dealer) ReportLatency(m Metric, t time.Time, labels ...string)
- func (bot *Dealer) ReportValue(m Metric, v float64, labels ...string)
- func (bot *Dealer) Run(ctx context.Context)
- func (bot *Dealer) SubmitOrder(ctx context.Context, exchangeOrName interface{}, submit order.Submit) (*order.SubmitResponse, error)
- func (bot *Dealer) SubmitOrderUD(ctx context.Context, exchangeOrName interface{}, submit order.Submit, ...) (*order.SubmitResponse, error)
- func (bot *Dealer) SubmitOrders(ctx context.Context, e exchange.IBotExchange, xs ...order.Submit) error
- type ExchangeFactory
- type ExchangeHoldings
- type GCTConsoleWriter
- type Historian
- type HistoryStrategy
- func (r *HistoryStrategy) AddHistorian(exchangeName, eventName string, interval time.Duration, stateLength int, ...) error
- func (r *HistoryStrategy) BindOnPrice(unit *Historian)
- func (r *HistoryStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
- func (r *HistoryStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
- func (r *HistoryStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
- func (r *HistoryStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
- func (r *HistoryStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
- func (r *HistoryStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
- func (r *HistoryStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
- func (r *HistoryStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
- func (r *HistoryStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
- func (r *HistoryStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
- func (r *HistoryStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
- func (r *HistoryStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
- type LogState
- type Metric
- type OnFilledObserver
- type OrderKey
- type OrderRegistry
- type OrderValue
- type Reporter
- type RootStrategy
- func (m *RootStrategy) Add(name string, s Strategy)
- func (m *RootStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
- func (m *RootStrategy) Delete(name string) (Strategy, error)
- func (m *RootStrategy) Get(name string) (Strategy, error)
- func (m *RootStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
- func (m *RootStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
- func (m *RootStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
- func (m *RootStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
- func (m *RootStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
- func (m *RootStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
- func (m *RootStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
- func (m *RootStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
- func (m *RootStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
- func (m *RootStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
- func (m *RootStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
- type Slots
- type Strategy
- type SubAccount
- type TickerStrategy
- func (s *TickerStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
- func (s *TickerStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
- func (s *TickerStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
- func (s *TickerStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
- func (s *TickerStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
- func (s *TickerStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
- func (s *TickerStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
- func (s *TickerStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
- func (s *TickerStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
- func (s *TickerStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
- func (s *TickerStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
- func (s *TickerStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
- type Trade
Constants ¶
const ( // Dormant mode: the AwakenLogger outputs trace logs as info // every once in a while. Dormant = iota // Awaken mode: everything is outputted as-is. Awaken = iota )
Variables ¶
var ( ErrNoExchangesLoaded = errors.New("no exchanges have been loaded") ErrExchangeFailedToLoad = errors.New("exchange failed to load") )
var ( ErrAccountIndexOutOfRange = errors.New("no account with this index exists") ErrHoldingsNotFound = errors.New("holdings not found for exchange") ErrAccountNotFound = errors.New("account not found in holdings") ErrAssetNotFound = errors.New("asset not found in account") ErrCurrencyNotFound = errors.New("currency not found in asset") )
var ( ErrStrategyNotFound = errors.New("strategy not found") ErrNotStrategy = errors.New("given object is not a strategy") )
var ( ErrWebsocketNotSupported = errors.New("websocket not supported") ErrWebsocketNotEnabled = errors.New("websocket is not enabled") )
var ErrNeedBalancesStrategy = errors.New("Dealer should be configured with balances support")
var ErrNoAssetType = errors.New("asset type not associated with currency pair")
var ErrOrdersAlreadyExists = errors.New("order already exists")
var ErrUnknownEvent = errors.New("unknown event")
Functions ¶
func Loop ¶
Loop function is the main entry point for the bot. It is responsible for handling the websocket connection and dispatching events to the appropriate strategy. The Loop function is an infinite loop that blocks until the websocket connection is closed. It is expected to be run in a goroutine.
func ModifyOrder ¶
func ModifyOrder(ctx context.Context, d *Dealer, e exchange.IBotExchange, mod order.Modify) (ans order.ModifyResponse, err error)
ModifyOrder function will execute two steps: modify order on exchange current order status using the submitted ID, after that cancel that order using the same ID. All markers issue when modifying/canceling order also will be made using the same ID it was treated before
func ModifyToCancel ¶
ModifyToCancel function is responsible for creating a cancel order
func ModifyToSubmit ¶
ModifyToSubmit function receives a Modify Order which is passed in from the client calls, it creates a Submit order from it. The client calls modifying the order and updating the fetched order if it's done. e.g if an order submitted is filled, the client should change to new order.
func OpenWebsocket ¶
func OpenWebsocket(e exchange.IBotExchange) (*stream.Websocket, error)
OpenWebsocket function is responsible for opening a Websocket connection. The `req.Exchange.GetWebsocket` method performs the actual functionality of creating a new Websocket in a struct. Understandably, if a connection can't be opened, the error would be returned. OpenWebsocket checks if the client is sending a query to the interface instance, blocking on a channel, which was a select on a chan while the bolt process has a rule queuing, while the rest of the engine while be blocked on a chan So, non-blocking options were applied to get a non-blocked client and a non-blocked engine.
func Stream ¶
Stream is the main entry point for the bot. It is responsible for opening the websocket connection, and then listening for data on the websocket to come in. When data comes through (this goroutine never dies), it handles all the types of messages available on the websocket. The *exchange.IBotExchange contains the underlying Golang Websocket library, which must be imported with an alias. By using that package with the alias "exchange", we can consolidate the Exchange package into this one without problematic circular imports.
Types ¶
type Array ¶
type Array interface { At(index int) interface{} Len() int Last() interface{} Floats() []float64 LastFloat() float64 }
Array interface serves to represent a dynamic array of unknown type. For the purpose of this solution we use a `CircularArray` of `string`. Each Historian Object create and own an instance of such a CircularArray. The Dealer holds a totally Stateful History Struct. A `HiStr` keep a pointer to a specific CircularArray Instance. The `HiStr` has a LIFO Queue which stores updates according to their insertion order.
type AugmentConfigFunc ¶
type AwakenLogger ¶
type AwakenLogger struct {
// contains filtered or unexported fields
}
AwakenLogger is a zerolog logger that outputs trace logs as info
func NewAwakenLogger ¶
func NewAwakenLogger(d time.Duration) AwakenLogger
NewAwakenLogger creates a new AwakenLogger.
func (*AwakenLogger) Trace ¶
func (t *AwakenLogger) Trace() *zerolog.Event
Trace logs a trace message.
func (*AwakenLogger) WakeUp ¶
func (t *AwakenLogger) WakeUp()
WakeUp gets the AwakenLogger out of its dormant state for a an amount of time.
type BalancesStrategy ¶
type BalancesStrategy struct {
// contains filtered or unexported fields
}
BalancesStrategy struct maps exchange names as keys to their respective exchange holdings as values. Using this strategy, we subscribe to a user defined number of tickers and use those to update our holdings. We then atomically update the exchange holding map in our balance strategy struct, and we can read an `ExchangeHoldings` object at any point. Note that this strategy does not order, so stops and take profits can't be engaged. To use it, initialize an exchange and a builder and then simply
func (*BalancesStrategy) Deinit ¶
func (b *BalancesStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
Deinit should be called when the bot is shutting down or closing functions given by the exchange's API interface.It is used to stop the ticker.
func (*BalancesStrategy) ExchangeHoldings ¶
func (b *BalancesStrategy) ExchangeHoldings(exchangeName string) (*ExchangeHoldings, error)
ExchangeHoldings method returns all the balance from an exchange including all the global account information and information for each asset and account.
func (*BalancesStrategy) Init ¶
func (b *BalancesStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
Init method loads an initial holdings item and then calls the internal tickers Init. This merges well with the LazyHandler holding the last refresh timestamp since the refresh should already be running when this is called.
func (*BalancesStrategy) OnBalanceChange ¶
func (b *BalancesStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
func (*BalancesStrategy) OnFill ¶
func (b *BalancesStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
func (*BalancesStrategy) OnFunding ¶
func (b *BalancesStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
OnFunding method is not being used because the backtest loads directly from a saved ledger
func (*BalancesStrategy) OnKline ¶
func (b *BalancesStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
OnKline is called when a new kline is received.
func (*BalancesStrategy) OnModify ¶
func (b *BalancesStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
func (*BalancesStrategy) OnOrder ¶
func (b *BalancesStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
func (*BalancesStrategy) OnOrderBook ¶
func (b *BalancesStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
func (*BalancesStrategy) OnPrice ¶
func (b *BalancesStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
OnPrice method is called every time a new price is received from the exchange.
func (*BalancesStrategy) OnTrade ¶
func (b *BalancesStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
func (*BalancesStrategy) OnUnrecognized ¶
func (b *BalancesStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder struct holds state. In this case it specifically has a definition function Augment(). It also stores internal values such as the path the configs will be read from, the closures/recipe function it will use while conditioning config values. Our Augment() will run before the Build() code is called. In this case, the config itself may have been read from a filepath. In this case, our function augments with a value from the dealerBuilder struct/obj. That function is then run, and various further functions that had been defined for this. Finally, if a file wasn't found, one of the directives within our builder will be constructed a new default template as an alternative to the expected input not found (the expected input "initial")
func NewBuilder ¶
func NewBuilder() *Builder
NewBuilder returns a new or configured keep builder NewBuilder function is used to build the Dealer object. When we call `dealer, err := builder.build()` we get a *dealer and an error back.
func (*Builder) Augment ¶
func (b *Builder) Augment(f AugmentConfigFunc) *Builder
Augment augments the exposed functions of the generated service interface, change this to modify the exposed service definition Augment function, which you can change, compiles any code in the go code in this environment upon running application.
func (*Builder) Balances ¶
Balances function will set the refresh interval to fetch balances which in our could be 10 seconds for example. This interval will determine how often the bot will make an API call for fetching latest prices. My assumption is that it's done 10 seconds to minimize amount of data fetched in-between trades to reduce fees.
func (Builder) Build ¶
Build function is used to build the dealer object. When we call `dealer, err := builder.build()` we get a *dealer and an error back.
func (*Builder) CustomExchange ¶
func (b *Builder) CustomExchange(name string, f ExchangeFactory) *Builder
CustomExchange function exports a variable called "CustomExchange", which will be registered in each pair's "ExchangeCreatorFunc". Via *Builder's CustomExchange function we can insert a custom Exchange Creator. Since the name is the only customization we have with this builder, we have to have a factory interface which can instantiate ExchangeCreatorFunc.
type CircularArray ¶
type CircularArray struct { Offset int // contains filtered or unexported fields }
CircularArray is initialized with the "width" of the array.
func NewCircularArray ¶
func NewCircularArray(n int) CircularArray
NewCircularArray function creates a new circular buffer of a defined size of capacity. The Len function returns the length of the buffer which is the same as the number of observations in a specific window.
func (*CircularArray) At ¶
func (a *CircularArray) At(index int) interface{}
At function returns the n-th element which can be indexed by the external `index` argument. To map this external 0-based index to the underlying 0-based index of the slice, we call a helper method `Index` which will return a wrapped index. Assuming a CircularArray of 100 elements, a call to `At(99)` with a wrapping index of 96 will return the 96th element of the array, wrapped completely around the array as considered as a circle.
func (*CircularArray) Floats ¶
func (a *CircularArray) Floats() []float64
Floats converts each element in the underlying slice to a floating point number.
func (*CircularArray) Index ¶
func (a *CircularArray) Index(i int) int
Index maps an external 0-based index to the corresponding internal index.
func (*CircularArray) Last ¶
func (a *CircularArray) Last() interface{}
Last returns the last element of the underlying slice.
func (*CircularArray) LastFloat ¶
func (a *CircularArray) LastFloat() float64
LastFloat function returns the last element in the underlying slice cast to a floating point number
func (*CircularArray) LastIndex ¶
func (a *CircularArray) LastIndex() int
The LastIndex function returns int value. If the values are all inside of uint values (whose maximum value is (1 << 31) - 1) the must value of offset, which is returned by lastIndex function, would be (1 << 31) - 1. In normal case, the maximum uint value will be (1 << 32) - 1. Then, lastIndex function returns (1 << 32) - 1.
func (*CircularArray) Len ¶
func (a *CircularArray) Len() int
Len function returns the number of elements currently stored. It returns `len(y)` which extracts the length of the underlying slice.
func (*CircularArray) Push ¶
func (a *CircularArray) Push(x interface{})
type CurrencyBalance ¶
CurrencyBalance struct is an easy way to house the pairs of currency held. struct with our most used currencies. Just with some nice printing methods for the most part.
type Dealer ¶
type Dealer struct { Root RootStrategy Settings engine.Settings Config config.Config ExchangeManager engine.ExchangeManager // contains filtered or unexported fields }
Dealer struct holds state. In this case it specifically has a definition function Augment(). It also stores internal values such as the path the configs will be read from, the closures/recipe function it will use while conditioning config values. Our Augment() will run before the Build() code is called. In this case, the config itself may have been read from a filepath. In this case, our function augments with a value from the dealerBuilder struct/obj. That function is then run, and various further functions that had been defined for this. Finally, if a file wasn't found, one of the directives within our builder will be constructed a new default template as an alternative to the expected input not found (the expected input "initial"
func (*Dealer) ActivateAsset ¶
ActivateAsset will activate the asset for the given exchange.
func (*Dealer) ActivatePair ¶
ActivatePair will activate the pair for the given exchange.
func (*Dealer) AddHistorian ¶
func (*Dealer) CancelOrder ¶
func (bot *Dealer) CancelOrder(ctx context.Context, exchangeOrName interface{}, x order.Cancel) error
CancelOrder calls to make an Order.Cancel which includes the giving submitted order, the name to the requested submitted order and the current name of Exchange, calls to it to make Order.Cancel, otherwise return error. It returns the waiting for canceled order if successful, otherwise error. Filters the Orders map if the given Order ID exists and deletes its map from it.
func (*Dealer) GetActiveOrders ¶
func (bot *Dealer) GetActiveOrders(ctx context.Context, exchangeOrName interface{}, request order.MultiOrderRequest) ([]order.Detail, error)
GetActiveOrders function is a wrapper around the GetActiveOrders function in the exchange package.
func (*Dealer) GetEnabledPairAssetType ¶
func (bot *Dealer) GetEnabledPairAssetType(e exchange.IBotExchange, c currency.Pair) (asset.Item, error)
GetEnabledPairAssetType function returns a list of enabled asset types for a given exchange.
func (*Dealer) GetExchangeByName ¶
func (bot *Dealer) GetExchangeByName(name string) (exchange.IBotExchange, error)
GetExchangeByName function returns an exchange interface by name.
func (*Dealer) GetExchanges ¶
func (bot *Dealer) GetExchanges() []exchange.IBotExchange
GetExchanges is a wrapper of GCT's Engine.GetExchanges
func (*Dealer) GetOrderValue ¶
func (bot *Dealer) GetOrderValue(exchangeName, orderID string) (OrderValue, bool)
GetOrderValue function retrieves order details from the given bot's store.
func (*Dealer) ModifyOrder ¶
func (bot *Dealer) ModifyOrder(ctx context.Context, exchangeOrName interface{}, mod order.Modify) (order.ModifyResponse, error)
ModifyOrder method calls the SubmitOrder method then Contains method to check for an exchange name in xs slice. If contains is true, you will return an error since an exchange was reported. If contains is false, you will continue with the execution of the function. CreateOrder method will not be executed if Contains method returns an error.
func (*Dealer) OnOrder ¶
func (bot *Dealer) OnOrder(e exchange.IBotExchange, x order.Detail)
OnOrder function calls the GetOrderValue method to see if an order exists with that dealer. We have a GetValue method in the handler file. We modify the obtained value by setting its UserData to the OnFilled Observer required to perform the appropriate strategy. In n our instance, our order may include two methods. One provides us with a transaction, while the other provides us with profit and loss information (P&L). When we get an order, we set the User data to OnFilledObserver using the Value property and leave the handler code. Within the Handler. OnFilled, we check two criteria to verify whether they are present in Value in order to optimize the strategy's execution.
func (*Dealer) ReportEvent ¶
ReportEvent will report an event to the metrics server.
func (*Dealer) ReportLatency ¶
ReportLatency will report the latency of the bot to the metrics server.
func (*Dealer) ReportValue ¶
ReportValue will report a value to the metrics server
func (*Dealer) Run ¶
Run is the entry point of all exchange data streams. Strategy.On*() events for a single exchange are invoked from the same thread. Thus, if a strategy deals with multiple exchanges simultaneously, there may be race conditions.
func (*Dealer) SubmitOrder ¶
func (bot *Dealer) SubmitOrder(ctx context.Context, exchangeOrName interface{}, submit order.Submit) (*order.SubmitResponse, error)
SubmitOrder function, simply makes an Order.Submit which contains the giving parameters and the current name of requested Exchange Submit it to the giving requested Exchange, called at the user orders code. It returns the order map response if successful, otherwise error.
func (*Dealer) SubmitOrderUD ¶
func (bot *Dealer) SubmitOrderUD(ctx context.Context, exchangeOrName interface{}, submit order.Submit, userData interface{}) (*order.SubmitResponse, error)
SubmitOrderUD is similar to the SubmitOrder, except that this function also adds the order map into the Orders map and its corresponding ID and name and then return it and its error and additional notes and errors which cause the metric to move asynchronous processing.
func (*Dealer) SubmitOrders ¶
func (bot *Dealer) SubmitOrders(ctx context.Context, e exchange.IBotExchange, xs ...order.Submit) error
SubmitOrders method calls the SubmitOrder method then Contains method to check for an exchage name in xs slice. If contains is true, you will return an error since an exchange was reported. If contains is false, you will continue with the execution of the function. ListOrder method will not be executed if Contains method returns an error.
type ExchangeFactory ¶
type ExchangeFactory interface {
NewExchangeByName(name string) (exchange.IBotExchange, error)
}
ExchangeFactory defines an interface for creating exchange instances. It abstracts the instantiation process, allowing for flexible and dynamic creation of different exchanges based on a given name.
type ExchangeHoldings ¶
type ExchangeHoldings struct {
Accounts map[string]SubAccount
}
ExchangeHoldings struct is a struct where we house a map[string]SubAccount. For accounts, we basically house all our accounts now as a string as they are all now connected to gct now as a linked service. To make them easier to reference.
func Holdings ¶
func Holdings(d *Dealer, exchangeName string) (*ExchangeHoldings, error)
Holdings function finds the exchanges balances strategy, then does two things: Looks for an exchange by its name in the holdings map. Returns the holding for the exchange if it's in the map.
func NewExchangeHoldings ¶
func NewExchangeHoldings() *ExchangeHoldings
NewExchangeHoldings function is an easy way to create an empty ExchangeHoldings struct, so we can create an empty struct on startup to avoid us facing gct/goat by ensuring state on startup
func (*ExchangeHoldings) CurrencyBalance ¶
func (h *ExchangeHoldings) CurrencyBalance(accountID string, asset asset.Item, code currency.Code) (CurrencyBalance, error)
CurrencyBalance method is an easy way to get the total value of a currency held.
type GCTConsoleWriter ¶
type GCTConsoleWriter struct{}
GCTConsoleWriter is a zerolog writer that outputs to the console.
type Historian ¶
type Historian struct {
// contains filtered or unexported fields
}
Historian struct creates an array that is responsible for storing data. The event this struct executes is `OnOrder`, that appends to the array the order. the interval is `OnOrder` is optional; since it returns once every interval epoch is an attribute of the struct, its mutability allows us to isolate the state quirks. The `state` itself is an interface that allows us to replace with different arrays
func NewHistorian ¶
NewHistorian function above returns a pointer to golang native type Historian, NOT a reference to it. This, in turn, returns a pointer to golang native type CircularArray, NOT a reference to a new instance of a CircularArray.
func (*Historian) Floats ¶
Floats returns the underlying array, but cast to []float64, for easy sorting/graphing, without any modifications.
func (*Historian) Push ¶
func (u *Historian) Push(x interface{})
Push is called once per update, so it is guaranteed to be executed once per interval. The push function not update the state of the historian
type HistoryStrategy ¶
type HistoryStrategy struct {
// contains filtered or unexported fields
}
HistoryStrategy struct is to reduce the amount of data processed by the bot. The idea is to gather the required data points (e.g. OHLCV) and store them in `Historian` units (see `NewHistorian` above) instead of asking exchanges to provide the data directly.
func NewHistoryStrategy ¶
func NewHistoryStrategy() HistoryStrategy
NewHistoryStrategy defines Two maps, one for the History event on the Price field, and one for the Order event.
func (*HistoryStrategy) AddHistorian ¶
func (r *HistoryStrategy) AddHistorian(exchangeName, eventName string, interval time.Duration, stateLength int, f func(array Array)) error
AddHistorian function is called at exchange initialization. First, it creates internal data structures necessary for the history to work. AddHistorian function is very useful when you expect the same event to be triggered constantly over a certain time interval. `onPriceUnits` member is a map of arrays of historians. Each array contains exactly one historian, since every history strategy needs to be attached to a single exchange. `onOrderUnits` member is a map of arrays of historians. Each array contains exactly one historian, since every history strategy needs to be attached to a single exchange.
func (*HistoryStrategy) BindOnPrice ¶
func (r *HistoryStrategy) BindOnPrice(unit *Historian)
func (*HistoryStrategy) Deinit ¶
func (r *HistoryStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
func (*HistoryStrategy) Init ¶
func (r *HistoryStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
Init function of the HistoryStrategy registers the onPriceUnits, onOrderUnits, onPriceUnitsPerCurrency, onOrderUnitsPerCurrency collectors.
func (*HistoryStrategy) OnBalanceChange ¶
func (r *HistoryStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
func (*HistoryStrategy) OnFill ¶
func (r *HistoryStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
func (*HistoryStrategy) OnFunding ¶
func (r *HistoryStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
func (*HistoryStrategy) OnKline ¶
func (r *HistoryStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
func (*HistoryStrategy) OnModify ¶
func (r *HistoryStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
func (*HistoryStrategy) OnOrder ¶
func (r *HistoryStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
func (*HistoryStrategy) OnOrderBook ¶
func (r *HistoryStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
func (*HistoryStrategy) OnPrice ¶
func (r *HistoryStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
func (*HistoryStrategy) OnTrade ¶
func (r *HistoryStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
func (*HistoryStrategy) OnUnrecognized ¶
func (r *HistoryStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
type LogState ¶
type LogState struct {
// contains filtered or unexported fields
}
LogState keeps track of what the current state is.
func NewLogState ¶
NewLogState creates a new LogState.
type Metric ¶
type Metric int
const ( // SubmitOrderMetric Submit order metrics. SubmitOrderMetric Metric = iota SubmitOrderLatencyMetric SubmitOrderErrorMetric // SubmitBulkOrderMetric Submit bulk orders metrics. SubmitBulkOrderMetric SubmitBulkOrderLatencyMetric // ModifyOrderMetric Modify order metrics. ModifyOrderMetric ModifyOrderLatencyMetric ModifyOrderErrorMetric // CancelOrderMetric Cancel order metrics. CancelOrderMetric CancelOrderLatencyMetric CancelOrderErrorMetric // CancelAllOrdersMetric Cancel all orders metrics. CancelAllOrdersMetric CancelAllOrdersLatencyMetric CancelAllOrdersErrorMetric // GetActiveOrdersMetric Get Active orders metrics. GetActiveOrdersMetric GetActiveOrdersLatencyMetric GetActiveOrdersErrorMetric // MaxMetrics this should always be the last one. MaxMetrics )
type OnFilledObserver ¶
type OnFilledObserver interface {
OnFilled(d *Dealer, e exchange.IBotExchange, orderDetail order.Detail)
}
OnFilledObserver is an interface that responds to each placed order by the dealer. The OnFilled method is expected to perform operations when a trade order is filled.
type OrderKey ¶
OrderKey struct implements the `Key` interface of the sync.Map, which used for type assertion of the key
type OrderRegistry ¶
type OrderRegistry struct {
// contains filtered or unexported fields
}
OrderRegistry struct that stores two things: The amount of orders in it and the key. It has a single `int` property that represents the amount of orders currently in the registry. The `int` property is an atomic.Int, which is part of the golang's atomic package. It contains the modification of this `int`property that happens at the same time. The modification of an int cannot happen at two places in code in parallel. This provides a safe way to get or update integers from multiple routines, or from goroutines. In this case it’s the inner length field.
func NewOrderRegistry ¶
func NewOrderRegistry() *OrderRegistry
NewOrderRegistry constructs a new OrderRegistry. The function initializes the field atomic.Int32 called length with 0 this means your r.length is incremented after every call of this function.
func (*OrderRegistry) GetOrderValue ¶
func (r *OrderRegistry) GetOrderValue(exchangeName, orderID string) (OrderValue, bool)
GetOrderValue initially verifies that the exchange name and order ID exist in the OrderRegistry. This results in the `want`, and `ok` variables and assignment then return if that's the case. If it's not, then it's safe for r.values. LoadOrStore to return a "new" order value. It will create a new OrderValue with the input `UserData` and then load the `SubmitResponse` from the `DecodedUpdates` channel. If that should fail, its logged
func (*OrderRegistry) Length ¶
func (r *OrderRegistry) Length() int
func (*OrderRegistry) Store ¶
func (r *OrderRegistry) Store(exchangeName string, response order.SubmitResponse, userData interface{}) bool
Store stores the global order data to the `OrderRegistry`. The code looks like it should just wrap structs around another struct, that is not the case. First, it checks if an order with the same exchange name and order ID already exist, if not the order value will be stored in the `OrderRegistry` and `returned` will `true`. Secondly, the `loaded` argument is returned. This `loaded` argument is needed to see if the order has already been added to the `OrderRegistry` and therefore we need to run the code again.
type OrderValue ¶
type OrderValue struct { SubmitResponse order.SubmitResponse UserData interface{} }
OrderValue struct holds two fields, which are both stored under the `OrderValue` struct. The first field is the `SubmitResponse` which comes from `Submit` function. It's the response returned from the webserver of each exchange. It includes data like whether or not the order is placed, the order ID (in case the order is placed), the creation timestamp, the creation amount (unit), etc. It also contains all exchange-specific error messages under `Error()`.
type Reporter ¶
type Reporter interface { // Event metrics in a single occurrence Event(m Metric, labels ...string) // Latency metrics provide visibility over latencies Latency(m Metric, d time.Duration, labels ...string) // Value metrics provide visibility over arbitrary value Value(m Metric, v float64, labels ...string) }
Reporter interface is implemented by the clients that wish to report their metrics for this library.
type RootStrategy ¶
type RootStrategy struct {
// contains filtered or unexported fields
}
RootStrategy is a struct that contains a map of strategies. The map is a sync.Map, which is a thread safe map. The map is initialized with a sync.Map{} and then we can add strategies to it. The map is a map of string to Strategy. The string is the name of the strategy and the Strategy is the implementation of the strategy.
func NewRootStrategy ¶
func NewRootStrategy() RootStrategy
NewRootStrategy returns the RootStrategy object. The RootStrategy object has several functions (each). creating a RootStrategy variable which is an object. Then we are iterating through each of the additional strategies and adding them to the NewRootStrategy, so they are available as the final implementation is created after they have been created
func (*RootStrategy) Add ¶
func (m *RootStrategy) Add(name string, s Strategy)
Add function takes a string that identifies a implementation of the Strategy, and the implementation of the implementation of the Strategy implementation itself. It stores an implementation of a strategy implementation under a string named after the strategy implementation. Which resolves to the correct implementation of the Strategy.
func (*RootStrategy) Deinit ¶
func (m *RootStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
Deinit deinitializes strategies in a specific Dealer struct For each strategy in a Dealer, calls Strategy.Deinit()
func (*RootStrategy) Delete ¶
func (m *RootStrategy) Delete(name string) (Strategy, error)
Delete the Strategy specified by name. You get an object, get the interface's value, and then determine the interface's value.
func (*RootStrategy) Get ¶
func (m *RootStrategy) Get(name string) (Strategy, error)
Get returns the strategy with the given name
func (*RootStrategy) Init ¶
func (m *RootStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
Init function loops through each of the imported Strategy implementations and calls their init functions to initialize them. Ordering of implementations is important and if an implementation depends on something another requires you should order the strategy implementations.
func (*RootStrategy) OnBalanceChange ¶
func (m *RootStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
OnBalanceChange iterates over each strategy, calling OnBalanceChange, logging an error if any fail Returns nil on success, or Function specific error on failure
func (*RootStrategy) OnFill ¶
func (m *RootStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
func (*RootStrategy) OnFunding ¶
func (m *RootStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
OnFunding function for the Root strategy. The first line of the function is to call the same function on each_ it is the interface method for the Strategy. A new function is called, which is more of an interface for the Strategy called OnFunding. Which allows the user to choose how they want to pass this event to the strategy.
func (*RootStrategy) OnKline ¶
func (m *RootStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
OnKline listens to the Kline stream data events and execute optional action
func (*RootStrategy) OnModify ¶
func (m *RootStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
OnModify is invoked when an order is modified. The arguments passed are the original user message
func (*RootStrategy) OnOrder ¶
func (m *RootStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
OnOrder is called when changes occur to a specific order
func (*RootStrategy) OnOrderBook ¶
func (m *RootStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
OnOrderBook is called when initial orderbook is created or if the bids or asks change Must pass in Dealer that created this strategy. Also pass in the Exchange used by the strategy Call this function once per Strategy
func (*RootStrategy) OnPrice ¶
func (m *RootStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
The OnPrice implementation of the Strategy is different from above. It does not let the user choose how they want to use this information and passes all the information to the specific implementation of that data.
func (*RootStrategy) OnTrade ¶
func (m *RootStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
func (*RootStrategy) OnUnrecognized ¶
func (m *RootStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
OnUnrecognized is called on unrecognized data
type Slots ¶
type Slots struct {
OnFilledSlot func(d *Dealer, e exchange.IBotExchange, orderDetail order.Detail)
}
Slots is a struct that contains an OnFilled function pointer. as the OnFilled method in the OnFilledObserver interface. This allows for customizable behavior when an order gets filled.
type Strategy ¶
type Strategy interface { Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error Deinit(d *Dealer, e exchange.IBotExchange) error }
Strategy is an interface and defines all function needed for a user defined strategy. The RootStrategy provides a way to create and use strategies and action according to given strategies. Strategy interface defines all the functions that must be implemented in order for the strategy to operate correctly. It has "On" functions and a data type that comprises keys and values that may be strings, interfaces, or anything else. While this may seem to be a constraint on the execution of your approach, you may use the OnUnrecognized function to implement anything at an experimental stage.
func NewBalancesStrategy ¶
NewBalancesStrategy function creates an instance of the BalancesStrategy struct. In turn, the BalancesStrategy struct creates a TickFunc method as a `ticker.Ticker.TickFunc` Then assigns that TickFunc function to the TickerStrategy object that is to be used later.
type SubAccount ¶
SubAccount struct is an easy way to group our connected accounts. To hold all connected exchanges.
type TickerStrategy ¶
type TickerStrategy struct { Interval time.Duration TickFunc func(d *Dealer, e exchange.IBotExchange) // contains filtered or unexported fields }
TickerStrategy is a struct that implements the TickerStrategy interface. Interval is the time interval between tickers. TickFunc is a function that returns a ticker. tickers is a map of tickers.
func (*TickerStrategy) Deinit ¶
func (s *TickerStrategy) Deinit(d *Dealer, e exchange.IBotExchange) error
Deinit stops the ticker for the given Exchange.
func (*TickerStrategy) Init ¶
func (s *TickerStrategy) Init(ctx context.Context, d *Dealer, e exchange.IBotExchange) error
Init will call our ticker code on its own. We can easily build a reoccurring ticker using the information in the ExchangeConnections struct by establishing a goroutine runtime. The runtime clock enables us to manage time without the need for a goroutine.
func (*TickerStrategy) OnBalanceChange ¶
func (s *TickerStrategy) OnBalanceChange(d *Dealer, e exchange.IBotExchange, x account.Change) error
OnBalanceChange implements the TickerStrategy interface function. Used to trigger an action for an already running ticker
func (*TickerStrategy) OnFill ¶
func (s *TickerStrategy) OnFill(d *Dealer, e exchange.IBotExchange, x []fill.Data) error
func (*TickerStrategy) OnFunding ¶
func (s *TickerStrategy) OnFunding(d *Dealer, e exchange.IBotExchange, x stream.FundingData) error
OnFunding - entrypoint for the strategy triggered on funding data Called if OnMsgHandlerMsg(Data(fundingData) trigger returns true
func (*TickerStrategy) OnKline ¶
func (s *TickerStrategy) OnKline(d *Dealer, e exchange.IBotExchange, x stream.KlineData) error
OnKline is called when tick data is received
func (*TickerStrategy) OnModify ¶
func (s *TickerStrategy) OnModify(d *Dealer, e exchange.IBotExchange, x order.Modify) error
OnModify updates modify order
func (*TickerStrategy) OnOrder ¶
func (s *TickerStrategy) OnOrder(d *Dealer, e exchange.IBotExchange, x order.Detail) error
OnOrder manipulates the dealers orderbook given a new incoming order x order.Detail is the new order
func (*TickerStrategy) OnOrderBook ¶
func (s *TickerStrategy) OnOrderBook(d *Dealer, e exchange.IBotExchange, x orderbook.Base) error
OnOrderBook is triggered when API receives orderbook update
func (*TickerStrategy) OnPrice ¶
func (s *TickerStrategy) OnPrice(d *Dealer, e exchange.IBotExchange, x ticker.Price) error
OnPrice is called when price announcement or updates are received.
func (*TickerStrategy) OnTrade ¶
func (s *TickerStrategy) OnTrade(d *Dealer, e exchange.IBotExchange, x []trade.Data) error
func (*TickerStrategy) OnUnrecognized ¶
func (s *TickerStrategy) OnUnrecognized(d *Dealer, e exchange.IBotExchange, x interface{}) error
OnUnrecognized is a function that is called when an unsupported data type is given and most likely indicates a parsing error has occurred with Exchanges