]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git/blob - db/report_lines.go
Refactor Portfolio balance.
[perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git] / db / report_lines.go
1 package db
2
3 import (
4 "encoding/json"
5 "fmt"
6 "time"
7
8 "github.com/go-redis/redis"
9 "github.com/shopspring/decimal"
10 )
11
12 type PortfolioStep string
13
14 const SELL_BEGIN PortfolioStep = "process_sell_all__1_all_sell_begin"
15 const SELL_END PortfolioStep = "process_sell_all__1_all_sell_end"
16 const BUY_BEGIN PortfolioStep = "process_sell_all__3_all_buy_begin"
17 const BUY_END PortfolioStep = "process_sell_all__3_all_buy_end"
18 const INTERMADIATE_STATE PortfolioStep = "process_print_balances__1_print_balances_begin"
19
20 type ViewBalances struct {
21 Id int64
22 Date time.Time
23 ReportId int64
24 MarketId int64
25 Payload struct {
26 Report
27 }
28 }
29
30 type Report struct {
31 Tag PortfolioStep
32 Date time.Time
33 Balances ReportBalances
34 Tickers ReportTickers
35 }
36
37 type ReportTickers struct {
38 Currency string
39 Balances map[string]decimal.Decimal
40 Rates BTCRates
41 Total decimal.Decimal
42 }
43
44 func (r ReportTickers) GetBTCRate(currency string) decimal.Decimal {
45 if currency == "BTC" {
46 return decimal.NewFromFloat(1.0)
47 }
48
49 return r.Rates[currency]
50 }
51
52 type BTCRates map[string]decimal.Decimal
53
54 func (b BTCRates) Rate(currency string) decimal.Decimal {
55 if currency == "BTC" {
56 return decimal.NewFromFloat(1.0)
57 }
58
59 return b[currency]
60 }
61
62 type ReportBalances map[string]struct {
63 Total decimal.Decimal
64 MarginTotal decimal.Decimal `json:"margin_total"`
65 MarginInPosition decimal.Decimal `json:"margin_in_position"`
66 MarginAvailable decimal.Decimal `json:"margin_available"`
67 }
68
69 func RedisReportKey(marketConfigId int64, timestamp, entity string) string {
70 return fmt.Sprintf("/cryptoportfolio/%v/%v/%v", marketConfigId, timestamp, entity)
71 }
72
73 func GetLatestReport(marketConfig MarketConfig) (Report, error) {
74 var reportPayload Report
75 var err error
76 var key string
77
78 // Get balance.
79 key = RedisReportKey(marketConfig.Id, "latest", "balance")
80
81 payload, err := Redis.Get(key).Bytes()
82 if err == redis.Nil {
83 return Report{}, fmt.Errorf("cannot find '%s' redis key", key)
84 } else if err != nil {
85 return Report{}, err
86 }
87
88 // Get date.
89 key = RedisReportKey(marketConfig.Id, "latest", "date")
90 dateString, err := Redis.Get(key).Result()
91
92 if err == redis.Nil {
93 return Report{}, fmt.Errorf("cannot find '%s' redis key", key)
94 } else if err != nil {
95 return Report{}, err
96 }
97
98 reportPayload.Date, err = time.Parse("2006-01-02T15:04:05", dateString)
99 if err != nil {
100 return Report{}, err
101 }
102
103 err = json.Unmarshal(payload, &reportPayload)
104
105 return reportPayload, err
106 }
107
108 func GetPortfolioMilestones(marketConfig MarketConfig, step PortfolioStep, limit int) ([]Report, error) {
109 viewBalances := make([]ViewBalances, 0)
110 reports := make([]Report, 0)
111
112 err := DB.
113 Model(&viewBalances).
114 Where("market_id = ?", marketConfig.Id).
115 Where("payload @> ?", fmt.Sprintf(`{"tag": "%s", "checkpoint": "%s"}`, step, "begin")).
116 OrderExpr("date DESC").Limit(limit).Select()
117 if err != nil {
118 return nil, err
119 }
120
121 for _, reportLine := range viewBalances {
122 reportLine.Payload.Report.Date = reportLine.Date
123 reports = append(reports, reportLine.Payload.Report)
124 }
125
126 return reports, nil
127 }
128
129 func GetLastPortfolioBegin(marketConfig MarketConfig) (*Report, error) {
130 reports, err := GetPortfolioMilestones(marketConfig, BUY_END, 1)
131 if err != nil {
132 return nil, nil
133 }
134
135 if len(reports) == 0 {
136 return nil, nil
137 }
138
139 return &reports[0], nil
140 }