Skip to content

Commit

Permalink
added GetTickSize method to Listing
Browse files Browse the repository at this point in the history
  • Loading branch information
ettec committed Nov 7, 2021
1 parent 4614f6b commit 07d10d2
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 44 deletions.
18 changes: 18 additions & 0 deletions model/listing.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ func (m *Listing) RoundToNearestTick(price float64) (*Decimal64, error) {
return nil, fmt.Errorf("no tick table entry for price:%v", price)
}


func (m *Listing) GetTickSizeForPriceLevel( price float64) (*Decimal64, error) {

for _, entry := range m.TickSize.Entries {
delta := entry.TickSize.ToFloat() / 1000
lowerBound := entry.LowerPriceBound.ToFloat()
upperBound := entry.UpperPriceBound.ToFloat()

if compare(price, lowerBound, delta) >= 0 &&
compare(price, upperBound, delta) <= 0 {
return entry.TickSize, nil
}
}

return nil, fmt.Errorf("no tick table entry for price:%v", price)
}


func compare(f1 float64, f2 float64, delta float64) int {

diff := f1 - f2
Expand Down
113 changes: 76 additions & 37 deletions model/listing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,111 @@ package model

import "testing"

func TestListing_RoundToTickSize(t *testing.T) {

tst := &TickSizeTable{
Entries: []*TickSizeEntry{
{
LowerPriceBound: &Decimal64{Mantissa: -100, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: -10, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: -1},
},
{
LowerPriceBound: &Decimal64{Mantissa: -10, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: 10, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: -2},
},
{
LowerPriceBound: &Decimal64{Mantissa: 10, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: 100, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: -1},
},
{
LowerPriceBound: &Decimal64{Mantissa: 100, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: 1000, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: 0},
},
var tickSizeTable = &TickSizeTable{
Entries: []*TickSizeEntry{
{
LowerPriceBound: &Decimal64{Mantissa: -100, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: -10, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: -1},
},
{
LowerPriceBound: &Decimal64{Mantissa: -10, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: 10, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: -2},
},
{
LowerPriceBound: &Decimal64{Mantissa: 10, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: 100, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: -1},
},
{
LowerPriceBound: &Decimal64{Mantissa: 100, Exponent: 0},
UpperPriceBound: &Decimal64{Mantissa: 1000, Exponent: 0},
TickSize: &Decimal64{Mantissa: 1, Exponent: 0},
},
},
}

func TestListing_GetTickSizeForPriceLevel(t *testing.T) {

tests := []struct {
name string
tst *TickSizeTable
price float64
result *Decimal64
wantErr bool
}{
{"test", tickSizeTable, 9.13211,
&Decimal64{Mantissa: 1, Exponent: -2}, false},
{"test", tickSizeTable, 253.4,
&Decimal64{Mantissa: 1, Exponent: 0}, false},
{"test", tickSizeTable, 1253.4,
nil, true},
{"test", tickSizeTable, -125.4,
nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := &Listing{
TickSize: tt.tst,
}

d, err := m.GetTickSizeForPriceLevel(tt.price)
if (err != nil) != tt.wantErr {
t.Errorf("GetTickSizeForPriceLevel() error = %v, wantErr %v", err, tt.wantErr)
}

if !d.Equal(tt.result) {
t.Errorf("GetTickSizeForPriceLevel() tickSize = %v, wanted %v", d, tt.result)
}

})
}


}

func TestListing_RoundToTickSize(t *testing.T) {

tests := []struct {
name string
tst *TickSizeTable
price float64
result *Decimal64
wantErr bool
}{
{"test", tst, 9.13211,
{"test", tickSizeTable, 9.13211,
&Decimal64{Mantissa: 913, Exponent: -2}, false},
{"test", tst, 19.132,
{"test", tickSizeTable, 19.132,
&Decimal64{Mantissa: 191, Exponent: -1}, false},
{"test", tst, 200.1,
{"test", tickSizeTable, 200.1,
&Decimal64{Mantissa: 200, Exponent: 0}, false},
{"test", tst, -2.1163,
{"test", tickSizeTable, -2.1163,
&Decimal64{Mantissa: -212, Exponent: -2}, false},

{"test", tst, 2116.3,
{"test", tickSizeTable, 2116.3,
nil, true},

{"test", tst, 9.997,
{"test", tickSizeTable, 9.997,
&Decimal64{Mantissa: 10, Exponent: 0}, false},

{"test", tst, 9.9945,
{"test", tickSizeTable, 9.9945,
&Decimal64{Mantissa: 999, Exponent: -2}, false},
{"test", tst, 9.999945,
{"test", tickSizeTable, 9.999945,
&Decimal64{Mantissa: 10, Exponent: 0}, false},

{"test", tst, 10.00001,
{"test", tickSizeTable, 10.00001,
&Decimal64{Mantissa: 10, Exponent: 0}, false},

{"test", tst, -9.997,
{"test", tickSizeTable, -9.997,
&Decimal64{Mantissa: -10, Exponent: 0}, false},

{"test", tst, -9.9945,
{"test", tickSizeTable, -9.9945,
&Decimal64{Mantissa: -999, Exponent: -2}, false},
{"test", tst, -9.999945,
{"test", tickSizeTable, -9.999945,
&Decimal64{Mantissa: -10, Exponent: 0}, false},

{"test", tst, -10.00001,
{"test", tickSizeTable, -10.00001,
&Decimal64{Mantissa: -10, Exponent: 0}, false},
}
for _, tt := range tests {
Expand Down
5 changes: 3 additions & 2 deletions ordermanagement/parentorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ func init() {
zero = &model.Decimal64{}
}

// ParentOrder has a one to many relationship to its child orders. The parent aggregates and summarises state across
// its children.
type ParentOrder struct {
model.Order
ChildOrders map[string]*model.Order
Expand All @@ -19,8 +21,7 @@ type ParentOrder struct {
childOrdersRecovered bool
}

// Parent order has a one to many relationship to its child orders. The parent aggregates and summarises state across
// its children.S

func NewParentOrder(order model.Order) *ParentOrder {

childOrderRefs := map[string]model.Ref{}
Expand Down
9 changes: 4 additions & 5 deletions strategy/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ func NewStrategyFromParentOrder(initialState *model.Order, store func(*model.Ord
}



// Sends a child order to the given destination and ensures the parent order cannot become over exposed.
// SendChildOrder Sends a child order to the given destination and ensures the parent order cannot become over exposed.
func (om *Strategy) SendChildOrder(side model.Side, quantity *model.Decimal64, price *model.Decimal64, listingId int32,
destination string, execParametersJson string) error {

Expand Down Expand Up @@ -116,7 +115,7 @@ func (om *Strategy) SendChildOrder(side model.Side, quantity *model.Decimal64, p
}


// This func must be called in the strategies event handling loop, see example strategies as per package documentation.
// CheckIfDone must be called in the strategies event handling loop, see example strategies as per package documentation.
func (om *Strategy) CheckIfDone() (done bool, err error) {
done = false
err = om.persistParentOrderChanges()
Expand All @@ -132,7 +131,7 @@ func (om *Strategy) CheckIfDone() (done bool, err error) {
return done, nil
}

// Must be called in response to receipt of a child order update in the strategy's event processing loop as per example strategies
// OnChildOrderUpdate must be called in response to receipt of a child order update in the strategy's event processing loop as per example strategies
func (om *Strategy) OnChildOrderUpdate(ok bool, co *model.Order) error {
if ok {
_, err := om.ParentOrder.OnChildOrderUpdate(co)
Expand All @@ -146,7 +145,7 @@ func (om *Strategy) OnChildOrderUpdate(ok bool, co *model.Order) error {
return nil
}

// Should only be called from with the strategy's event processing loop as per the example strategies
// CancelChildOrdersAndStrategyOrder should only be called from with the strategy's event processing loop as per the example strategies
func (om *Strategy) CancelChildOrdersAndStrategyOrder() error {
if !om.ParentOrder.IsTerminalState() {
om.Log.Print("cancelling order")
Expand Down

0 comments on commit 07d10d2

Please sign in to comment.