portfolio: clean up fixes #243

pull/250/head
Miguel Mota 3 years ago committed by Simon Roberts
parent b5b68833f5
commit 0e956d6358
No known key found for this signature in database
GPG Key ID: 0F30F99E6B771FD4

@ -647,10 +647,8 @@ func (ct *Cointop) loadPortfolioHoldingsFromConfig(holdingsIfc []interface{}) er
buyPrice := 0.0
if len(tupleIfc) >= 3 {
if parsePrice, err := ct.InterfaceToFloat64(tupleIfc[2]); err != nil {
if buyPrice, err = ct.InterfaceToFloat64(tupleIfc[2]); err != nil {
return err
} else {
buyPrice = parsePrice
}
}

@ -302,19 +302,19 @@ func CurrencySymbol(currency string) string {
return "?"
}
func (ct *Cointop) Convert(convertFrom string, convertTo string, amount float64) (float64, error) {
// Convert converts an amount to another currency type
func (ct *Cointop) Convert(convertFrom, convertTo string, amount float64) (float64, error) {
convertFrom = strings.ToLower(convertFrom)
convertTo = strings.ToLower(convertTo)
var rate float64
if convertFrom == convertTo {
rate = 1.0
} else {
crate, err := ct.api.GetExchangeRate(convertFrom, convertTo, true)
return amount, nil
}
rate, err := ct.api.GetExchangeRate(convertFrom, convertTo, true)
if err != nil {
return 0, err
}
rate = crate
}
return rate * amount, nil
}

@ -328,9 +328,9 @@ func (ct *Cointop) SetKeybindingAction(shortcutKey string, action string) error
case "sort_column_cost":
fn = ct.Sortfn("cost", true)
case "sort_column_pnl":
fn = ct.Sortfn("profit", true)
fn = ct.Sortfn("pnl", true)
case "sort_column_pnl_percent":
fn = ct.Sortfn("profit_percent", true)
fn = ct.Sortfn("pnl_percent", true)
default:
fn = ct.Keyfn(ct.Noop)
}

@ -37,8 +37,8 @@ var SupportedPortfolioTableHeaders = []string{
"last_updated",
"cost_price",
"cost",
"profit",
"profit_percent",
"pnl",
"pnl_percent",
}
// DefaultPortfolioTableHeaders are the default portfolio table header columns
@ -53,12 +53,23 @@ var DefaultPortfolioTableHeaders = []string{
"24h_change",
"7d_change",
"percent_holdings",
"cost_price",
"cost",
"pnl",
"pnl_percent",
"last_updated",
}
// HiddenBalanceChars are the characters to show when hidding balances
var HiddenBalanceChars = "********"
var costColumns = map[string]bool{
"cost_price": true,
"cost": true,
"pnl": true,
"pnl_percent": true,
}
// ValidPortfolioTableHeader returns the portfolio table headers
func (ct *Cointop) ValidPortfolioTableHeader(name string) bool {
for _, v := range SupportedPortfolioTableHeaders {
@ -84,6 +95,25 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
headers := ct.GetPortfolioTableHeaders()
ct.ClearSyncMap(&ct.State.tableColumnWidths)
ct.ClearSyncMap(&ct.State.tableColumnAlignLeft)
displayCostColumns := false
for _, coin := range ct.State.coins {
if coin.BuyPrice > 0 && coin.BuyCurrency != "" {
displayCostColumns = true
break
}
}
if !displayCostColumns {
filtered := make([]string, 0)
for _, header := range headers {
if _, ok := costColumns[header]; !ok {
filtered = append(filtered, header)
}
}
headers = filtered
}
for _, coin := range ct.State.coins {
leftMargin := 1
rightMargin := 1
@ -332,7 +362,6 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
cost = costPrice * coin.Holdings
}
}
// text := ct.FormatPrice(cost)
text := humanize.FixedMonetaryf(cost, 2)
if ct.State.hidePortfolioBalances {
text = HiddenBalanceChars
@ -352,7 +381,7 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
Color: ct.colorscheme.TableColumnPrice,
Text: text,
})
case "profit":
case "pnl":
text := ""
colorProfit := ct.colorscheme.TableColumnChange
if coin.BuyPrice > 0 && coin.BuyCurrency != "" {
@ -385,7 +414,7 @@ func (ct *Cointop) GetPortfolioTable() *table.Table {
Color: colorProfit,
Text: text,
})
case "profit_percent":
case "pnl_percent":
profitPercent := 0.0
if coin.BuyPrice > 0 && coin.BuyCurrency != "" {
costPrice, err := ct.Convert(coin.BuyCurrency, ct.State.currencyConversion, coin.BuyPrice)
@ -812,8 +841,7 @@ func (ct *Cointop) PrintHoldingsTable(options *TablePrintOptions) error {
records := make([][]string, len(holdings))
symbol := ct.CurrencySymbol()
// TODO: buy_price, buy_currency, profit, profit_percent, etc
headers := []string{"name", "symbol", "price", "holdings", "balance", "24h%", "%holdings"}
headers := []string{"name", "symbol", "price", "holdings", "balance", "24h%", "%holdings", "buy_price", "buy_currency", "pnl", "pnl_percent"}
if len(filterCols) > 0 {
for _, col := range filterCols {
valid := false

@ -72,9 +72,9 @@ func (ct *Cointop) Sort(sortBy string, desc bool, list []*Coin, renderHeaders bo
return a.BuyPrice < b.BuyPrice
case "cost":
return (a.BuyPrice * a.Holdings) < (b.BuyPrice * b.Holdings) // TODO: convert?
case "profit":
case "pnl":
return (a.Price - a.BuyPrice) < (b.Price - b.BuyPrice)
case "profit_percent":
case "pnl_percent":
return (a.Price - a.BuyPrice) < (b.Price - b.BuyPrice)
default:
return a.Rank < b.Rank

@ -133,17 +133,17 @@ var HeaderColumns = map[string]*HeaderColumn{
},
"cost": {
Slug: "cost",
Label: "cost[!]",
Label: "[!]cost",
PlainLabel: "cost",
},
"profit": {
Slug: "profit",
Label: "PNL[@]",
"pnl": {
Slug: "pnl",
Label: "[@]PNL",
PlainLabel: "PNL",
},
"profit_percent": {
Slug: "profit_percent",
Label: "PNL%[#]",
"pnl_percent": {
Slug: "pnl_percent",
Label: "[#]PNL%",
PlainLabel: "PNL%",
},
}
@ -231,7 +231,7 @@ func (ct *Cointop) UpdateTableHeader() error {
}
leftAlign := ct.GetTableColumnAlignLeft(col)
switch col {
case "price", "balance", "profit", "cost":
case "price", "balance", "pnl", "cost":
label = fmt.Sprintf("%s%s", ct.CurrencySymbol(), label)
}
if leftAlign {

@ -200,12 +200,12 @@ draft: false
- `cost_price` the price and currency that the coins were purchased at
- `cost` the cost (in the current currency) of the coins
- `profit` the PNL of the coins (current value vs original cost)
- `profit_percent` the PNL of the coins as a fraction of the original cost
- `pnl` the PNL of the coins (current value vs original cost)
- `pnl_percent` the PNL of the coins as a fraction of the original cost
With the holdings above, and the currency set to GBP (British Pounds) cointop will look something like this:
![Screen Shot 2021-10-22 at 8 41 21 am](https://user-images.githubusercontent.com/122371/138361142-8e1f32b5-ca24-471d-a628-06968f07c65f.png)
![portfolio profit and loss](https://user-images.githubusercontent.com/122371/138361142-8e1f32b5-ca24-471d-a628-06968f07c65f.png)
## How do I hide my portfolio balances (private mode)?

@ -161,7 +161,7 @@ func (s *Service) GetExchangeRates(cached bool) (*types.ExchangeRatesItem, error
}
// GetExchangeRate gets the current excange rate between two currencies
func (s *Service) GetExchangeRate(convertFrom string, convertTo string, cached bool) (float64, error) {
func (s *Service) GetExchangeRate(convertFrom, convertTo string, cached bool) (float64, error) {
convertFrom = strings.ToLower(convertFrom)
convertTo = strings.ToLower(convertTo)
if convertFrom == convertTo {

@ -432,7 +432,7 @@ func getChartInterval(start, end int64) string {
}
// GetExchangeRate gets the current excange rate between two currencies
func (s *Service) GetExchangeRate(convertFrom string, convertTo string, cached bool) (float64, error) {
func (s *Service) GetExchangeRate(convertFrom, convertTo string, cached bool) (float64, error) {
if convertFrom == convertTo {
return 1.0, nil
}

@ -16,5 +16,5 @@ type Interface interface {
CoinLink(name string) string
SupportedCurrencies() []string
Price(name string, convert string) (float64, error)
GetExchangeRate(convertFrom string, convertTo string, cached bool) (float64, error) // I don't love this caching
GetExchangeRate(convertFrom, convertTo string, cached bool) (float64, error) // I don't love this caching
}

Loading…
Cancel
Save