區塊鏈應用開發方案|數字貨幣交易所繫統開發(架構設計與原始碼演示)

v_ch3nguang發表於2023-04-07

數字貨幣是基於區塊鏈技術的最典型的應用。它可以作為一種 “資產”,實現貨幣屬性、證券屬性和投資屬性的組合。因此,必須有一套交易和升值 平臺 ——交易所就是這樣的 平臺

 

交易所平臺 技術架構主要考慮安全、分散式、易擴充套件、容錯、低延遲、高併發等特點,以及 熔斷 機制、服務註冊和發現、訊息服務、服務閘道器、安全認證、記憶體資料庫、關聯式資料庫等多種選擇,並最終形成以下技術選擇:

 

1 分散式基礎進行架構SpringCloud Dubbo 之間二選一,由於 SpringCloud 更加知名, SpringCloud 的程式設計師更好招聘,有利於系統的長期運維升級,而且 SpringCloud 是基於 SpringBoot 開發,比較有親切感,所以選擇了 SpringCloud, 其實由於阿里系的強大影響,國內 Dubbo 使用更加廣泛,不同的團隊可以根據自己的情況選擇。

 

2 引入Hystrix 斷路器作為容錯保護模組,防止單個服務的故障,耗盡整個撮合系統容器的執行緒資源,避免分散式環境裡大量級聯失敗。對透過第三方客戶端訪問依賴服務出現失敗、拒絕、超時或短路時執行回退邏輯。

 

3 採用Eureka 作為服務註冊與發現中心,實現中間層服務,以達到負載均衡和中間層服務故障轉移的目的。

 

4 服務閘道器Spring Cloud Gateway Zuul 的選型,選擇了 Zuul ,因為名字短一些。

 

5 引入SpringCloud Security 安全認證模組用於構建安全的應用程式和服務, SpringCloud Security Spring Boot Spring Security OAuth2 的基礎上,可以快速建立和實現常見的安全認證方式,如單點登入,令牌中繼和令牌交換等。

 

6 引入Redis 作為記憶體資料庫,兼做系統資料快取和記憶體計算。

 

7 使用MySQL 作為關聯式資料庫,效能測試非常過關,而且對熟悉 MYSQL 的程式設計師非常友好。

 

8 訊息佇列中介軟體MQ 採用了 Kafka, 具有超高效能體現。

 

無論是股票交易系統,還是數字貨幣交易系統,都離不開撮合交易引擎,這是交易平臺的心臟。同時,一個優秀的架構設計也會讓交易平臺的運維和持續開發更加容易。

 

關於撮合交易引擎

採用記憶體撮合的方式進行,以Kafka 做撮合訂單資訊傳輸, MongoDB 持久化訂單成交明細, MySQL 記錄訂單總體成交。其中行情模組主要負責訂單成交持久化、行情生成、行情推送等服務,包括:

K 線資料,間隔分別為: 1 分鐘、 5 分鐘、 15 分鐘、 30 分鐘、 1 小時、 1 天、 1 周、 1

所有交易對的市場深度(market depth )資料

所有交易對的最新價格

最近成交的交易對

記憶體撮合交易支援的模式

限價訂單與限價訂單撮合

市價訂單與限價訂單撮合

限價訂單與市價訂單撮合

市價訂單與市價訂單撮合

 

數字貨幣交易所繫統開發示例程式碼如下:

 

/**

      * 限價委託單與限價佇列匹配

      * @param lpList 限價對手單佇列

      * @param focusedOrder 交易訂單

      */

     public void matchLimitPriceWithLPList(TreeMap<BigDecimal,MergeOrder> lpList, ExchangeOrder focusedOrder,boolean canEnterList){

         List<ExchangeTrade> exchangeTrades = new ArrayList<>();

         List<ExchangeOrder> completedOrders = new ArrayList<>();

         synchronized (lpList) {

             Iterator<Map.Entry<BigDecimal,MergeOrder>> mergeOrderIterator = lpList.entrySet().iterator();

             boolean exitLoop = false;

             while (!exitLoop && mergeOrderIterator.hasNext()) {

                 Map.Entry<BigDecimal,MergeOrder> entry = mergeOrderIterator.next();

                 MergeOrder mergeOrder = entry.getValue();

                 Iterator<ExchangeOrder> orderIterator = mergeOrder.iterator();

                 // 買入單需要匹配的價格不大於委託價,否則退出

                 if (focusedOrder.getDirection() == ExchangeOrderDirection.BUY && mergeOrder.getPrice().compareTo(focusedOrder.getPrice()) > 0) {

                     break;

                 }

                 // 賣出單需要匹配的價格不小於委託價,否則退出

                 if (focusedOrder.getDirection() == ExchangeOrderDirection.SELL && mergeOrder.getPrice().compareTo(focusedOrder.getPrice()) < 0) {

                     break;

                 }

                 while (orderIterator.hasNext()) {

                     ExchangeOrder matchOrder = orderIterator.next();

                     // 處理匹配

                     ExchangeTrade trade = processMatch(focusedOrder, matchOrder);

                     exchangeTrades.add(trade);

                     // 判斷匹配單是否完成

                     if (matchOrder.isCompleted()) {

                         // 當前匹配的訂單完成交易,刪除該訂單

                         orderIterator.remove();

                         completedOrders.add(matchOrder);

                     }

                     // 判斷交易單是否完成

                     if (focusedOrder.isCompleted()) {

                         // 交易完成

                         completedOrders.add(focusedOrder);

                         // 退出迴圈

                         exitLoop = true;

                         break;

                     }

                 }

                 if(mergeOrder.size() == 0){

                     mergeOrderIterator.remove();

                 }

             }

         }

         // 如果還沒有交易完,訂單壓入列表中

         if (focusedOrder.getTradedAmount().compareTo(focusedOrder.getAmount()) < 0 && canEnterList) {

             addLimitPriceOrder(focusedOrder);

         }

         // 每個訂單的匹配批次推送

         handleExchangeTrade(exchangeTrades);

         if(completedOrders.size() > 0){

             orderCompleted(completedOrders);

             TradePlate plate = focusedOrder.getDirection() == ExchangeOrderDirection.BUY ? sellTradePlate : buyTradePlate;

             sendTradePlateMessage(plate);

         }

     }

 

     /**

      * 限價委託單與市價佇列匹配

      * @param mpList 市價對手單佇列

      * @param focusedOrder 交易訂單

      */

     public void matchLimitPriceWithMPList(LinkedList<ExchangeOrder> mpList,ExchangeOrder focusedOrder){

         List<ExchangeTrade> exchangeTrades = new ArrayList<>();

         List<ExchangeOrder> completedOrders = new ArrayList<>();

         synchronized (mpList) {

             Iterator<ExchangeOrder> iterator = mpList.iterator();

             while (iterator.hasNext()) {

                 ExchangeOrder matchOrder = iterator.next();

                 ExchangeTrade trade = processMatch(focusedOrder, matchOrder);

                 logger.info(">>>>>"+trade);

                 if(trade != null){

                     exchangeTrades.add(trade);

                 }

                 // 判斷匹配單是否完成,市價單 amount 為成交量

                 if(matchOrder.isCompleted()){

                     iterator.remove();

                     completedOrders.add(matchOrder);

                 }

                 // 判斷吃單是否完成,判斷成交量是否完成

                 if (focusedOrder.isCompleted()) {

                     // 交易完成

                     completedOrders.add(focusedOrder);

                     // 退出迴圈

                     break;

                 }

             }

         }

         // 如果還沒有交易完,訂單壓入列表中

         if (focusedOrder.getTradedAmount().compareTo(focusedOrder.getAmount()) < 0) {

             addLimitPriceOrder(focusedOrder);

         }

         // 每個訂單的匹配批次推送

         handleExchangeTrade(exchangeTrades);

         orderCompleted(completedOrders);

     }

 

 

     /**

      * 市價委託單與限價對手單列表交易

      * @param lpList   限價對手單列表

      * @param focusedOrder 待交易訂單

      */

     public void matchMarketPriceWithLPList(TreeMap<BigDecimal,MergeOrder> lpList, ExchangeOrder focusedOrder){

         List<ExchangeTrade> exchangeTrades = new ArrayList<>();

         List<ExchangeOrder> completedOrders = new ArrayList<>();

         synchronized (lpList) {

             Iterator<Map.Entry<BigDecimal,MergeOrder>> mergeOrderIterator = lpList.entrySet().iterator();

             boolean exitLoop = false;

             while (!exitLoop && mergeOrderIterator.hasNext()) {

                 Map.Entry<BigDecimal,MergeOrder> entry = mergeOrderIterator.next();

                 MergeOrder mergeOrder = entry.getValue();

                 Iterator<ExchangeOrder> orderIterator = mergeOrder.iterator();

                 while (orderIterator.hasNext()) {

                     ExchangeOrder matchOrder = orderIterator.next();

                     // 處理匹配

                     ExchangeTrade trade = processMatch(focusedOrder, matchOrder);

                     if (trade != null) {

                         exchangeTrades.add(trade);

                     }

                     // 判斷匹配單是否完成

                     if (matchOrder.isCompleted()) {

                         // 當前匹配的訂單完成交易,刪除該訂單

                         orderIterator.remove();

                         completedOrders.add(matchOrder);

                     }

                     // 判斷焦點訂單是否完成

                     if (focusedOrder.isCompleted()) {

                         completedOrders.add(focusedOrder);

                         // 退出迴圈

                         exitLoop = true;

                         break;

                     }

                 }

                 if(mergeOrder.size() == 0){

                     mergeOrderIterator.remove();

                 }

             }

         }

         // 如果還沒有交易完,訂單壓入列表中 , 市價買單按成交量算

         if (focusedOrder.getDirection() == ExchangeOrderDirection.SELL&&focusedOrder.getTradedAmount().compareTo(focusedOrder.getAmount()) < 0

                 || focusedOrder.getDirection() == ExchangeOrderDirection.BUY&& focusedOrder.getTurnover().compareTo(focusedOrder.getAmount()) < 0) {

             addMarketPriceOrder(focusedOrder);

         }

         // 每個訂單的匹配批次推送

         handleExchangeTrade(exchangeTrades);

         if(completedOrders.size() > 0){

             orderCompleted(completedOrders);

             TradePlate plate = focusedOrder.getDirection() == ExchangeOrderDirection.BUY ? sellTradePlate : buyTradePlate;

             sendTradePlateMessage(plate);

         }

     }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70028290/viewspace-2944319/,如需轉載,請註明出處,否則將追究法律責任。

相關文章