1 package org.oxerr.okcoin.examples.fix;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.List;
6 import java.util.UUID;
7 import java.util.concurrent.TimeUnit;
8
9 import org.knowm.xchange.currency.CurrencyPair;
10 import org.knowm.xchange.dto.account.AccountInfo;
11 import org.knowm.xchange.dto.marketdata.OrderBook;
12 import org.knowm.xchange.dto.marketdata.Trade;
13 import org.knowm.xchange.dto.trade.LimitOrder;
14 import org.oxerr.okcoin.fix.fix44.ExceptionResponseMessage;
15 import org.oxerr.okcoin.fix.fix44.OKCoinMessageFactory;
16 import org.oxerr.okcoin.xchange.service.fix.OKCoinXChangeApplication;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 import quickfix.ConfigError;
21 import quickfix.FieldNotFound;
22 import quickfix.FileLogFactory;
23 import quickfix.FileStoreFactory;
24 import quickfix.IncorrectTagValue;
25 import quickfix.Initiator;
26 import quickfix.LogFactory;
27 import quickfix.MessageFactory;
28 import quickfix.MessageStoreFactory;
29 import quickfix.SessionID;
30 import quickfix.SessionSettings;
31 import quickfix.SocketInitiator;
32 import quickfix.UnsupportedMessageType;
33 import quickfix.field.MassStatusReqType;
34 import quickfix.fix44.ExecutionReport;
35
36
37
38
39 public class Client {
40
41 private static final Logger log = LoggerFactory.getLogger(Client.class);
42
43 private final OKCoinXChangeApplication app;
44 private final SessionID sessionId;
45 private final Initiator initiator;
46
47 public Client(String apiKey, String secretKey) throws IOException,
48 ConfigError, InterruptedException {
49 app = new OKCoinXChangeApplication(apiKey, secretKey) {
50
51 @Override
52 public void onLogon(SessionID sessionId) {
53 super.onLogon(sessionId);
54
55 String massStatusReqId = UUID.randomUUID().toString();
56 this.requestOrderMassStatus(massStatusReqId, MassStatusReqType.STATUS_FOR_ALL_ORDERS, sessionId);
57 }
58
59 @Override
60 public void onOrderBook(OrderBook orderBook, SessionID sessionId) {
61 log.info("asks: {}, bids: {}", orderBook.getAsks().size(), orderBook.getBids().size());
62
63
64 LimitOrder preOrder = null;
65 for (LimitOrder order : orderBook.getBids()) {
66 log.info("Bid: {}, {}", order.getLimitPrice(), order.getTradableAmount());
67
68 if (preOrder != null && preOrder.compareTo(order) >= 0) {
69 log.error("bids should be sorted by limit price descending");
70 }
71 preOrder = order;
72 }
73
74
75 preOrder = null;
76 for (LimitOrder order : orderBook.getAsks()) {
77 log.info("Ask: {}, {}", order.getLimitPrice(), order.getTradableAmount());
78
79 if (preOrder != null && preOrder.compareTo(order) >= 0) {
80 log.error("asks should be sorted by limit price ascending");
81 }
82 preOrder = order;
83 }
84
85 LimitOrder ask = orderBook.getAsks().get(0);
86 LimitOrder bid = orderBook.getBids().get(0);
87 log.info("lowest ask: {}, {}", ask.getLimitPrice(), ask.getTradableAmount());
88 log.info("highest bid: {}, {}", bid.getLimitPrice(), bid.getTradableAmount());
89
90 if (ask.getLimitPrice().compareTo(bid.getLimitPrice()) <= 0) {
91 throw new IllegalStateException(String.format("Lowest ask %s is not higher than the highest bid %s.",
92 ask.getLimitPrice(), bid.getLimitPrice()));
93 }
94 }
95
96 @Override
97 public void onTrades(List<Trade> trades, SessionID sessionId) {
98 for (Trade trade : trades) {
99 log.info("{}", trade);
100 }
101 }
102
103 @Override
104 public void onAccountInfo(AccountInfo accountInfo,
105 SessionID sessionId) {
106 log.info("AccountInfo: {}", accountInfo);
107 }
108
109 @Override
110 public void onMessage(ExecutionReport message, SessionID sessionId)
111 throws FieldNotFound, UnsupportedMessageType,
112 IncorrectTagValue {
113 log.info(message.toXML(getDataDictionary()));
114 }
115
116 @Override
117 public void onMessage(ExceptionResponseMessage message,
118 SessionID sessionId) throws FieldNotFound,
119 UnsupportedMessageType, IncorrectTagValue {
120 log.error(message.toXML(getDataDictionary()));
121 }
122
123 };
124
125 SessionSettings settings;
126 try (InputStream inputStream = getClass().getResourceAsStream("client.cfg")) {
127 settings = new SessionSettings(inputStream);
128 }
129
130 MessageStoreFactory storeFactory = new FileStoreFactory(settings);
131 LogFactory logFactory = new FileLogFactory(settings);
132 MessageFactory messageFactory = new OKCoinMessageFactory();
133 initiator = new SocketInitiator(app, storeFactory, settings,
134 logFactory, messageFactory);
135 initiator.start();
136
137 while (!initiator.isLoggedOn()) {
138 log.info("Waiting for logged on...");
139 TimeUnit.SECONDS.sleep(1);
140 }
141
142 sessionId = initiator.getSessions().get(0);
143 }
144
145 public void demo() {
146 String mdReqId = UUID.randomUUID().toString();
147 String symbol = "BTC/CNY";
148 app.subscribeOrderBook(CurrencyPair.BTC_CNY, sessionId);
149
150 mdReqId = UUID.randomUUID().toString();
151 app.requestLiveTrades(mdReqId, symbol, sessionId);
152
153 mdReqId = UUID.randomUUID().toString();
154 app.request24HTicker(mdReqId, symbol, sessionId);
155
156 String accReqId = UUID.randomUUID().toString();
157 app.requestAccountInfo(accReqId, sessionId);
158
159 String tradeRequestId = UUID.randomUUID().toString();
160 long orderId = 1;
161 char ordStatus = '0';
162 app.requestOrdersInfoAfterSomeID(tradeRequestId, symbol, orderId, ordStatus, sessionId);
163
164
165 app.requestOrderMassStatus("2147488076",
166 MassStatusReqType.STATUS_FOR_ORDERS_FOR_A_SECURITY, sessionId);
167
168 }
169
170 public static void main(String[] args) throws IOException, ConfigError,
171 InterruptedException {
172 String apiKey = args[0], secretKey = args[1];
173 Client client = new Client(apiKey, secretKey);
174 client.demo();
175
176 log.info("Waiting a moment and exiting.");
177 TimeUnit.SECONDS.sleep(30);
178 client.initiator.stop();
179 }
180
181 }