package db import ( "encoding/json" "fmt" "time" "github.com/go-redis/redis" "github.com/shopspring/decimal" ) type PortfolioStep string const SELL_BEGIN PortfolioStep = "process_sell_all__1_all_sell_begin" const SELL_END PortfolioStep = "process_sell_all__1_all_sell_end" const BUY_BEGIN PortfolioStep = "process_sell_all__3_all_buy_begin" const BUY_END PortfolioStep = "process_sell_all__3_all_buy_end" const INTERMADIATE_STATE PortfolioStep = "process_print_balances__1_print_balances_begin" type ViewBalances struct { Id int64 Date time.Time ReportId int64 MarketId int64 Payload struct { Report } } type Report struct { Tag PortfolioStep Date time.Time Balances ReportBalances Tickers ReportTickers } type ReportTickers struct { Currency string Balances map[string]decimal.Decimal Rates BTCRates Total decimal.Decimal } func (r ReportTickers) GetBTCRate(currency string) decimal.Decimal { if currency == "BTC" { return decimal.NewFromFloat(1.0) } return r.Rates[currency] } type BTCRates map[string]decimal.Decimal func (b BTCRates) Rate(currency string) decimal.Decimal { if currency == "BTC" { return decimal.NewFromFloat(1.0) } return b[currency] } type ReportBalances map[string]struct { Total decimal.Decimal MarginTotal decimal.Decimal `json:"margin_total"` MarginInPosition decimal.Decimal `json:"margin_in_position"` MarginAvailable decimal.Decimal `json:"margin_available"` } func RedisReportKey(marketConfigId int64, timestamp, entity string) string { return fmt.Sprintf("/cryptoportfolio/%v/%v/%v", marketConfigId, timestamp, entity) } func GetLatestReport(marketConfig MarketConfig) (Report, error) { var reportPayload Report var err error var key string // Get balance. key = RedisReportKey(marketConfig.Id, "latest", "balance") payload, err := Redis.Get(key).Bytes() if err == redis.Nil { return Report{}, fmt.Errorf("cannot find '%s' redis key", key) } else if err != nil { return Report{}, err } // Get date. key = RedisReportKey(marketConfig.Id, "latest", "date") dateString, err := Redis.Get(key).Result() if err == redis.Nil { return Report{}, fmt.Errorf("cannot find '%s' redis key", key) } else if err != nil { return Report{}, err } reportPayload.Date, err = time.Parse("2006-01-02T15:04:05", dateString) if err != nil { return Report{}, err } err = json.Unmarshal(payload, &reportPayload) return reportPayload, err } func GetPortfolioMilestones(marketConfig MarketConfig, step PortfolioStep, limit int) ([]Report, error) { viewBalances := make([]ViewBalances, 0) reports := make([]Report, 0) err := DB. Model(&viewBalances). Where("market_id = ?", marketConfig.Id). Where("payload @> ?", fmt.Sprintf(`{"tag": "%s", "checkpoint": "%s"}`, step, "begin")). OrderExpr("date DESC").Limit(limit).Select() if err != nil { return nil, err } for _, reportLine := range viewBalances { reportLine.Payload.Report.Date = reportLine.Date reports = append(reports, reportLine.Payload.Report) } return reports, nil } func GetLastPortfolioBegin(marketConfig MarketConfig) (*Report, error) { reports, err := GetPortfolioMilestones(marketConfig, BUY_END, 1) if err != nil { return nil, nil } if len(reports) == 0 { return nil, nil } return &reports[0], nil }