Skip to content

Commit

Permalink
Merge branch 'main' into SCRUM-57-publish-user-service-events
Browse files Browse the repository at this point in the history
  • Loading branch information
djangbahevans authored Aug 1, 2024
2 parents 0a9aa97 + 14a569a commit 72d2be4
Show file tree
Hide file tree
Showing 18 changed files with 548 additions and 129 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
package com.joe.trading.marketdataservice;

import com.joe.trading.marketdataservice.model.MarketData;
import com.joe.trading.marketdataservice.services.MarketDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.ArrayList;
import java.util.List;

@SpringBootApplication
public class MarketDataServiceApplication {

private final MarketDataService mdService;

@Autowired
public MarketDataServiceApplication(MarketDataService mdService) {
this.mdService = mdService;
}

public static void main(String[] args) {
SpringApplication.run(MarketDataServiceApplication.class, args);
}

public CommandLineRunner startupMDRunner(){

return args -> {
List<MarketData> marketDataList = new ArrayList<>();
// get market data from Exchange 1;
marketDataList.addAll(mdService.getAllMarketDataFromExchange("exchange1"));
// get market data from Exchange 2;
marketDataList.addAll(mdService.getAllMarketDataFromExchange("exchange2"));

};
}

}
package com.joe.trading.marketdataservice;

import com.joe.trading.marketdataservice.services.MarketDataServiceImpl;
import com.joe.trading.marketdataservice.services.orderbook.OrderBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;

@SpringBootApplication(scanBasePackages = "com.joe.trading")
public class MarketDataServiceApplication {

public static void main(String[] args) {
SpringApplication.run(MarketDataServiceApplication.class, args);
}

@Component
public static class StartupRunner implements CommandLineRunner {

private final MarketDataServiceImpl mdService;
private final OrderBookService orderBookService;

@Autowired
public StartupRunner(MarketDataServiceImpl mdService, OrderBookService orderBookService) {
this.mdService = mdService;
this.orderBookService = orderBookService;
}

@Override
public void run(String... args) throws Exception {
mdService.buildInitialCacheEntry();
orderBookService.publishOrderBook();
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.joe.trading.marketdataservice.config;

import com.joe.trading.marketdataservice.model.MarketData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -29,11 +30,11 @@ public LettuceConnectionFactory lettuceConnectionFactory(){
}

@Bean
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
public RedisTemplate<String, MarketData> redisTemplate(){
RedisTemplate<String, MarketData> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(this.lettuceConnectionFactory());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(MarketData.class));


return redisTemplate;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.joe.trading.marketdataservice.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,62 @@
package com.joe.trading.marketdataservice.controllers;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.joe.trading.marketdataservice.model.MarketData;
import com.joe.trading.marketdataservice.model.OpenOrderDTO;
import com.joe.trading.marketdataservice.services.MarketDataServiceImpl;
import com.joe.trading.marketdataservice.services.orderbook.OrderBookService;
import com.joe.trading.shared.events.Event;
import com.joe.trading.shared.nats.NatsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/md/webhook")
public class MarketDataWebhookController {

private NatsService natsService;
private final NatsService natsService;
private final MarketDataServiceImpl mdService;
private final OrderBookService orderBookService;

@Autowired
public MarketDataWebhookController(NatsService natsService){
public MarketDataWebhookController(NatsService natsService, MarketDataServiceImpl mdService, OrderBookService orderBookService){
this.natsService = natsService;
this.mdService = mdService;
this.orderBookService = orderBookService;
}

@PostMapping
public OpenOrderDTO receiveUpdate(@RequestBody OpenOrderDTO payload) throws JsonProcessingException {
public ResponseEntity<OpenOrderDTO> receiveUpdate(@RequestBody OpenOrderDTO payload) throws JsonProcessingException {

String ticker = "";
Map<String, MarketData> dataUpdate = new HashMap<>();

System.out.println("Received Subscription Update: " + payload);
if (payload.getExchange().equals("MAL1")){
this.natsService.publish(Event.NEW_ORDER_EX1, payload);
ticker = payload.getProduct() + "_EX1";
dataUpdate.put(ticker, newMarketData("exchange1", payload.getProduct()));
}
else {
this.natsService.publish(Event.NEW_ORDER_EX2, payload);
ticker = payload.getProduct() + "_EX1";
dataUpdate.put(ticker, newMarketData("exchange2", payload.getProduct()));
}
return payload;

natsService.publish(Event.MARKET_DATA_UPDATE, dataUpdate);
orderBookService.publishOrderBook();
mdService.updateMarketData(dataUpdate.get(ticker));


return ResponseEntity.ok(payload);
}

private MarketData newMarketData(String exchange, String ticker){
return mdService.getMarketDataFromExchange(exchange, ticker);
}

@GetMapping
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.joe.trading.marketdataservice.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.Objects;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Executions {
private Integer quantity;
private String timestamp;
private Double price;

@Override
public String toString() {
return "Executions{" +
"quantity=" + quantity +
", timestamp=" + timestamp +
", price=" + price +
'}';
}

@Override
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof Executions that)) return false;
return Objects.equals(quantity, that.quantity) && Objects.equals(timestamp, that.timestamp) && Objects.equals(price, that.price);
}

@Override
public int hashCode() {
return Objects.hash(quantity, timestamp, price);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
package com.joe.trading.marketdataservice.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

@Getter
@Setter
@NoArgsConstructor
public class MarketData {
public class MarketData implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

@JsonProperty
private Double LAST_TRADED_PRICE;
@JsonProperty
private String TICKER;
@JsonProperty
private Integer SELL_LIMIT;
@JsonProperty
private Double BID_PRICE;
@JsonProperty
private Integer BUY_LIMIT;

@JsonProperty
private Double ASK_PRICE;
@JsonProperty
private Double MAX_PRICE_SHIFT;

private String EXCHANGE;

@Override
Expand All @@ -31,4 +47,16 @@ public String toString() {
", EXCHANGE='" + EXCHANGE + '\'' +
'}';
}

@Override
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof MarketData that)) return false;
return Objects.equals(LAST_TRADED_PRICE, that.LAST_TRADED_PRICE) && Objects.equals(TICKER, that.TICKER) && Objects.equals(SELL_LIMIT, that.SELL_LIMIT) && Objects.equals(BID_PRICE, that.BID_PRICE) && Objects.equals(BUY_LIMIT, that.BUY_LIMIT) && Objects.equals(ASK_PRICE, that.ASK_PRICE) && Objects.equals(MAX_PRICE_SHIFT, that.MAX_PRICE_SHIFT) && Objects.equals(EXCHANGE, that.EXCHANGE);
}

@Override
public int hashCode() {
return Objects.hash(LAST_TRADED_PRICE, TICKER, SELL_LIMIT, BID_PRICE, BUY_LIMIT, ASK_PRICE, MAX_PRICE_SHIFT, EXCHANGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.joe.trading.marketdataservice.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Getter
@Setter
@NoArgsConstructor
public class OrderBook {
private String orderID;
private Double price;
private String product;
private Integer quantity;
private Integer cumulatitiveQuantity;
private Double cumulatitivePrice;
private String side;
private String orderType;

private List<Executions> executions = new ArrayList();

public OrderBook(String product, String id, Integer quantity, String side, String type) {
this.product = product;
this.orderID = id;
this.quantity = quantity;
this.side = side;
this.orderType = type;
this.cumulatitiveQuantity = 0;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrderBook orderBook = (OrderBook) o;
return Objects.equals(orderID, orderBook.orderID);
}

@Override
public int hashCode() {
return Objects.hashCode(orderID);
}

@Override
public String toString() {
return "OrderBook{" +
"orderID=" + orderID +
"price=" + price +
", product='" + product + '\'' +
", quantity=" + quantity +
", cumulatitiveQuantity=" + cumulatitiveQuantity +
", side='" + side + '\'' +
", type='" + orderType + '\'' +
", executions=" + executions +
'}';
}
}
Loading

0 comments on commit 72d2be4

Please sign in to comment.