bbgo/pkg/strategy/tri/position.go

140 lines
3.7 KiB
Go

package tri
import (
"fmt"
"git.qtrade.icu/lychiyu/bbgo/pkg/fixedpoint"
"git.qtrade.icu/lychiyu/bbgo/pkg/types"
)
type MultiCurrencyPosition struct {
Currencies map[string]fixedpoint.Value `json:"currencies"`
Markets map[string]types.Market `json:"markets"`
TotalProfits map[string]fixedpoint.Value `json:"totalProfits"`
Fees map[string]fixedpoint.Value `json:"fees"`
TradePrices map[string]fixedpoint.Value `json:"prices"`
}
func NewMultiCurrencyPosition(markets map[string]types.Market) *MultiCurrencyPosition {
p := &MultiCurrencyPosition{
Currencies: make(map[string]fixedpoint.Value),
Markets: make(map[string]types.Market),
TotalProfits: make(map[string]fixedpoint.Value),
TradePrices: make(map[string]fixedpoint.Value),
Fees: make(map[string]fixedpoint.Value),
}
for _, market := range markets {
p.Markets[market.Symbol] = market
p.Currencies[market.BaseCurrency] = fixedpoint.Zero
p.Currencies[market.QuoteCurrency] = fixedpoint.Zero
p.TotalProfits[market.QuoteCurrency] = fixedpoint.Zero
p.TotalProfits[market.BaseCurrency] = fixedpoint.Zero
p.Fees[market.QuoteCurrency] = fixedpoint.Zero
p.Fees[market.BaseCurrency] = fixedpoint.Zero
p.TradePrices[market.QuoteCurrency] = fixedpoint.Zero
p.TradePrices[market.BaseCurrency] = fixedpoint.Zero
}
return p
}
func (p *MultiCurrencyPosition) handleTrade(trade types.Trade) {
market := p.Markets[trade.Symbol]
switch trade.Side {
case types.SideTypeBuy:
p.Currencies[market.BaseCurrency] = p.Currencies[market.BaseCurrency].Add(trade.Quantity)
p.Currencies[market.QuoteCurrency] = p.Currencies[market.QuoteCurrency].Sub(trade.QuoteQuantity)
case types.SideTypeSell:
p.Currencies[market.BaseCurrency] = p.Currencies[market.BaseCurrency].Sub(trade.Quantity)
p.Currencies[market.QuoteCurrency] = p.Currencies[market.QuoteCurrency].Add(trade.QuoteQuantity)
}
if types.IsUSDFiatCurrency(market.QuoteCurrency) {
p.TradePrices[market.BaseCurrency] = trade.Price
} else if types.IsUSDFiatCurrency(market.BaseCurrency) { // For USDT/TWD pair, convert USDT/TWD price to TWD/USDT
p.TradePrices[market.QuoteCurrency] = one.Div(trade.Price)
}
if !trade.Fee.IsZero() {
if f, ok := p.Fees[trade.FeeCurrency]; ok {
p.Fees[trade.FeeCurrency] = f.Add(trade.Fee)
} else {
p.Fees[trade.FeeCurrency] = trade.Fee
}
}
}
func (p *MultiCurrencyPosition) CollectProfits() []Profit {
var profits []Profit
for currency, base := range p.Currencies {
if base.IsZero() {
continue
}
profit := Profit{
Asset: currency,
Profit: base,
ProfitInUSD: fixedpoint.Zero,
}
if price, ok := p.TradePrices[currency]; ok && !price.IsZero() {
profit.ProfitInUSD = base.Mul(price)
} else if types.IsUSDFiatCurrency(currency) {
profit.ProfitInUSD = base
}
profits = append(profits, profit)
if total, ok := p.TotalProfits[currency]; ok {
p.TotalProfits[currency] = total.Add(base)
} else {
p.TotalProfits[currency] = base
}
}
p.Reset()
return profits
}
func (p *MultiCurrencyPosition) Reset() {
for currency := range p.Currencies {
p.Currencies[currency] = fixedpoint.Zero
}
}
func (p *MultiCurrencyPosition) String() (o string) {
o += "position: \n"
for currency, base := range p.Currencies {
if base.IsZero() {
continue
}
o += fmt.Sprintf("- %s: %f\n", currency, base.Float64())
}
o += "totalProfits: \n"
for currency, total := range p.TotalProfits {
if total.IsZero() {
continue
}
o += fmt.Sprintf("- %s: %f\n", currency, total.Float64())
}
o += "fees: \n"
for currency, fee := range p.Fees {
if fee.IsZero() {
continue
}
o += fmt.Sprintf("- %s: %f\n", currency, fee.Float64())
}
return o
}