Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internals/SubEvents/subevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (s *SubEvent) SubmitOrder(o models.Order) error {
log.Printf("SubEvent has expired")
return errors.New("SubEvent has expired")
}

s.OrderBook.PushOrderIntoQueue(o)

return nil
}
51 changes: 42 additions & 9 deletions internals/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,13 @@ func SetupRoutes(router *gin.Engine) {
// Event endpoints
router.POST("/admin/event", CreateEvent) // Create a new event

// IMPLEMENT EDITING AN EVENT
router.PUT("/admin/event", ModifyEvent) // Modify an event
router.DELETE("/admin/event") // Delete an event

// SubEvent endpoints
router.POST("/admin/subevent", CreateSubevent) // Create a new subevent
router.PUT("/admin/subevent", ModifySubEvent) // Modify a subevent
router.DELETE("/admin/subevent") // Delete a subevent
router.POST("/admin/subevent", CreateSubevent) // Create a new subevent
router.PUT("/admin/subevent", ModifySubEvent) // Modify a subevent
router.DELETE("/admin/subevent") // Delete a subevent

}

Expand Down Expand Up @@ -109,7 +108,7 @@ func CreateSubevent(c *gin.Context) {
}

event.AddSubevent([]subevents.SubEvent{*subevents.NewSubEvent("", tempSubEvent.SubEventName, time.Now(), false, subEventExpiry)})
c.JSON(http.StatusOK, gin.H{"message": "SubEvent created successfully","subevent_name": tempSubEvent.SubEventName})
c.JSON(http.StatusOK, gin.H{"message": "SubEvent created successfully", "subevent_name": tempSubEvent.SubEventName})
}

// ModifySubEvent handles modifying an existing subevent such as expiry date, name, info
Expand Down Expand Up @@ -337,15 +336,21 @@ func CreateOrder(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
Order.ErrChan = make(chan error,1)
Order.SetRequestType("add")
Order.SetTimestamp(time.Now().UnixMilli())

err := l.SubmitOrder(Order)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}


err = <-Order.ErrChan
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"message": "Order created successfully", "Order": Order})
}

Expand All @@ -365,6 +370,8 @@ func CancelOrder(c *gin.Context) {
// "subevent_id": "SubEventID",
// }
var OrderForCancellation models.Order
OrderForCancellation.ErrChan = make(chan error,1)

if err := c.BindJSON(&OrderForCancellation); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
Expand All @@ -375,6 +382,12 @@ func CancelOrder(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err = <-OrderForCancellation.ErrChan
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"message": "Order cancelled successfully"})

}
Expand All @@ -399,15 +412,15 @@ func ModifyOrder(c *gin.Context) {
// }

var OrderForModification models.Order
OrderForModification.ErrChan = make(chan error,1)

// Bind the input to the Order struct
if err := c.BindJSON(&OrderForModification); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

OrderForModification.SetRequestType("modify")

OrderForModification.SetRequestType("delete")
// Submit the modified order
err := l.SubmitOrder(OrderForModification)

Expand All @@ -417,6 +430,26 @@ func ModifyOrder(c *gin.Context) {
return
}

// Wait for the order to be deleted
err = <-OrderForModification.ErrChan
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

OrderForModification.SetRequestType("add")
err = l.SubmitOrder(OrderForModification)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

err = <-OrderForModification.ErrChan
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

// Return success message
c.JSON(http.StatusOK, gin.H{"message": "Order modified successfully"})
}
Expand Down
2 changes: 1 addition & 1 deletion internals/ledger/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (l *Ledger) SubmitOrder(o models.Order) error {
log.Printf("Error in submitting order ")
return errors.New("Event doesn't exist")
}

// Submit the order to the event
err := event.SubmitOrder(o)
if err != nil {
Expand Down
6 changes: 4 additions & 2 deletions internals/orderbook/matchOrderHelpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,16 @@ func (ob *OrderBook) MergeTopPrices() error {
lowestAsk, _ := ob.Asks.Pop()
highestBid, _ := ob.Bids.Top()
NoOfOrders = lowestAsk.GetQuantity()
highestBid.SetQuantity(highestBid.GetQuantity() - lowestAsk.GetQuantity())
ob.LogHandler(lowestAsk, highestBid)
highestBid.SetQuantity(highestBid.GetQuantity() - lowestAsk.GetQuantity())
delete(ob.Orders, lowestAsk.GetOrderID())
} else {
lowestAsk, _ := ob.Asks.Top()
highestBid, _ := ob.Bids.Pop()
NoOfOrders = highestBid.GetQuantity()
lowestAsk.SetQuantity(lowestAsk.GetQuantity() - highestBid.GetQuantity())
ob.LogHandler(lowestAsk, highestBid)
lowestAsk.SetQuantity(lowestAsk.GetQuantity() - highestBid.GetQuantity())
delete(ob.Orders, highestBid.GetOrderID())
}
log.Printf("\nAsk_Price : %v\n Bid_Price : %v\n Orders : %v", _lowestAsk.GetPrice(), _highestBid.GetPrice(), NoOfOrders)
}
Expand Down
64 changes: 59 additions & 5 deletions internals/orderbook/orderbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ func (ob *OrderBook) StartProcessingTrades() {
case "add":
if err := ob.AddOrder(&Order); err != nil {
log.Printf("Error adding Order: %v", err)
Order.ErrChan <- err
}
case "delete":
if err := ob.CancelOrder(&Order); err != nil {
log.Printf("Error deleting Order: %v", err)
log.Printf("Error delPushOrderIntoQueueeting Order: %v", err)
Order.ErrChan <- err
}
default:
log.Printf("Unknown request type: %s", Order.RequestType)
Order.ErrChan <- errors.New("unknown request type")
}
}
}()
Expand All @@ -77,18 +80,24 @@ func (ob *OrderBook) StartProcessingOrders() {
case "add":
if err := ob.AddOrder(&Order); err != nil {
log.Printf("Error adding Order: %v", err)
Order.ErrChan <- err
}
case "delete":
if err := ob.CancelOrder(&Order); err != nil {
log.Printf("Error deleting Order: %v", err)
Order.ErrChan <- err
}
case "modify":
if err := ob.ModifyOrder(&Order); err != nil {
log.Printf("Error modifying Order: %v", err)
Order.ErrChan <- err
}
default:
log.Printf("Unknown request type: %s", Order.RequestType)
Order.ErrChan <- errors.New("unknown request type")
}
Order.ErrChan <- nil
close(Order.ErrChan)
}
}()
}
Expand All @@ -100,35 +109,36 @@ func (ob *OrderBook) PushOrderIntoQueue(Order models.Order) {
// AddOrder adds a new Order (order) to the order book and attempts to match orders.
func (ob *OrderBook) AddOrder(Order *models.Order) error {

//Order.OrderID = helpers.GenerateRandomString(helpers.ConvertStringToInt(os.Getenv("Order_ID_LENGTH")))

newOrderID := strconv.Itoa(ob.OrderNo)
Order.OrderID = newOrderID
ob.OrderNo++
switch Order.OrderType {
case "sell":

err := ob.Asks.Push(Order)
if err != nil {
log.Printf("Error pushing Order into Asks: %v", err)
return err
}
log.Printf("Pushed Order into Asks: %+v", Order)
case "buy":
err := ob.Bids.Push(Order)
if err != nil {
log.Printf("Error pushing Order into Bids: %v", err)
return err
}
log.Printf("Pushed Order into Bids: %+v", Order)
case "limit_sell":
err := ob.LimitAsks.Push(Order)
if err != nil {
log.Printf("Error pushing Order into LimitAsks: %v", err)
return err
}
log.Printf("Pushed Order into LimitAsks: %+v", Order)
case "limit_buy":
err := ob.LimitBids.Push(Order)
if err != nil {
log.Printf("Error pushing Order into LimitBids: %v", err)
return err
}
log.Printf("Pushed Order into LimitBids: %+v", Order)
default:
Expand Down Expand Up @@ -205,7 +215,6 @@ func (ob *OrderBook) CancelOrder(Order *models.Order) error {

}


// ISSUE TO BE FIXED POTENTIAL SITUATION WHERE ORDER CANT BE DELETED BUT DUE TO IMPLEMENTATION ANOTHER ORDER IS ADDED
// ModifyOrder cancels a specific user's Order and then adds a new Order based on the updated modifications.
func (ob *OrderBook) ModifyOrder(Order *models.Order) error {
Expand All @@ -214,31 +223,76 @@ func (ob *OrderBook) ModifyOrder(Order *models.Order) error {
case "buy":
c, err := ob.Bids.Find(Order.OrderID)
if err != nil {
log.Printf("Error Finding Order: %v", err)
return err
}
err = ob.CancelOrder(c)
if err != nil {
log.Printf("Error Canceling Order: %v", err)
return err
}
c.SetPrice(Order.GetPrice())
c.SetQuantity(Order.GetQuantity())
err = ob.AddOrder(c)
if err != nil {
log.Printf("Error adding Order: %v", err)
return err
}

case "sell":
c, err := ob.Asks.Find(Order.OrderID)
if err != nil {
log.Printf("Error Finding Order: %v", err)
return err
}
err = ob.CancelOrder(c)
if err != nil {
log.Printf("Error Canceling Order: %v", err)
return err
}
c.SetPrice(Order.GetPrice())
c.SetQuantity(Order.GetQuantity())
err = ob.AddOrder(c)
if err != nil {
log.Printf("Error adding Order: %v", err)
return err
}
case "limit_buy":
c, err := ob.LimitBids.Find(Order.OrderID)
if err != nil {
log.Printf("Error Finding Order: %v", err)
return err
}
err = ob.CancelOrder(c)
if err != nil {
log.Printf("Error Canceling Order: %v", err)
return err
}
c.SetPrice(Order.GetPrice())
c.SetQuantity(Order.GetQuantity())
err = ob.AddOrder(c)
if err != nil {
log.Printf("Error adding Order: %v", err)
return err
}
case "limit_sell":
c, err := ob.LimitAsks.Find(Order.OrderID)
if err != nil {
log.Printf("Error Finding Order: %v", err)
return err
}
err = ob.CancelOrder(c)
if err != nil {
log.Printf("Error Canceling Order: %v", err)
return err
}
c.SetPrice(Order.GetPrice())
c.SetQuantity(Order.GetQuantity())
err = ob.AddOrder(c)
if err != nil {
log.Printf("Error adding Order: %v", err)
return err
}
default:
return errors.New("invalid order type")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/models/hashHeaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func PriceTimeBased(a, b interface{}) int {
A := a.(*Order)
B := b.(*Order)
if A.GetPrice() == B.GetPrice() {
return utils.Int64Comparator(A.GetTimestamp(), B.GetTimestamp())
return utils.Int64Comparator(B.GetTimestamp(),A.GetTimestamp() )
} else {
if A.GetOrderType() == "buy" || A.GetOrderType() == "limit_buy" {
if A.GetPrice() < B.GetPrice() {
Expand Down
19 changes: 10 additions & 9 deletions pkg/models/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package models

// Order struct represents an order (buy/sell)
type Order struct {
OrderID string `json:"order_id"`
EventID string `json:"event_id"`
SubEventID string `json:"subevent_id"`
UserID string `json:"user_id"`
RequestType string `json:"request_type"`
OrderType string `json:"order_type"`
Price float32 `json:"price" binding:"required,gt=0"`
Quantity int64 `json:"quantity" binding:"required,gte=1"`
Timestamp int64 `json:"timestamp"`
OrderID string `json:"order_id"`
EventID string `json:"event_id"`
SubEventID string `json:"subevent_id"`
UserID string `json:"user_id"`
RequestType string `json:"request_type"`
OrderType string `json:"order_type"`
Price float32 `json:"price" binding:"required,gt=0"`
Quantity int64 `json:"quantity" binding:"required,gte=1"`
Timestamp int64 `json:"timestamp"`
ErrChan chan error `json:"-"`
}

// NewOrder creates a new instance of Order
Expand Down
Loading