-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathposition.go
138 lines (115 loc) · 3.07 KB
/
position.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
package bfldb
import (
"errors"
"math"
)
var (
ErrNoPreviousPosition = errors.New("no previous position amount")
)
// PositionType is a type of a position
type PositionType int
const (
Opened PositionType = iota + 1 // A completely new position
Closed // A completely closed position
AddedTo // A new position where there previously already was a position for the same direction and ticker + the amount increased
PartiallyClosed // A new position where there previously already was a position for the same direction and ticker + the amount decreased
)
func (pt PositionType) String() string {
switch pt {
default:
return ""
case Opened:
return "opened"
case Closed:
return "closed"
case AddedTo:
return "added to"
case PartiallyClosed:
return "partially closed"
}
}
// Position represents a position user is in.
type Position struct {
Type PositionType // Type of the position
Direction TradeDirection // Direction (e.g. LONG / SHORT)
Ticker string // Ticker of the position (e.g. BTCUSDT)
EntryPrice float64 // Entry price
MarkPrice float64 // Entry price
Amount float64 // Amount
PrevAmount float64 // previous amount, used for determining position type
Leverage int // Position leverage
Pnl float64 // PNL
Roe float64 // ROE
}
// ToOrder converts a position into an Order.
func (p Position) ToOrder() Order {
o := Order{
Ticker: p.Ticker,
ReduceOnly: false,
Direction: p.Direction,
Amount: p.Amount,
Leverage: p.Leverage,
}
if p.Type == Closed || p.Type == PartiallyClosed {
o.ReduceOnly = true
// inverse the direction since the new order should be closing the
// position
if p.Direction == Long {
o.Direction = Short
} else {
o.Direction = Long
}
}
// opened = nothing changes
if p.Type == Closed {
o.Amount = p.PrevAmount
}
if p.Type == PartiallyClosed {
o.Amount = p.PrevAmount - p.Amount
}
if p.Type == AddedTo {
o.Amount = p.Amount - p.PrevAmount
}
return o
}
// DeterminePositionType determines the type of a position,
// based on the current and previous position size.
func DeterminePositionType(amt float64, prevAmt float64) PositionType {
if prevAmt == 0 {
// no previous amount, so it's a freshly opened position
return Opened
}
if prevAmt < amt {
// amount increased
return AddedTo
}
if prevAmt > amt {
// amount decreased
return PartiallyClosed
}
if amt == 0 {
// no amount, so position is closed
return Closed
}
// should never get here...
return 0
}
// newPosition creates a new Position from a rawPosition
func newPosition(rp rawPosition) Position {
// Amount is negative on short positions
dir := Long
if rp.Amount < 0 {
dir = Short
rp.Amount = math.Abs(rp.Amount)
}
return Position{
Direction: dir,
Ticker: rp.Symbol,
EntryPrice: rp.EntryPrice,
MarkPrice: rp.MarkPrice,
Amount: rp.Amount,
Leverage: rp.Leverage,
Pnl: rp.Pnl,
Roe: rp.Roe,
}
}