-
Notifications
You must be signed in to change notification settings - Fork 5
/
models.go
265 lines (230 loc) · 6.49 KB
/
models.go
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
package trade
import (
"time"
"github.com/rocketlaunchr/dataframe-go"
)
type Balance struct {
Equity float64 // 净值
Available float64 // 可用余额
Margin float64 // 已用保证金
RealizedPnl float64
UnrealisedPnl float64
}
type Item struct {
Price float64
Amount float64
}
type OrderBook struct {
Symbol string
Time time.Time
Asks []Item
Bids []Item
}
// Ask 卖一
func (o *OrderBook) Ask() (result Item) {
if len(o.Asks) > 0 {
result = o.Asks[0]
}
return
}
// Bid 买一
func (o *OrderBook) Bid() (result Item) {
if len(o.Bids) > 0 {
result = o.Bids[0]
}
return
}
// AskPrice 卖一价
func (o *OrderBook) AskPrice() (result float64) {
if len(o.Asks) > 0 {
result = o.Asks[0].Price
}
return
}
func avePrice(items []Item, size float64) float64 {
var totalSize = 0.0
var totalValue = 0.0
var lSize = size
var n = len(items)
for i := 0; i < n; i++ {
if lSize >= items[i].Amount {
totalSize += items[i].Amount
totalValue += items[i].Amount * items[i].Price
lSize -= items[i].Amount
} else {
totalSize += lSize
totalValue += lSize * items[i].Price
lSize = 0
}
if lSize <= 0 {
break
}
}
if lSize != 0 || totalSize == 0 {
return -1
}
return totalValue / totalSize
}
func (o *OrderBook) AskAvePrice(size float64) float64 {
return avePrice(o.Asks, size)
}
func (o *OrderBook) BidAvePrice(size float64) float64 {
return avePrice(o.Bids, size)
}
func (o *OrderBook) MatchOrderbook(size float64, ob []Item) (filledSize float64, avgPrice float64) {
type item = struct {
Amount float64
Price float64
}
var items []item
lSize := size
for i := 0; i < len(ob); i++ {
if lSize >= ob[i].Amount {
items = append(items, item{
Amount: ob[i].Amount,
Price: ob[i].Price,
})
lSize -= ob[i].Amount
} else {
items = append(items, item{
Amount: lSize,
Price: ob[i].Price,
})
lSize = 0
}
if lSize <= 0 {
break
}
}
if lSize != 0 {
return
}
// 计算平均价
amount := 0.0
for _, v := range items {
amount += v.Price * v.Amount
filledSize += v.Amount
}
if filledSize == 0 {
return
}
avgPrice = amount / filledSize
return
}
func (o *OrderBook) MatchBids(size float64) (filledSize float64, avgPrice float64) {
return o.MatchOrderbook(size, o.Bids)
}
func (o *OrderBook) MatchAsks(size float64) (filledSize float64, avgPrice float64) {
return o.MatchOrderbook(size, o.Asks)
}
// BidPrice 买一价
func (o *OrderBook) BidPrice() (result float64) {
if len(o.Bids) > 0 {
result = o.Bids[0].Price
}
return
}
// Price returns the middle of Bid and Ask.
func (o *OrderBook) Price() float64 {
latest := (o.Bid().Price + o.Ask().Price) / float64(2)
return latest
}
func (o *OrderBook) Table() string {
askPrice := dataframe.NewSeriesFloat64("ask price", nil)
bidPrice := dataframe.NewSeriesFloat64("bid price", nil)
askAmount := dataframe.NewSeriesFloat64("ask amount", nil)
bidAmount := dataframe.NewSeriesFloat64("bid amount", nil)
for _, v := range o.Asks {
askPrice.Append(v.Price)
askAmount.Append(v.Amount)
}
for _, v := range o.Bids {
bidPrice.Append(v.Price)
bidAmount.Append(v.Amount)
}
df := dataframe.NewDataFrame(askPrice, askAmount, bidPrice, bidAmount)
return df.Table()
}
// Record 表示K线数据
type Record struct {
Symbol string `json:"symbol"` // 标
Timestamp time.Time `json:"timestamp"` // 时间
Open float64 `json:"open"` // 开盘价
High float64 `json:"high"` // 最高价
Low float64 `json:"low"` // 最低价
Close float64 `json:"close"` // 收盘价
Volume float64 `json:"volume"` // 量
}
// Trade 成交记录
type Trade struct {
ID string `json:"id"` // ID
Direction Direction `json:"type"` // 主动成交方向
Price float64 `json:"price"` // 价格
Amount float64 `json:"amount"` // 成交量(张),买卖双边成交量之和
Ts int64 `json:"ts"` // 订单成交时间 unix time (ms)
Symbol string `json:"omitempty"`
}
// Order 委托
type Order struct {
ID string `json:"id"` // ID
ClientOId string `json:"client_oid"` // 客户端订单ID
Symbol string `json:"symbol"` // 标
Time time.Time `json:"time"` // 订单时间
Price float64 `json:"price"` // 价格
StopPx float64 `json:"stop_px"` // 触发价
Amount float64 `json:"amount"` // 委托数量
AvgPrice float64 `json:"avg_price"` // 平均成交价
FilledAmount float64 `json:"filled_amount"` // 成交数量
Direction Direction `json:"direction"` // 委托方向
Type OrderType `json:"type"` // 委托类型
PostOnly bool `json:"post_only"` // 只做Maker选项
ReduceOnly bool `json:"reduce_only"` // 只减仓选项
Commission float64 `json:"commission"` // 支付的佣金
Pnl float64 `json:"pnl"` // 盈亏
UpdateTime time.Time `json:"update_time"` // 更新时间
Status OrderStatus `json:"status"` // 委托状态
ActivatePrice string `json:"activatePrice"`
PriceRate string `json:"priceRate"`
ClosePosition bool `json:"closePosition"`
}
// IsOpen 是否活跃委托
func (o *Order) IsOpen() bool {
return o.Status == OrderStatusCreated || o.Status == OrderStatusNew || o.Status == OrderStatusPartiallyFilled
}
// Position 持仓
type Position struct {
Symbol string `json:"symbol"` // 标
OpenTime time.Time `json:"open_time"` // 开仓时间
OpenPrice float64 `json:"open_price"` // 开仓价
Size float64 `json:"size"` // 仓位大小
AvgPrice float64 `json:"avg_price"` // 平均价
Profit float64 `json:"profit"` //浮动盈亏
MarginType string `json:"marginType"`
IsAutoAddMargin bool `json:"isAutoAddMargin"`
IsolatedMargin float64 `json:"isolatedMargin"`
Leverage float64 `json:"leverage"`
LiquidationPrice float64 `json:"liquidationPrice"`
MarkPrice float64 `json:"markPrice"`
MaxNotionalValue float64 `json:"maxNotionalValue"`
PositionSide string `json:"positionSide"`
}
func (p *Position) Side() Direction {
if p.Size > 0 {
return Buy
} else if p.Size < 0 {
return Sell
}
return Buy
}
// IsOpen 是否持仓
func (p *Position) IsOpen() bool {
return p.Size != 0
}
// IsLong 是否多仓
func (p *Position) IsLong() bool {
return p.Size > 0
}
// IsShort 是否空仓
func (p *Position) IsShort() bool {
return p.Size < 0
}