pkg/core: add currency converter

This commit is contained in:
edwin 2024-08-23 17:05:52 +08:00
parent b683550f44
commit 4fefbaf0e7
3 changed files with 198 additions and 1 deletions

View File

@ -0,0 +1,68 @@
package core
import (
"errors"
"github.com/c9s/bbgo/pkg/types"
)
type CurrencyConverter struct {
FromCurrency string `json:"from"`
ToCurrency string `json:"to"`
}
func NewCurrencyConverter(fromSymbol, toSymbol string) *CurrencyConverter {
return &CurrencyConverter{FromCurrency: fromSymbol, ToCurrency: toSymbol}
}
func (c *CurrencyConverter) Initialize() error {
if c.FromCurrency == "" {
return errors.New("FromCurrency can not be empty")
}
if c.ToCurrency == "" {
return errors.New("ToCurrency can not be empty")
}
return nil
}
func (c *CurrencyConverter) ConvertOrder(order types.Order) (types.Order, error) {
if order.SubmitOrder.Market.QuoteCurrency == c.FromCurrency {
order.SubmitOrder.Market.QuoteCurrency = c.ToCurrency
}
if order.SubmitOrder.Market.BaseCurrency == c.FromCurrency {
order.SubmitOrder.Market.BaseCurrency = c.ToCurrency
}
return order, nil
}
func (c *CurrencyConverter) ConvertTrade(trade types.Trade) (types.Trade, error) {
if trade.FeeCurrency == c.FromCurrency {
trade.FeeCurrency = c.ToCurrency
}
return trade, nil
}
func (c *CurrencyConverter) ConvertKLine(kline types.KLine) (types.KLine, error) {
return kline, nil
}
func (c *CurrencyConverter) ConvertMarket(mkt types.Market) (types.Market, error) {
if mkt.QuoteCurrency == c.FromCurrency {
mkt.QuoteCurrency = c.ToCurrency
}
if mkt.BaseCurrency == c.FromCurrency {
mkt.BaseCurrency = c.ToCurrency
}
return mkt, nil
}
func (c *CurrencyConverter) ConvertBalance(balance types.Balance) (types.Balance, error) {
if balance.Currency == c.FromCurrency {
balance.Currency = c.ToCurrency
}
return balance, nil
}

View File

@ -0,0 +1,124 @@
package core
import (
"github.com/c9s/bbgo/pkg/types"
"github.com/stretchr/testify/assert"
"testing"
)
// pkg/core/tradecollector_test.go
func TestInitialize_ValidCurrencies(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
err := converter.Initialize()
assert.NoError(t, err)
}
func TestInitialize_EmptyFromCurrency(t *testing.T) {
converter := NewCurrencyConverter("", "MAX")
err := converter.Initialize()
assert.Error(t, err)
assert.Equal(t, "FromCurrency can not be empty", err.Error())
}
func TestInitialize_EmptyToCurrency(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "")
err := converter.Initialize()
assert.Error(t, err)
assert.Equal(t, "ToCurrency can not be empty", err.Error())
}
func TestConvertOrder_ValidConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
order := types.Order{
SubmitOrder: types.SubmitOrder{
Market: types.Market{
QuoteCurrency: "MAXEXCHANGE",
BaseCurrency: "MAXEXCHANGE",
},
},
}
convertedOrder, err := converter.ConvertOrder(order)
assert.NoError(t, err)
assert.Equal(t, "MAX", convertedOrder.SubmitOrder.Market.QuoteCurrency)
assert.Equal(t, "MAX", convertedOrder.SubmitOrder.Market.BaseCurrency)
}
func TestConvertOrder_NoConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
order := types.Order{
SubmitOrder: types.SubmitOrder{
Market: types.Market{
QuoteCurrency: "JPY",
BaseCurrency: "JPY",
},
},
}
convertedOrder, err := converter.ConvertOrder(order)
assert.NoError(t, err)
assert.Equal(t, "JPY", convertedOrder.SubmitOrder.Market.QuoteCurrency)
assert.Equal(t, "JPY", convertedOrder.SubmitOrder.Market.BaseCurrency)
}
func TestConvertTrade_ValidConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
trade := types.Trade{
FeeCurrency: "MAXEXCHANGE",
}
convertedTrade, err := converter.ConvertTrade(trade)
assert.NoError(t, err)
assert.Equal(t, "MAX", convertedTrade.FeeCurrency)
}
func TestConvertTrade_NoConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
trade := types.Trade{
FeeCurrency: "JPY",
}
convertedTrade, err := converter.ConvertTrade(trade)
assert.NoError(t, err)
assert.Equal(t, "JPY", convertedTrade.FeeCurrency)
}
func TestConvertMarket_ValidConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
market := types.Market{
QuoteCurrency: "MAXEXCHANGE",
BaseCurrency: "MAXEXCHANGE",
}
convertedMarket, err := converter.ConvertMarket(market)
assert.NoError(t, err)
assert.Equal(t, "MAX", convertedMarket.QuoteCurrency)
assert.Equal(t, "MAX", convertedMarket.BaseCurrency)
}
func TestConvertMarket_NoConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
market := types.Market{
QuoteCurrency: "JPY",
BaseCurrency: "JPY",
}
convertedMarket, err := converter.ConvertMarket(market)
assert.NoError(t, err)
assert.Equal(t, "JPY", convertedMarket.QuoteCurrency)
assert.Equal(t, "JPY", convertedMarket.BaseCurrency)
}
func TestConvertBalance_ValidConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
balance := types.Balance{
Currency: "MAXEXCHANGE",
}
convertedBalance, err := converter.ConvertBalance(balance)
assert.NoError(t, err)
assert.Equal(t, "MAX", convertedBalance.Currency)
}
func TestConvertBalance_NoConversion(t *testing.T) {
converter := NewCurrencyConverter("MAXEXCHANGE", "MAX")
balance := types.Balance{
Currency: "JPY",
}
convertedBalance, err := converter.ConvertBalance(balance)
assert.NoError(t, err)
assert.Equal(t, "JPY", convertedBalance.Currency)
}

View File

@ -13,7 +13,8 @@ import (
) )
type ConverterSetting struct { type ConverterSetting struct {
SymbolConverter *SymbolConverter `json:"symbolConverter" yaml:"symbolConverter"` SymbolConverter *SymbolConverter `json:"symbolConverter" yaml:"symbolConverter"`
CurrencyConverter *CurrencyConverter `json:"currencyConverter" yaml:"currencyConverter"`
} }
func (s *ConverterSetting) getConverter() Converter { func (s *ConverterSetting) getConverter() Converter {
@ -21,6 +22,10 @@ func (s *ConverterSetting) getConverter() Converter {
return s.SymbolConverter return s.SymbolConverter
} }
if s.CurrencyConverter != nil {
return s.CurrencyConverter
}
return nil return nil
} }