]>
Commit | Line | Data |
---|---|---|
24e47979 | 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 | } |