]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git/blobdiff - db/report_lines.go
Refactor Portfolio balance.
[perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git] / db / report_lines.go
diff --git a/db/report_lines.go b/db/report_lines.go
new file mode 100644 (file)
index 0000000..274be57
--- /dev/null
@@ -0,0 +1,140 @@
+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
+}