1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
}
|