-
Notifications
You must be signed in to change notification settings - Fork 1
/
settlement.go
129 lines (124 loc) · 3.91 KB
/
settlement.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
package exchange
import (
sdk "github.com/cosmos/cosmos-sdk/types"
cache "github.com/fibonacci-chain/core/x/dex/cache"
"github.com/fibonacci-chain/core/x/dex/types"
)
// this function helps to settle market orders
func Settle(
ctx sdk.Context,
takerOrder *types.Order,
quantityTaken sdk.Dec,
orderbook *types.CachedSortedOrderBookEntries,
worstPrice sdk.Dec,
makerPrice sdk.Dec,
) ([]*types.SettlementEntry, []*types.SettlementEntry) {
// settlement of one liquidity taker's order is allocated on a FIFO basis
takerSettlements := []*types.SettlementEntry{}
makerSettlements := []*types.SettlementEntry{}
if quantityTaken.IsZero() {
return takerSettlements, makerSettlements
}
newToSettle, _ := orderbook.SettleQuantity(ctx, quantityTaken)
for _, toSettle := range newToSettle {
takerSettlements = append(takerSettlements, types.NewSettlementEntry(
ctx,
takerOrder.Id,
takerOrder.Account,
takerOrder.PositionDirection,
takerOrder.PriceDenom,
takerOrder.AssetDenom,
toSettle.Amount,
worstPrice,
worstPrice,
takerOrder.OrderType,
))
makerSettlements = append(makerSettlements, types.NewSettlementEntry(
ctx,
toSettle.OrderID,
toSettle.Account,
types.OppositePositionDirection[takerOrder.PositionDirection],
takerOrder.PriceDenom,
takerOrder.AssetDenom,
toSettle.Amount,
makerPrice,
makerPrice,
types.OrderType_LIMIT,
))
}
return takerSettlements, makerSettlements
}
// this function update the order data in the memState
// to be noted that the order status will only reflect for market orders that are settled
func UpdateOrderData(
takerOrder *types.Order,
quantityTaken sdk.Dec,
blockOrders *cache.BlockOrders,
) {
// update order data in the memstate
orderStored := blockOrders.GetByID(takerOrder.Id)
orderStored.Quantity = orderStored.Quantity.Sub(quantityTaken)
if orderStored.OrderType == types.OrderType_FOKMARKET || orderStored.OrderType == types.OrderType_FOKMARKETBYVALUE || orderStored.Quantity.IsZero() {
orderStored.Status = types.OrderStatus_FULFILLED
}
blockOrders.Add(orderStored)
}
func SettleFromBook(
ctx sdk.Context,
orderbook *types.OrderBook,
executedQuantity sdk.Dec,
longPrice sdk.Dec,
shortPrice sdk.Dec,
) []*types.SettlementEntry {
// settlement from within the order book is also allocated on a FIFO basis
settlements := []*types.SettlementEntry{}
if executedQuantity.IsZero() {
return settlements
}
newLongToSettle, _ := orderbook.Longs.SettleQuantity(ctx, executedQuantity)
newShortToSettle, _ := orderbook.Shorts.SettleQuantity(ctx, executedQuantity)
avgPrice := longPrice.Add(shortPrice).Quo(sdk.NewDec(2))
longPtr, shortPtr := 0, 0
for longPtr < len(newLongToSettle) && shortPtr < len(newShortToSettle) {
longToSettle := newLongToSettle[longPtr]
shortToSettle := newShortToSettle[shortPtr]
var quantity sdk.Dec
if longToSettle.Amount.LT(shortToSettle.Amount) {
quantity = longToSettle.Amount
} else {
quantity = shortToSettle.Amount
}
settlements = append(settlements, types.NewSettlementEntry(
ctx,
longToSettle.OrderID,
longToSettle.Account,
types.PositionDirection_LONG,
orderbook.Pair.PriceDenom,
orderbook.Pair.AssetDenom,
quantity,
avgPrice,
longPrice,
types.OrderType_LIMIT,
), types.NewSettlementEntry(
ctx,
shortToSettle.OrderID,
shortToSettle.Account,
types.PositionDirection_SHORT,
orderbook.Pair.PriceDenom,
orderbook.Pair.AssetDenom,
quantity,
avgPrice,
shortPrice,
types.OrderType_LIMIT,
))
newLongToSettle[longPtr] = types.ToSettle{Account: longToSettle.Account, Amount: longToSettle.Amount.Sub(quantity), OrderID: longToSettle.OrderID}
newShortToSettle[shortPtr] = types.ToSettle{Account: shortToSettle.Account, Amount: shortToSettle.Amount.Sub(quantity), OrderID: shortToSettle.OrderID}
if newLongToSettle[longPtr].Amount.IsZero() {
longPtr++
}
if newShortToSettle[shortPtr].Amount.IsZero() {
shortPtr++
}
}
return settlements
}