mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
commit
57f0888c3c
|
@ -22,4 +22,3 @@ func SaveConfigFile(filename string, v interface{}) error {
|
||||||
|
|
||||||
return ioutil.WriteFile(filename, out, 0644)
|
return ioutil.WriteFile(filename, out, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MovingAverageIndicator struct {
|
type MovingAverageIndicator struct {
|
||||||
store *MarketDataStore
|
store *MarketDataStore
|
||||||
Period int
|
Period int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ func NewMovingAverageIndicator(period int) *MovingAverageIndicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *MovingAverageIndicator) handleUpdate(kline types.KLine) {
|
func (i *MovingAverageIndicator) handleUpdate(kline types.KLine) {
|
||||||
klines, ok := i.store.KLineWindows[ Interval(kline.Interval) ]
|
klines, ok := i.store.KLineWindows[Interval(kline.Interval)]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,13 @@ func (i *MovingAverageIndicator) handleUpdate(kline types.KLine) {
|
||||||
|
|
||||||
type IndicatorValue struct {
|
type IndicatorValue struct {
|
||||||
Value float64
|
Value float64
|
||||||
Time time.Time
|
Time time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateMovingAverage(klines types.KLineWindow, period int) (values []IndicatorValue) {
|
func calculateMovingAverage(klines types.KLineWindow, period int) (values []IndicatorValue) {
|
||||||
for idx := range klines[period:] {
|
for idx := range klines[period:] {
|
||||||
offset := idx + period
|
offset := idx + period
|
||||||
sum := klines[offset - period:offset].ReduceClose()
|
sum := klines[offset-period : offset].ReduceClose()
|
||||||
values = append(values, IndicatorValue{
|
values = append(values, IndicatorValue{
|
||||||
Time: klines[offset].GetEndTime(),
|
Time: klines[offset].GetEndTime(),
|
||||||
Value: math.Round(sum / float64(period)),
|
Value: math.Round(sum / float64(period)),
|
||||||
|
@ -48,16 +48,9 @@ func calculateMovingAverage(klines types.KLineWindow, period int) (values []Indi
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (i *MovingAverageIndicator) SubscribeStore(store *MarketDataStore) {
|
func (i *MovingAverageIndicator) SubscribeStore(store *MarketDataStore) {
|
||||||
i.store = store
|
i.store = store
|
||||||
|
|
||||||
// register kline update callback
|
// register kline update callback
|
||||||
store.OnUpdate(i.handleUpdate)
|
store.OnUpdate(i.handleUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package bbgo
|
package bbgo
|
||||||
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -9,9 +8,7 @@ import (
|
||||||
|
|
||||||
func TestCalculateMovingAverage(t *testing.T) {
|
func TestCalculateMovingAverage(t *testing.T) {
|
||||||
klines := types.KLineWindow{
|
klines := types.KLineWindow{
|
||||||
{
|
{},
|
||||||
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
_ = klines
|
_ = klines
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ type BackTestStream struct {
|
||||||
types.StandardStream
|
types.StandardStream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *BackTestStream) Connect(ctx context.Context) error {
|
func (s *BackTestStream) Connect(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
package bbgo
|
package bbgo
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
package bbgo
|
package bbgo
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package bbgo
|
package bbgo
|
||||||
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -9,5 +8,4 @@ func TestOrderProcessor(t *testing.T) {
|
||||||
processor := &OrderProcessor{}
|
processor := &OrderProcessor{}
|
||||||
_ = processor
|
_ = processor
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
package bbgo
|
package bbgo
|
||||||
|
|
||||||
|
|
|
@ -15,4 +15,3 @@ type NullNotifier struct{}
|
||||||
|
|
||||||
func (n *NullNotifier) Notify(format string, args ...interface{}) {
|
func (n *NullNotifier) Notify(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,23 +61,23 @@ type StockManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Distribution struct {
|
type Distribution struct {
|
||||||
PriceLevels []string `json:"priceLevels"`
|
PriceLevels []string `json:"priceLevels"`
|
||||||
TotalQuantity float64 `json:"totalQuantity"`
|
TotalQuantity float64 `json:"totalQuantity"`
|
||||||
Quantities map[string]float64 `json:"quantities"`
|
Quantities map[string]float64 `json:"quantities"`
|
||||||
Stocks map[string]StockSlice `json:"stocks"`
|
Stocks map[string]StockSlice `json:"stocks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *StockManager) Distribution(level int) *Distribution {
|
func (m *StockManager) Distribution(level int) *Distribution {
|
||||||
var d = Distribution{
|
var d = Distribution{
|
||||||
Quantities: map[string]float64{},
|
Quantities: map[string]float64{},
|
||||||
Stocks: map[string]StockSlice{},
|
Stocks: map[string]StockSlice{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, stock := range m.Stocks {
|
for _, stock := range m.Stocks {
|
||||||
n := math.Ceil(math.Log10(stock.Price))
|
n := math.Ceil(math.Log10(stock.Price))
|
||||||
digits := int(n - math.Max(float64(level), 1.0))
|
digits := int(n - math.Max(float64(level), 1.0))
|
||||||
div := math.Pow10(digits)
|
div := math.Pow10(digits)
|
||||||
priceLevel := math.Floor(stock.Price / div) * div
|
priceLevel := math.Floor(stock.Price/div) * div
|
||||||
key := strconv.FormatFloat(priceLevel, 'f', 2, 64)
|
key := strconv.FormatFloat(priceLevel, 'f', 2, 64)
|
||||||
|
|
||||||
d.TotalQuantity += stock.Quantity
|
d.TotalQuantity += stock.Quantity
|
||||||
|
@ -98,7 +98,6 @@ func (m *StockManager) Distribution(level int) *Distribution {
|
||||||
|
|
||||||
sort.Float64s(priceLevels)
|
sort.Float64s(priceLevels)
|
||||||
|
|
||||||
|
|
||||||
return &d
|
return &d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,16 @@ func TestStockManager(t *testing.T) {
|
||||||
assert.Len(t, stockManager.Stocks, 2)
|
assert.Len(t, stockManager.Stocks, 2)
|
||||||
assert.Equal(t, StockSlice{
|
assert.Equal(t, StockSlice{
|
||||||
{
|
{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Price: 9100.0,
|
Price: 9100.0,
|
||||||
Quantity: 0.05,
|
Quantity: 0.05,
|
||||||
IsBuyer: true,
|
IsBuyer: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Price: 9100.0,
|
Price: 9100.0,
|
||||||
Quantity: 0.04,
|
Quantity: 0.04,
|
||||||
IsBuyer: true,
|
IsBuyer: true,
|
||||||
},
|
},
|
||||||
}, stockManager.Stocks)
|
}, stockManager.Stocks)
|
||||||
assert.Len(t, stockManager.PendingSells, 0)
|
assert.Len(t, stockManager.PendingSells, 0)
|
||||||
|
@ -121,10 +121,10 @@ func TestStockManager(t *testing.T) {
|
||||||
assert.Len(t, stockManager.Stocks, 1)
|
assert.Len(t, stockManager.Stocks, 1)
|
||||||
assert.Equal(t, StockSlice{
|
assert.Equal(t, StockSlice{
|
||||||
{
|
{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Price: 9100.0,
|
Price: 9100.0,
|
||||||
Quantity: 0.02,
|
Quantity: 0.02,
|
||||||
IsBuyer: true,
|
IsBuyer: true,
|
||||||
},
|
},
|
||||||
}, stockManager.Stocks)
|
}, stockManager.Stocks)
|
||||||
assert.Len(t, stockManager.PendingSells, 0)
|
assert.Len(t, stockManager.PendingSells, 0)
|
||||||
|
@ -146,10 +146,10 @@ func TestStockManager(t *testing.T) {
|
||||||
assert.Len(t, stockManager.Stocks, 1)
|
assert.Len(t, stockManager.Stocks, 1)
|
||||||
assert.Equal(t, StockSlice{
|
assert.Equal(t, StockSlice{
|
||||||
{
|
{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Price: 9100.0,
|
Price: 9100.0,
|
||||||
Quantity: 0.03,
|
Quantity: 0.03,
|
||||||
IsBuyer: true,
|
IsBuyer: true,
|
||||||
},
|
},
|
||||||
}, stockManager.Stocks)
|
}, stockManager.Stocks)
|
||||||
assert.Len(t, stockManager.PendingSells, 0)
|
assert.Len(t, stockManager.PendingSells, 0)
|
||||||
|
@ -172,10 +172,10 @@ func TestStockManager(t *testing.T) {
|
||||||
assert.Len(t, stockManager.PendingSells, 1)
|
assert.Len(t, stockManager.PendingSells, 1)
|
||||||
assert.Equal(t, StockSlice{
|
assert.Equal(t, StockSlice{
|
||||||
{
|
{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Price: 9200.0,
|
Price: 9200.0,
|
||||||
Quantity: 0.05,
|
Quantity: 0.05,
|
||||||
IsBuyer: false,
|
IsBuyer: false,
|
||||||
},
|
},
|
||||||
}, stockManager.PendingSells)
|
}, stockManager.PendingSells)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
|
|
|
@ -249,15 +249,15 @@ func ParseEvent(message string) (interface{}, error) {
|
||||||
|
|
||||||
type DepthEntry struct {
|
type DepthEntry struct {
|
||||||
PriceLevel string
|
PriceLevel string
|
||||||
Quantity string
|
Quantity string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DepthEvent struct {
|
type DepthEvent struct {
|
||||||
EventBase
|
EventBase
|
||||||
|
|
||||||
Symbol string `json:"s"`
|
Symbol string `json:"s"`
|
||||||
FirstUpdateID int64 `json:"U"`
|
FirstUpdateID int64 `json:"U"`
|
||||||
FinalUpdateID int64 `json:"u"`
|
FinalUpdateID int64 `json:"u"`
|
||||||
|
|
||||||
Bids []DepthEntry
|
Bids []DepthEntry
|
||||||
Asks []DepthEntry
|
Asks []DepthEntry
|
||||||
|
@ -319,7 +319,7 @@ func parseDepthEntry(val *fastjson.Value) (*DepthEntry, error) {
|
||||||
|
|
||||||
return &DepthEntry{
|
return &DepthEntry{
|
||||||
PriceLevel: string(arr[0].GetStringBytes()),
|
PriceLevel: string(arr[0].GetStringBytes()),
|
||||||
Quantity: string(arr[1].GetStringBytes()),
|
Quantity: string(arr[1].GetStringBytes()),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ func parseDepthEvent(val *fastjson.Value) (*DepthEvent, error) {
|
||||||
Event: string(val.GetStringBytes("e")),
|
Event: string(val.GetStringBytes("e")),
|
||||||
Time: val.GetInt64("E"),
|
Time: val.GetInt64("E"),
|
||||||
},
|
},
|
||||||
Symbol: string(val.GetStringBytes("s")),
|
Symbol: string(val.GetStringBytes("s")),
|
||||||
FirstUpdateID: val.GetInt64("U"),
|
FirstUpdateID: val.GetInt64("U"),
|
||||||
FinalUpdateID: val.GetInt64("u"),
|
FinalUpdateID: val.GetInt64("u"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,15 @@ const (
|
||||||
Closed
|
Closed
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type OrderState string
|
type OrderState string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OrderStateDone = OrderState("done")
|
OrderStateDone = OrderState("done")
|
||||||
OrderStateCancel = OrderState("cancel")
|
OrderStateCancel = OrderState("cancel")
|
||||||
OrderStateWait = OrderState("wait")
|
OrderStateWait = OrderState("wait")
|
||||||
OrderStateConvert = OrderState("convert")
|
OrderStateConvert = OrderState("convert")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type OrderType string
|
type OrderType string
|
||||||
|
|
||||||
// Order types that the API can return.
|
// Order types that the API can return.
|
||||||
|
|
|
@ -88,7 +88,7 @@ type RestClient struct {
|
||||||
AccountService *AccountService
|
AccountService *AccountService
|
||||||
PublicService *PublicService
|
PublicService *PublicService
|
||||||
TradeService *TradeService
|
TradeService *TradeService
|
||||||
OrderService *OrderService
|
OrderService *OrderService
|
||||||
// OrderBookService *OrderBookService
|
// OrderBookService *OrderBookService
|
||||||
// MaxTokenService *MaxTokenService
|
// MaxTokenService *MaxTokenService
|
||||||
// MaxKLineService *KLineService
|
// MaxKLineService *KLineService
|
||||||
|
@ -212,7 +212,6 @@ func (c *RestClient) newAuthenticatedRequest(m string, refURL string, data inter
|
||||||
return nil, errors.New("empty api secret")
|
return nil, errors.New("empty api secret")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
req, err := c.newRequest(m, refURL, nil, p)
|
req, err := c.newRequest(m, refURL, nil, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -7,16 +7,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MarkerInfo struct {
|
type MarkerInfo struct {
|
||||||
Fee string `json:"fee"`
|
Fee string `json:"fee"`
|
||||||
FeeCurrency string `json:"fee_currency"`
|
FeeCurrency string `json:"fee_currency"`
|
||||||
OrderID int `json:"order_id"`
|
OrderID int `json:"order_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TradeInfo struct {
|
type TradeInfo struct {
|
||||||
// Maker tells you the maker trade side
|
// Maker tells you the maker trade side
|
||||||
Maker string `json:"maker,omitempty"`
|
Maker string `json:"maker,omitempty"`
|
||||||
Bid *MarkerInfo `json:"bid,omitempty"`
|
Bid *MarkerInfo `json:"bid,omitempty"`
|
||||||
Ask *MarkerInfo `json:"ask,omitempty"`
|
Ask *MarkerInfo `json:"ask,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trade represents one returned trade on the max platform.
|
// Trade represents one returned trade on the max platform.
|
||||||
|
|
|
@ -180,8 +180,8 @@ func (m *BalanceMessage) Balance() (*types.Balance, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.Balance{
|
return &types.Balance{
|
||||||
Currency: m.Currency,
|
Currency: m.Currency,
|
||||||
Locked: locked,
|
Locked: locked,
|
||||||
Available: available,
|
Available: available,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,13 +54,13 @@ type WebSocketService struct {
|
||||||
errorEventCallbacks []func(e ErrorEvent)
|
errorEventCallbacks []func(e ErrorEvent)
|
||||||
subscriptionEventCallbacks []func(e SubscriptionEvent)
|
subscriptionEventCallbacks []func(e SubscriptionEvent)
|
||||||
|
|
||||||
tradeUpdateEventCallbacks []func(e TradeUpdateEvent)
|
tradeUpdateEventCallbacks []func(e TradeUpdateEvent)
|
||||||
tradeSnapshotEventCallbacks []func(e TradeSnapshotEvent)
|
tradeSnapshotEventCallbacks []func(e TradeSnapshotEvent)
|
||||||
orderUpdateEventCallbacks []func(e OrderUpdateEvent)
|
orderUpdateEventCallbacks []func(e OrderUpdateEvent)
|
||||||
orderSnapshotEventCallbacks []func(e OrderSnapshotEvent)
|
orderSnapshotEventCallbacks []func(e OrderSnapshotEvent)
|
||||||
|
|
||||||
accountSnapshotEventCallbacks []func(e AccountSnapshotEvent)
|
accountSnapshotEventCallbacks []func(e AccountSnapshotEvent)
|
||||||
accountUpdateEventCallbacks []func(e AccountUpdateEvent)
|
accountUpdateEventCallbacks []func(e AccountUpdateEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWebSocketService(wsURL string, key, secret string) *WebSocketService {
|
func NewWebSocketService(wsURL string, key, secret string) *WebSocketService {
|
||||||
|
|
|
@ -71,7 +71,6 @@ func NewStream(key, secret string) *Stream {
|
||||||
stream.EmitBalanceUpdate(snapshot)
|
stream.EmitBalanceUpdate(snapshot)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TradeSync struct {
|
type TradeSync struct {
|
||||||
Service *TradeService
|
Service *TradeService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TradeSync) Sync(ctx context.Context, exchange types.Exchange, symbol string, startTime time.Time) error {
|
func (s *TradeSync) Sync(ctx context.Context, exchange types.Exchange, symbol string, startTime time.Time) error {
|
||||||
|
@ -83,7 +83,7 @@ func (s *TradeService) QueryLast(symbol string) (*types.Trade, error) {
|
||||||
|
|
||||||
func (s *TradeService) QueryForTradingFeeCurrency(symbol string, feeCurrency string) ([]types.Trade, error) {
|
func (s *TradeService) QueryForTradingFeeCurrency(symbol string, feeCurrency string) ([]types.Trade, error) {
|
||||||
rows, err := s.DB.NamedQuery(`SELECT * FROM trades WHERE symbol = :symbol OR fee_currency = :fee_currency ORDER BY traded_at ASC`, map[string]interface{}{
|
rows, err := s.DB.NamedQuery(`SELECT * FROM trades WHERE symbol = :symbol OR fee_currency = :fee_currency ORDER BY traded_at ASC`, map[string]interface{}{
|
||||||
"symbol": symbol,
|
"symbol": symbol,
|
||||||
"fee_currency": feeCurrency,
|
"fee_currency": feeCurrency,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -108,7 +108,7 @@ func (s *TradeService) Query(symbol string) ([]types.Trade, error) {
|
||||||
return s.scanRows(rows)
|
return s.scanRows(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TradeService) scanRows(rows *sqlx.Rows) (trades []types.Trade, err error) {
|
func (s *TradeService) scanRows(rows *sqlx.Rows) (trades []types.Trade, err error) {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var trade types.Trade
|
var trade types.Trade
|
||||||
if err := rows.StructScan(&trade); err != nil {
|
if err := rows.StructScan(&trade); err != nil {
|
||||||
|
@ -121,8 +121,6 @@ func (s *TradeService) scanRows(rows *sqlx.Rows) (trades []types.Trade, err err
|
||||||
return trades, rows.Err()
|
return trades, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (s *TradeService) Insert(trade types.Trade) error {
|
func (s *TradeService) Insert(trade types.Trade) error {
|
||||||
_, err := s.DB.NamedExec(`
|
_, err := s.DB.NamedExec(`
|
||||||
INSERT INTO trades (id, exchange, symbol, price, quantity, quote_quantity, side, is_buyer, is_maker, fee, fee_currency, traded_at)
|
INSERT INTO trades (id, exchange, symbol, price, quantity, quote_quantity, side, is_buyer, is_maker, fee, fee_currency, traded_at)
|
||||||
|
|
|
@ -26,7 +26,6 @@ func (c Chan) Drain(duration, deadline time.Duration) (cnt int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (c Chan) Emit() {
|
func (c Chan) Emit() {
|
||||||
select {
|
select {
|
||||||
case c <- struct{}{}:
|
case c <- struct{}{}:
|
||||||
|
|
|
@ -17,7 +17,7 @@ type LogHook struct {
|
||||||
func NewLogHook(token string, channel string) *LogHook {
|
func NewLogHook(token string, channel string) *LogHook {
|
||||||
var client = slack.New(token)
|
var client = slack.New(token)
|
||||||
return &LogHook{
|
return &LogHook{
|
||||||
Slack: client,
|
Slack: client,
|
||||||
ErrorChannel: channel,
|
ErrorChannel: channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ func (t *LogHook) Fire(e *logrus.Entry) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
slackAttachments = append(slackAttachments, slack.Attachment{
|
slackAttachments = append(slackAttachments, slack.Attachment{
|
||||||
Color: color,
|
Color: color,
|
||||||
Title: strings.ToUpper(e.Level.String()),
|
Title: strings.ToUpper(e.Level.String()),
|
||||||
Fields: fields,
|
Fields: fields,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -11,5 +11,3 @@ func TrendIcon(trend int) string {
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
type Balance struct {
|
type Balance struct {
|
||||||
Currency string `json:"currency"`
|
Currency string `json:"currency"`
|
||||||
Available float64 `json:"available"`
|
Available float64 `json:"available"`
|
||||||
Locked float64 `json:"locked"`
|
Locked float64 `json:"locked"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BalanceMap map[string]Balance
|
type BalanceMap map[string]Balance
|
||||||
|
@ -11,8 +11,8 @@ type BalanceMap map[string]Balance
|
||||||
type Account struct {
|
type Account struct {
|
||||||
MakerCommission int64
|
MakerCommission int64
|
||||||
TakerCommission int64
|
TakerCommission int64
|
||||||
AccountType string
|
AccountType string
|
||||||
Balances map[string]Balance
|
Balances map[string]Balance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) UpdateBalance(b Balance) {
|
func (a *Account) UpdateBalance(b Balance) {
|
||||||
|
|
|
@ -2,4 +2,3 @@ package types
|
||||||
|
|
||||||
const Green = "#228B22"
|
const Green = "#228B22"
|
||||||
const Red = "#800000"
|
const Red = "#800000"
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,3 @@ import "github.com/leekchan/accounting"
|
||||||
var USD = accounting.Accounting{Symbol: "$ ", Precision: 2}
|
var USD = accounting.Accounting{Symbol: "$ ", Precision: 2}
|
||||||
var BTC = accounting.Accounting{Symbol: "BTC ", Precision: 2}
|
var BTC = accounting.Accounting{Symbol: "BTC ", Precision: 2}
|
||||||
var BNB = accounting.Accounting{Symbol: "BNB ", Precision: 4}
|
var BNB = accounting.Accounting{Symbol: "BNB ", Precision: 4}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
|
|
||||||
func TestKLineWindow_Tail(t *testing.T) {
|
func TestKLineWindow_Tail(t *testing.T) {
|
||||||
var win = KLineWindow{
|
var win = KLineWindow{
|
||||||
{ Open: 11600.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
{Open: 11600.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
||||||
{ Open: 11600.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
{Open: 11600.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
||||||
}
|
}
|
||||||
|
|
||||||
var win2 = win.Tail(1)
|
var win2 = win.Tail(1)
|
||||||
|
@ -24,10 +24,10 @@ func TestKLineWindow_Tail(t *testing.T) {
|
||||||
|
|
||||||
func TestKLineWindow_Truncate(t *testing.T) {
|
func TestKLineWindow_Truncate(t *testing.T) {
|
||||||
var win = KLineWindow{
|
var win = KLineWindow{
|
||||||
{ Open: 11600.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
{Open: 11600.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
||||||
{ Open: 11601.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
{Open: 11601.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
||||||
{ Open: 11602.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
{Open: 11602.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
||||||
{ Open: 11603.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
{Open: 11603.0, Close: 11600.0, High: 11600.0, Low: 11600.0},
|
||||||
}
|
}
|
||||||
|
|
||||||
win.Truncate(5)
|
win.Truncate(5)
|
||||||
|
@ -38,7 +38,6 @@ func TestKLineWindow_Truncate(t *testing.T) {
|
||||||
assert.Len(t, win, 3)
|
assert.Len(t, win, 3)
|
||||||
assert.Equal(t, 11603.0, win.Last().Open)
|
assert.Equal(t, 11603.0, win.Last().Open)
|
||||||
|
|
||||||
|
|
||||||
win.Truncate(1)
|
win.Truncate(1)
|
||||||
assert.Len(t, win, 1)
|
assert.Len(t, win, 1)
|
||||||
assert.Equal(t, 11603.0, win.Last().Open)
|
assert.Equal(t, 11603.0, win.Last().Open)
|
||||||
|
|
|
@ -238,5 +238,3 @@ func (sb *StreamOrderBook) BindStream(stream Stream) {
|
||||||
sb.C.Emit()
|
sb.C.Emit()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ var BookChannel = Channel("book")
|
||||||
|
|
||||||
var KLineChannel = Channel("kline")
|
var KLineChannel = Channel("kline")
|
||||||
|
|
||||||
|
|
||||||
//go:generate callbackgen -type StandardStream -interface
|
//go:generate callbackgen -type StandardStream -interface
|
||||||
type StandardStream struct {
|
type StandardStream struct {
|
||||||
Subscriptions []Subscription
|
Subscriptions []Subscription
|
||||||
|
|
|
@ -40,13 +40,13 @@ func (trade Trade) SlackAttachment() slack.Attachment {
|
||||||
market, ok := FindMarket(trade.Symbol)
|
market, ok := FindMarket(trade.Symbol)
|
||||||
if !ok {
|
if !ok {
|
||||||
return slack.Attachment{
|
return slack.Attachment{
|
||||||
Text: fmt.Sprintf("*%s* Trade %s", trade.Symbol, trade.Side),
|
Text: fmt.Sprintf("*%s* Trade %s", trade.Symbol, trade.Side),
|
||||||
Color: color,
|
Color: color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return slack.Attachment{
|
return slack.Attachment{
|
||||||
Text: fmt.Sprintf("*%s* Trade %s", trade.Symbol, trade.Side),
|
Text: fmt.Sprintf("*%s* Trade %s", trade.Symbol, trade.Side),
|
||||||
Color: color,
|
Color: color,
|
||||||
// Pretext: "",
|
// Pretext: "",
|
||||||
// Text: "",
|
// Text: "",
|
||||||
|
|
|
@ -30,7 +30,6 @@ func ParseFloat(s string) (float64, error) {
|
||||||
return strconv.ParseFloat(s, 64)
|
return strconv.ParseFloat(s, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func MustParseFloat(s string) float64 {
|
func MustParseFloat(s string) float64 {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return 0.0
|
return 0.0
|
||||||
|
@ -52,4 +51,3 @@ func Zero(v float64) bool {
|
||||||
func NotZero(v float64) bool {
|
func NotZero(v float64) bool {
|
||||||
return math.Abs(v) > epsilon
|
return math.Abs(v) > epsilon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,4 +20,3 @@ func Render(tpl string, args interface{}) string {
|
||||||
}
|
}
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,4 +41,3 @@ func (i *VolatileMemory) IsTextFresh(text string, ttl time.Duration) bool {
|
||||||
i.textTimes[text] = now
|
i.textTimes[text] = now
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user