├── .gitignore ├── README.md ├── pom.xml └── src └── main └── java └── com └── oanda └── v20 └── v20sample ├── AccountUpdateLoop.java ├── Config.java ├── PricePolling.java ├── StepByStepOrder.java ├── TestFailureException.java └── TestTradesAndOrders.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw* 2 | *~ 3 | target/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v20-java-samples 2 | Some sample applications using the v20 java libraries 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.oanda.v20 4 | v20sample 5 | 1.0.0 6 | 7 | 8 | UTF-8 9 | 1.8 10 | 1.8 11 | 12 | 13 | v20sample 14 | 15 | 16 | 17 | 18 | maven-assembly-plugin 19 | 3.0.0 20 | 21 | 22 | jar-with-dependencies 23 | 24 | 25 | 26 | 27 | make-assembly 28 | package 29 | 30 | single 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | A simple app to test the v20 java library 39 | 40 | 41 | 42 | com.oanda.v20 43 | v20 44 | 3.0.24 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/com/oanda/v20/v20sample/AccountUpdateLoop.java: -------------------------------------------------------------------------------- 1 | package com.oanda.v20.v20sample; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.oanda.v20.Context; 7 | import com.oanda.v20.ContextBuilder; 8 | import com.oanda.v20.account.Account; 9 | import com.oanda.v20.account.AccountChanges; 10 | import com.oanda.v20.account.AccountChangesRequest; 11 | import com.oanda.v20.account.AccountChangesResponse; 12 | import com.oanda.v20.account.AccountChangesState; 13 | import com.oanda.v20.account.AccountGetResponse; 14 | import com.oanda.v20.account.AccountID; 15 | import com.oanda.v20.order.DynamicOrderState; 16 | import com.oanda.v20.order.Order; 17 | import com.oanda.v20.order.OrderID; 18 | import com.oanda.v20.order.TrailingStopLossOrder; 19 | import com.oanda.v20.position.CalculatedPositionState; 20 | import com.oanda.v20.position.Position; 21 | import com.oanda.v20.primitives.InstrumentName; 22 | import com.oanda.v20.trade.CalculatedTradeState; 23 | import com.oanda.v20.trade.TradeID; 24 | import com.oanda.v20.trade.TradeSummary; 25 | import com.oanda.v20.transaction.TransactionID; 26 | 27 | public class AccountUpdateLoop { 28 | 29 | public static void main(String[] args) { 30 | Context ctx = new ContextBuilder(Config.URL) 31 | .setToken(Config.TOKEN) 32 | .setApplication("AccountUpdateLoop") 33 | .build(); 34 | 35 | AccountID accountId = Config.ACCOUNTID; 36 | 37 | // Get initial account state 38 | try { 39 | AccountGetResponse accountStateResponse = ctx.account.get(accountId); 40 | Account account = accountStateResponse.getAccount(); 41 | TransactionID lastTransactionId = accountStateResponse.getLastTransactionID(); 42 | 43 | while (true) { 44 | System.out.println("Polling from "+lastTransactionId); 45 | AccountChangesResponse resp = ctx.account.changes( 46 | new AccountChangesRequest(accountId) 47 | .setSinceTransactionID(lastTransactionId) 48 | ); 49 | lastTransactionId = resp.getLastTransactionID(); 50 | 51 | AccountChanges changes = resp.getChanges(); 52 | applyAccountChanges(account, changes); 53 | 54 | AccountChangesState updatedstate = resp.getState(); 55 | applyAccountChangesState(account, updatedstate); 56 | Thread.sleep(1000); 57 | } 58 | } catch (Exception e) { 59 | throw new RuntimeException(e); 60 | } 61 | } 62 | 63 | private static void applyAccountChanges( 64 | Account account, AccountChanges changes 65 | ) { 66 | System.out.println("Account Changes:"); 67 | System.out.println(changes); 68 | 69 | Map ordermap = new HashMap<>(); 70 | 71 | for (Order order : account.getOrders()) 72 | ordermap.put(order.getId(), order); 73 | 74 | for (Order created : changes.getOrdersCreated()) 75 | ordermap.put(created.getId(), created); 76 | for (Order cancelled : changes.getOrdersCancelled()) 77 | ordermap.remove(cancelled.getId()); 78 | for (Order filled : changes.getOrdersFilled()) 79 | ordermap.remove(filled.getId()); 80 | for (Order triggered : changes.getOrdersTriggered()) 81 | ordermap.remove(triggered.getId()); 82 | 83 | account.setOrders(ordermap.values()); 84 | 85 | Map trademap = new HashMap<>(); 86 | 87 | for (TradeSummary trade : account.getTrades()) 88 | trademap.put(trade.getId(), trade); 89 | 90 | for (TradeSummary opened : changes.getTradesOpened()) 91 | trademap.put(opened.getId(), opened); 92 | for (TradeSummary reduced : changes.getTradesReduced()) 93 | trademap.put(reduced.getId(),reduced); 94 | for (TradeSummary closed : changes.getTradesClosed()) 95 | trademap.remove(closed.getId()); 96 | 97 | account.setTrades(trademap.values()); 98 | 99 | Map positionMap = new HashMap<>(); 100 | 101 | for (Position position : account.getPositions()) 102 | positionMap.put(position.getInstrument(), position); 103 | 104 | for (Position position : changes.getPositions()) 105 | positionMap.put(position.getInstrument(), position); 106 | 107 | account.setPositions(positionMap.values()); 108 | } 109 | 110 | private static void applyAccountChangesState( 111 | Account account, AccountChangesState updatedstate 112 | ) { 113 | System.out.println("Account Changes State:"); 114 | System.out.println(updatedstate); 115 | 116 | if (updatedstate.getUnrealizedPL() != null) 117 | account.setUnrealizedPL(updatedstate.getUnrealizedPL()); 118 | if (updatedstate.getNAV() != null) 119 | account.setNAV(updatedstate.getNAV()); 120 | if (updatedstate.getMarginUsed() != null) 121 | account.setMarginUsed(updatedstate.getMarginUsed()); 122 | if (updatedstate.getMarginAvailable() != null) 123 | account.setMarginAvailable(updatedstate.getMarginAvailable()); 124 | if (updatedstate.getPositionValue() != null) 125 | account.setPositionValue(updatedstate.getPositionValue()); 126 | if (updatedstate.getMarginCloseoutUnrealizedPL() != null) 127 | account.setMarginCloseoutUnrealizedPL( 128 | updatedstate.getMarginCloseoutUnrealizedPL() 129 | ); 130 | if (updatedstate.getMarginCloseoutNAV() != null) 131 | account.setMarginCloseoutNAV(updatedstate.getMarginCloseoutNAV()); 132 | if (updatedstate.getMarginCloseoutMarginUsed() != null) 133 | account.setMarginCloseoutMarginUsed( 134 | updatedstate.getMarginCloseoutMarginUsed() 135 | ); 136 | if (updatedstate.getMarginCloseoutPercent() != null) 137 | account.setMarginCloseoutPercent( 138 | updatedstate.getMarginCloseoutPercent() 139 | ); 140 | if (updatedstate.getMarginCloseoutPositionValue() != null) 141 | account.setMarginCloseoutPositionValue( 142 | updatedstate.getMarginCloseoutPositionValue() 143 | ); 144 | if (updatedstate.getWithdrawalLimit() != null) 145 | account.setWithdrawalLimit(updatedstate.getWithdrawalLimit()); 146 | if (updatedstate.getMarginCallMarginUsed() != null) 147 | account.setMarginCallMarginUsed( 148 | updatedstate.getMarginCallMarginUsed() 149 | ); 150 | if (updatedstate.getMarginCallPercent() != null) 151 | account.setMarginCallPercent(updatedstate.getMarginCallPercent()); 152 | 153 | Map ordermap = new HashMap<>(); 154 | 155 | for (Order order : account.getOrders()) 156 | ordermap.put(order.getId(), order); 157 | for (DynamicOrderState orderstate : updatedstate.getOrders()) { 158 | TrailingStopLossOrder order = (TrailingStopLossOrder) ordermap.get( 159 | orderstate.getId() 160 | ); 161 | order.setTrailingStopValue(orderstate.getTrailingStopValue()); 162 | } 163 | 164 | Map trademap = new HashMap<>(); 165 | 166 | for (TradeSummary trade : account.getTrades()) 167 | trademap.put(trade.getId(), trade); 168 | for (CalculatedTradeState tradestate : updatedstate.getTrades()) { 169 | TradeSummary trade = trademap.get(tradestate.getId()); 170 | trade.setUnrealizedPL(tradestate.getUnrealizedPL()); 171 | } 172 | 173 | Map posmap = new HashMap<>(); 174 | 175 | for (Position pos : account.getPositions()) 176 | posmap.put(pos.getInstrument(),pos); 177 | for (CalculatedPositionState posstate : updatedstate.getPositions()) { 178 | Position pos = posmap.get(posstate.getInstrument()); 179 | pos.setInstrument(posstate.getInstrument()); 180 | pos.setUnrealizedPL(posstate.getNetUnrealizedPL()); 181 | pos.getLong().setUnrealizedPL(posstate.getLongUnrealizedPL()); 182 | pos.getShort().setUnrealizedPL(posstate.getShortUnrealizedPL()); 183 | } 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/oanda/v20/v20sample/Config.java: -------------------------------------------------------------------------------- 1 | package com.oanda.v20.v20sample; 2 | 3 | import com.oanda.v20.account.AccountID; 4 | import com.oanda.v20.primitives.InstrumentName; 5 | 6 | /** 7 | * This is the configuration object used by the various examples to connect to 8 | * one of the OANDA trading systems. Please fill them in with sane values. 9 | * 10 | * @param URL The fxTrade or fxPractice API URL 11 | * @param TOKEN The OANDA API Personal Access token 12 | * @param ACCOUNTID A valid v20 trading account ID that {@code TOKEN} has 13 | * permissions to take action on 14 | * @param INSTRUMENT A valid tradeable instrument for the given {@code 15 | * ACCOUNTID} 16 | */ 17 | public class Config { 18 | private Config() {} 19 | public static final String URL = "<< URL >>"; 20 | public static final String TOKEN = "<< TOKEN >>"; 21 | public static final AccountID ACCOUNTID = new AccountID("<< ACCOUNTID >>"); 22 | public static final InstrumentName INSTRUMENT = new InstrumentName("<< INSTRUMENT >>"); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/oanda/v20/v20sample/PricePolling.java: -------------------------------------------------------------------------------- 1 | package com.oanda.v20.v20sample; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import com.oanda.v20.Context; 8 | import com.oanda.v20.ContextBuilder; 9 | import com.oanda.v20.account.AccountID; 10 | import com.oanda.v20.pricing.ClientPrice; 11 | import com.oanda.v20.pricing.PricingGetRequest; 12 | import com.oanda.v20.pricing.PricingGetResponse; 13 | import com.oanda.v20.primitives.DateTime; 14 | 15 | public class PricePolling { 16 | 17 | public static void main(String[] args) { 18 | Context ctx = new ContextBuilder(Config.URL) 19 | .setToken(Config.TOKEN) 20 | .setApplication("PricePolling") 21 | .build(); 22 | 23 | AccountID accountId = Config.ACCOUNTID; 24 | List instruments = new ArrayList<>( 25 | Arrays.asList("EUR_USD", "USD_JPY", "GBP_USD", "USD_CHF")); 26 | 27 | // Poll for prices 28 | try { 29 | PricingGetRequest request = new PricingGetRequest(accountId, instruments); 30 | 31 | DateTime since = null; 32 | 33 | while (true) { 34 | if (since != null) 35 | { 36 | System.out.println("Polling since " + since); 37 | request.setSince(since); 38 | } 39 | PricingGetResponse resp = ctx.pricing.get(request); 40 | 41 | for (ClientPrice price : resp.getPrices()) 42 | System.out.println(price); 43 | since = resp.getTime(); 44 | 45 | Thread.sleep(1000); 46 | } 47 | } catch (Exception e) { 48 | throw new RuntimeException(e); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/oanda/v20/v20sample/StepByStepOrder.java: -------------------------------------------------------------------------------- 1 | package com.oanda.v20.v20sample; 2 | 3 | import java.util.List; 4 | 5 | import com.oanda.v20.Context; 6 | import com.oanda.v20.ContextBuilder; 7 | import com.oanda.v20.account.Account; 8 | import com.oanda.v20.account.AccountGetResponse; 9 | import com.oanda.v20.account.AccountID; 10 | import com.oanda.v20.account.AccountListResponse; 11 | import com.oanda.v20.account.AccountProperties; 12 | import com.oanda.v20.order.MarketOrderRequest; 13 | import com.oanda.v20.order.OrderCreateRequest; 14 | import com.oanda.v20.order.OrderCreateResponse; 15 | import com.oanda.v20.primitives.InstrumentName; 16 | import com.oanda.v20.trade.TradeCloseRequest; 17 | import com.oanda.v20.trade.TradeCloseResponse; 18 | import com.oanda.v20.trade.TradeSpecifier; 19 | import com.oanda.v20.transaction.OrderFillTransaction; 20 | import com.oanda.v20.transaction.TradeReduce; 21 | import com.oanda.v20.transaction.TransactionID; 22 | 23 | /** 24 | * This is a brief example that explicitly shows each step in the process of preparing, 25 | * executing, and processing results from a few different queries. This style is only 26 | * for demonstration purposes and is therefore overly verbose. 27 | *

28 | * For the idiomatic style, see {@link TestTradesAndOrders} 29 | *

30 | * @author gentili 31 | * 32 | */ 33 | public abstract class StepByStepOrder { 34 | 35 | public static void main(String[] args) { 36 | Context ctx = new ContextBuilder(Config.URL) 37 | .setToken(Config.TOKEN) 38 | .setApplication("StepByStepOrder") 39 | .build(); 40 | 41 | AccountID accountId = Config.ACCOUNTID; 42 | InstrumentName tradeableInstrument = Config.INSTRUMENT; 43 | 44 | // EXAMPLE: No parameters 45 | System.out.println("Make sure we have a valid account"); 46 | try { 47 | // Execute the request and obtain a response object 48 | AccountListResponse response = ctx.account.list(); 49 | // Retrieve account list from response object 50 | List accountProperties; 51 | accountProperties = response.getAccounts(); 52 | // Check for the configured account 53 | boolean hasaccount = false; 54 | for (AccountProperties account : accountProperties) { 55 | if (account.getId().equals(accountId)) 56 | hasaccount = true; 57 | } 58 | if (!hasaccount) 59 | throw new TestFailureException("Account "+accountId+" not found"); 60 | } catch (Exception e) { 61 | throw new RuntimeException(e); 62 | } 63 | 64 | // EXAMPLE: URL path parameter 65 | System.out.println("Make sure the account has a non zero balance"); 66 | try { 67 | // Execute the request and retrieve a response object 68 | AccountGetResponse response = ctx.account.get(accountId); 69 | // Retrieve the contents of the result 70 | Account account; 71 | account = response.getAccount(); 72 | // Check the balance 73 | if (account.getBalance().doubleValue() <= 0.0) 74 | throw new TestFailureException("Account "+accountId+" balance "+account.getBalance()+" <= 0"); 75 | } catch (Exception e) { 76 | throw new RuntimeException(e); 77 | } 78 | // EXAMPLE: Complex body parameter 79 | System.out.println("Place a Market Order"); 80 | TransactionID tradeId; 81 | try { 82 | // Create the new request 83 | OrderCreateRequest request = new OrderCreateRequest(accountId); 84 | // Create the required body parameter 85 | MarketOrderRequest marketorderrequest = new MarketOrderRequest(); 86 | // Populate the body parameter fields 87 | marketorderrequest.setInstrument(tradeableInstrument); 88 | marketorderrequest.setUnits(10); 89 | // Attach the body parameter to the request 90 | request.setOrder(marketorderrequest); 91 | // Execute the request and obtain the response object 92 | OrderCreateResponse response = ctx.order.create(request); 93 | // Extract the Order Fill transaction for the executed Market Order 94 | OrderFillTransaction transaction = response.getOrderFillTransaction(); 95 | // Extract the trade ID of the created trade from the transaction and keep it for future action 96 | tradeId = transaction.getId(); 97 | } catch (Exception e) { 98 | throw new RuntimeException(e); 99 | } 100 | // EXAMPLE: Take action on existing entity 101 | System.out.println("Close a Trade"); 102 | try { 103 | // Execute the request and retrieve the response object 104 | TradeCloseResponse response = ctx.trade.close( 105 | new TradeCloseRequest(accountId, new TradeSpecifier(tradeId.toString()))); 106 | // Extract the order fill transaction describing the trade close action 107 | OrderFillTransaction transaction = response.getOrderFillTransaction(); 108 | // Extract the list of trades that were closed by the request 109 | List trades = transaction.getTradesClosed(); 110 | // Check if single trade closed 111 | if (trades.size() != 1) 112 | throw new TestFailureException("Only 1 trade was expected to be closed"); 113 | // Extract the single closed trade 114 | TradeReduce trade = trades.get(0); 115 | // Check if trade closed was the one we asked to be closed 116 | if (!trade.getTradeID().equals(tradeId)) 117 | throw new TestFailureException("The wrong trade was closed"); 118 | } catch (Exception e) { 119 | throw new RuntimeException(e); 120 | } 121 | System.out.println("Done"); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/oanda/v20/v20sample/TestFailureException.java: -------------------------------------------------------------------------------- 1 | package com.oanda.v20.v20sample; 2 | 3 | public class TestFailureException extends RuntimeException { 4 | private static final long serialVersionUID = 1L; 5 | 6 | public TestFailureException(String message) { 7 | super("FAILURE:"+message); 8 | } 9 | 10 | public TestFailureException(Exception e) { 11 | super(e); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/oanda/v20/v20sample/TestTradesAndOrders.java: -------------------------------------------------------------------------------- 1 | package com.oanda.v20.v20sample; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import com.oanda.v20.Context; 7 | import com.oanda.v20.ContextBuilder; 8 | import com.oanda.v20.ExecuteException; 9 | import com.oanda.v20.RequestException; 10 | import com.oanda.v20.account.Account; 11 | import com.oanda.v20.account.AccountConfigure400RequestException; 12 | import com.oanda.v20.account.AccountConfigureResponse; 13 | import com.oanda.v20.account.AccountID; 14 | import com.oanda.v20.account.AccountProperties; 15 | import com.oanda.v20.order.LimitOrderRequest; 16 | import com.oanda.v20.order.MarketOrderRequest; 17 | import com.oanda.v20.order.Order; 18 | import com.oanda.v20.order.OrderCreateRequest; 19 | import com.oanda.v20.order.OrderCreateResponse; 20 | import com.oanda.v20.order.OrderID; 21 | import com.oanda.v20.order.OrderReplace400RequestException; 22 | import com.oanda.v20.order.OrderReplaceRequest; 23 | import com.oanda.v20.order.OrderReplaceResponse; 24 | import com.oanda.v20.order.OrderSpecifier; 25 | import com.oanda.v20.order.OrderState; 26 | import com.oanda.v20.order.OrderType; 27 | import com.oanda.v20.order.StopOrderRequest; 28 | import com.oanda.v20.position.Position; 29 | import com.oanda.v20.position.PositionCloseRequest; 30 | import com.oanda.v20.pricing.ClientPrice; 31 | import com.oanda.v20.primitives.Instrument; 32 | import com.oanda.v20.primitives.InstrumentName; 33 | import com.oanda.v20.trade.Trade; 34 | import com.oanda.v20.trade.TradeCloseRequest; 35 | import com.oanda.v20.trade.TradeSetClientExtensionsRequest; 36 | import com.oanda.v20.trade.TradeSetDependentOrdersRequest; 37 | import com.oanda.v20.trade.TradeSpecifier; 38 | import com.oanda.v20.trade.TradeState; 39 | import com.oanda.v20.transaction.ClientExtensions; 40 | import com.oanda.v20.transaction.OrderCancelTransaction; 41 | import com.oanda.v20.transaction.OrderFillTransaction; 42 | import com.oanda.v20.transaction.TakeProfitDetails; 43 | import com.oanda.v20.transaction.TakeProfitOrderTransaction; 44 | import com.oanda.v20.transaction.TradeClientExtensionsModifyTransaction; 45 | import com.oanda.v20.transaction.TradeReduce; 46 | import com.oanda.v20.transaction.Transaction; 47 | import com.oanda.v20.transaction.TransactionID; 48 | import com.oanda.v20.transaction.TransactionType; 49 | 50 | /** 51 | * This is a small sample application that demonstrates idiomatic usage of the v20 java library, 52 | * including chained method calls and exception handling. 53 | *

54 | * For a step by step breakdown of the actions of individual requests see {@link StepByStepOrder} 55 | *

56 | * @author Michael Gentili 57 | */ 58 | public class TestTradesAndOrders { 59 | 60 | Context ctx = new ContextBuilder(Config.URL) 61 | .setToken(Config.TOKEN) 62 | .setApplication("TestTradesAndOrders") 63 | .build(); 64 | 65 | AccountID accountId = Config.ACCOUNTID; 66 | InstrumentName tradeableInstrument = Config.INSTRUMENT; 67 | 68 | public static void main(String[] args) { 69 | try { 70 | new TestTradesAndOrders().runTest(); 71 | } catch (ExecuteException | RequestException e) { 72 | throw new TestFailureException(e); 73 | } 74 | } 75 | 76 | private void runTest() throws ExecuteException, RequestException 77 | { 78 | System.out.println("TEST - GET /accounts"); 79 | System.out.println("CHECK 200 - The list of authorized AccoungetInstrumentsts has been provided, expecting "+accountId+" in list."); 80 | 81 | List accountProperties = ctx.account.list().getAccounts(); 82 | boolean hasaccount = false; 83 | for (AccountProperties account : accountProperties) { 84 | if (account.getId().equals(accountId)) { 85 | hasaccount = true; 86 | break; 87 | } 88 | } 89 | if (!hasaccount) 90 | throw new RuntimeException("Account "+accountId+" not found"); 91 | 92 | System.out.println("TEST - GET /accounts/{accountID}"); 93 | System.out.println("CHECK 200 - The full Account details are provided, expecting balance > 0."); 94 | TransactionID firstTransId; // Store the last transaction that happened before this session 95 | 96 | Account account = ctx.account.get(accountId).getAccount(); 97 | firstTransId = account.getLastTransactionID(); 98 | if (account.getBalance().doubleValue() <= 0.0) 99 | throw new TestFailureException("Account "+accountId+" balance "+account.getBalance()+" <= 0"); 100 | 101 | // get /accounts/{accountID}/summary 102 | // ctx.account.summary(); 103 | // 200 - The Account summary are provided 104 | 105 | System.out.println ("TEST - GET /accounts/{accountID}/instruments"); 106 | System.out.println ("CHECK 200 - The list of tradeable instruments for the Account has been provided, expecting "+tradeableInstrument+" is tradeable."); 107 | 108 | List instruments = ctx.account.instruments(accountId).getInstruments(); 109 | boolean istradeable = false; 110 | for (Instrument instrument : instruments) { 111 | if (instrument.getName().equals(tradeableInstrument)) { 112 | istradeable = true; 113 | break; 114 | } 115 | } 116 | if (!istradeable) 117 | throw new TestFailureException("Instrument "+tradeableInstrument+" is not tradeable"); 118 | 119 | System.out.println("TEST - PATCH /accounts/{accountID}/configuration"); 120 | System.out.println("CHECK 400 - The Account could not be configured successfully, expecting [must specify parameter] exception."); 121 | try { 122 | AccountConfigureResponse result = ctx.account.configure(accountId); 123 | throw new TestFailureException("Unexpected Success:" + result.getClientConfigureTransaction()); 124 | } catch (AccountConfigure400RequestException e) { 125 | // PASS 126 | } 127 | 128 | // 200 - The Account was configured successfully. 129 | 130 | // get /accounts/{accountID}/changes 131 | // ctx.account.changes(); 132 | // 200 - The Account state and changes are provided. 133 | 134 | // get /users/{userSpecifier} 135 | // ctx.user.getInfo(); 136 | // 200 - The user information has been provided 137 | 138 | // get /users/{userSpecifier}/externalInfo 139 | // ctx.user.getExternalInfo(); 140 | // 200 - The external user information has been provided 141 | 142 | // get /accounts/{accountID}/positions 143 | // ctx.position.list(); 144 | // 200 - The Account's Positions are provided. 145 | 146 | // get /accounts/{accountID}/positions/{instrument} 147 | // ctx.position.get(); 148 | // 200 - The Position is provided. 149 | 150 | 151 | // get /accounts/{accountID}/transactions 152 | // ctx.transaction.list(); 153 | // 200 - The requested time range of Transaction pages are provided. 154 | 155 | // get /accounts/{accountID}/transactions/{transactionID} 156 | // ctx.transaction.get(); 157 | // 200 - The details of the requested Transaction are provided. 158 | 159 | // get /accounts/{accountID}/transactions/idrange 160 | // ctx.transaction.range(); 161 | // 200 - The requested time range of Transactions are provided. 162 | 163 | System.out.println("TEST - GET /accounts/{accountID}/openTrades"); 164 | System.out.println("CHECK 200 - The Account's list of open Trades is provided, expecting 0 open trades."); 165 | 166 | List trades = ctx.trade.listOpen(accountId).getTrades(); 167 | if (trades.size() > 0) 168 | throw new TestFailureException("Expected 0 open trades, account has "+trades.size()); 169 | 170 | System.out.println("TEST - POST /accounts/{accountID}/orders"); 171 | System.out.println("CHECK 201 - The Order was created as specified, expecting MarketOrder creation"); 172 | TransactionID orderTransId; 173 | TransactionID tradeTransId; 174 | 175 | OrderCreateResponse resp = ctx.order.create(new OrderCreateRequest(accountId) 176 | .setOrder(new MarketOrderRequest() 177 | .setInstrument(tradeableInstrument) 178 | .setUnits(10) 179 | ) 180 | ); 181 | Transaction orderTrans = resp.getOrderCreateTransaction(); 182 | if (orderTrans.getType() != TransactionType.MARKET_ORDER) 183 | throw new TestFailureException("Created order type "+ orderTrans.getType() + " != MARKET"); 184 | orderTransId = resp.getOrderCreateTransaction().getId(); 185 | tradeTransId = resp.getOrderFillTransaction().getId(); 186 | 187 | System.out.println("TEST - PUT /accounts/{accountID}/trades/{tradeSpecifier}/clientExtensions"); 188 | System.out.println("CHECK 200 - The Trade's Client Extensions have been updated as requested, expecting tag and comment to match what was set."); 189 | 190 | TradeClientExtensionsModifyTransaction trans = ctx.trade.setClientExtensions( 191 | new TradeSetClientExtensionsRequest(accountId, new TradeSpecifier(tradeTransId)) 192 | .setClientExtensions(new ClientExtensions() 193 | .setComment("this is a good trade") 194 | .setTag("good") 195 | ) 196 | ).getTradeClientExtensionsModifyTransaction(); 197 | if (!trans.getTradeClientExtensionsModify().getTag().equals("good")) 198 | throw new TestFailureException("Tag "+trans.getTradeClientExtensionsModify().getTag()+" != good"); 199 | 200 | System.out.println("TEST - PUT /accounts/{accountID}/trades/{tradeSpecifier}/orders"); 201 | System.out.println("CHECK 200 - The Trade's dependent Orders have been modified as requested, expecting pending TP with matching tradeId"); 202 | 203 | TakeProfitOrderTransaction tp = ctx.trade.setDependentOrders( 204 | new TradeSetDependentOrdersRequest(accountId, new TradeSpecifier(tradeTransId)) 205 | .setTakeProfit(new TakeProfitDetails().setPrice(2.0)) 206 | ).getTakeProfitOrderTransaction(); 207 | if (!tp.getTradeID().equals(tradeTransId)) 208 | throw new TestFailureException("Dependent tradeId "+tp.getTradeID()+" != "+tradeTransId); 209 | 210 | System.out.println("TEST - PUT /accounts/{accountID}/trades/{tradeSpecifier}/orders"); 211 | System.out.println("CHECK 200 - The Trade's dependent Orders have been modified as requested, expecting TP to be removed"); 212 | 213 | OrderCancelTransaction oc = ctx.trade.setDependentOrders( 214 | new TradeSetDependentOrdersRequest(accountId, new TradeSpecifier(tradeTransId)) 215 | .setTakeProfit(null) 216 | ).getTakeProfitOrderCancelTransaction(); 217 | if (!oc.getOrderID().equals(tp.getId())) 218 | throw new TestFailureException("Dependent orderId "+oc.getOrderID()+" != "+tp.getId()); 219 | 220 | System.out.println("TEST - GET /accounts/{accountID}/pricing/{instruments}"); 221 | System.out.println("CHECK 200 - Pricing information has been successfully provided."); 222 | 223 | String[] instrumentNames = {"USD_CAD", "GBP_USD"}; 224 | List prices = ctx.pricing.get(accountId, Arrays.asList(instrumentNames)).getPrices(); 225 | 226 | System.out.println("TEST - GET /accounts/{accountID}/orders/{orderSpecifier}"); 227 | System.out.println("CHECK 200 - The details of the Order requested match the order placed, expecting FILLED MARKET order."); 228 | 229 | Order order = ctx.order.get(accountId, new OrderSpecifier(orderTransId)).getOrder(); 230 | if (order.getType() != OrderType.MARKET) 231 | throw new TestFailureException("Order type "+order.getType()+" != MARKET"); 232 | if (order.getState() != OrderState.FILLED) 233 | throw new TestFailureException("Order state not filled"); 234 | 235 | System.out.println("TEST - GET /accounts/{accountID}/trades"); 236 | System.out.println("CHECK 200 - The list of trades requested, expecting the previously executed order in list."); 237 | 238 | trades = ctx.trade.list(accountId).getTrades(); 239 | boolean hastrade = false; 240 | for (Trade trade : trades) { 241 | if (trade.getId().equals(tradeTransId)) { 242 | hastrade = true; 243 | break; 244 | } 245 | } 246 | if (!hastrade) { 247 | throw new TestFailureException("Expected tradeId not in list"); 248 | } 249 | 250 | System.out.println("TEST - PUT /accounts/{accountID}/trades/{tradeSpecifier}/close"); 251 | System.out.println("CHECK 200 - The Trade has been closed as requested, expecting single close trade."); 252 | 253 | List reducedTrades = ctx.trade.close( 254 | new TradeCloseRequest(accountId, new TradeSpecifier(tradeTransId)) 255 | ).getOrderFillTransaction().getTradesClosed(); 256 | if (reducedTrades.size() != 1) 257 | throw new TestFailureException("Expecting 1 close trade, got "+reducedTrades.size()); 258 | if (!reducedTrades.get(0).getTradeID().equals(tradeTransId)) 259 | throw new TestFailureException("Closed trade "+reducedTrades.get(0).getTradeID()+ " doesn't match expected "+tradeTransId); 260 | 261 | System.out.println("TEST - GET /accounts/{accountID}/trades/{tradeSpecifier}"); 262 | System.out.println("CHECK 200 - The details for the requested Trade is provided, expecting CLOSED state"); 263 | 264 | Trade trade = ctx.trade.get(accountId, new TradeSpecifier(tradeTransId)).getTrade(); 265 | if (trade.getState() != TradeState.CLOSED) 266 | throw new TestFailureException("Trade state "+trade.getState()+" != CLOSED"); 267 | 268 | System.out.println("TEST - GET /accounts/{accountID}/pendingOrders"); 269 | System.out.println("CHECK 200 - List of pending Orders for the Account, expecting 0 pending"); 270 | 271 | List orders = ctx.order.listPending(accountId).getOrders(); 272 | if (orders.size() > 0) 273 | throw new TestFailureException("Expected 0 pending orders, received "+orders.size()); 274 | 275 | System.out.println("TEST - POST /accounts/{accountID}/orders"); 276 | System.out.println("CHECK 201 - The Order was created as specified, expecting LimitOrder creation"); 277 | 278 | resp = ctx.order.create(new OrderCreateRequest(accountId) 279 | .setOrder( 280 | new LimitOrderRequest() 281 | .setInstrument(tradeableInstrument) 282 | .setUnits(10) 283 | .setPrice(1.0) 284 | )); 285 | orderTrans = resp.getOrderCreateTransaction(); 286 | if (orderTrans.getType() != TransactionType.LIMIT_ORDER) 287 | throw new TestFailureException("Created order type "+ orderTrans.getType() + " != LIMIT_ORDER"); 288 | orderTransId = resp.getOrderCreateTransaction().getId(); 289 | 290 | System.out.println("TEST - PUT /accounts/{accountID}/orders/{orderSpecifier}"); 291 | System.out.println("CHECK 400 - The Order specification was invalid, expecting REPLACING_ORDER_INVALID"); 292 | 293 | try { 294 | ctx.order.replace(new OrderReplaceRequest(accountId, new OrderSpecifier(orderTransId)) 295 | .setOrder( 296 | new StopOrderRequest() 297 | .setInstrument(tradeableInstrument) 298 | .setUnits(10) 299 | .setPrice(1.0) 300 | ) 301 | ); 302 | throw new TestFailureException("Unexpected success replacing LimitOrder"); 303 | } catch (OrderReplace400RequestException e) { 304 | System.out.println(e.getErrorCode()+ " " +e.getErrorMessage()); 305 | if (!e.getErrorCode().equals("REPLACING_ORDER_INVALID")) { 306 | throw new TestFailureException("Unexpected errorCode "+e.getErrorCode()+" in expected exception"); 307 | } 308 | } 309 | 310 | System.out.println("CHECK 201 - The Order was successfully cancelled and replaced, expecting triggered and closed LimitOrder"); 311 | 312 | OrderReplaceResponse replaceResp = ctx.order.replace( 313 | new OrderReplaceRequest(accountId, new OrderSpecifier(orderTransId)) 314 | .setOrder( 315 | new LimitOrderRequest() 316 | .setInstrument(tradeableInstrument) 317 | .setUnits(10) 318 | .setPrice(2.0) 319 | .setTakeProfitOnFill( 320 | new TakeProfitDetails() 321 | .setPrice(2.0) 322 | ) 323 | ) 324 | ); 325 | OrderFillTransaction fillTrans = replaceResp.getOrderFillTransaction(); 326 | double units = fillTrans.getTradeOpened().getUnits().doubleValue(); 327 | if (units != 10) 328 | throw new TestFailureException("Expected open trade units "+units+" != 10"); 329 | 330 | System.out.println("TEST - GET /accounts/{accountID}/orders"); 331 | System.out.println("CHECK 200 - The list of Orders requested, expecting 1 TakeProfit"); 332 | 333 | orders = ctx.order.list(accountId).getOrders(); 334 | if (orders.size() != 1) 335 | throw new TestFailureException("Expected order count "+orders.size()+" != 1"); 336 | order = orders.get(0); 337 | OrderID orderId = order.getId(); 338 | if (order.getType() != OrderType.TAKE_PROFIT) 339 | throw new TestFailureException("Unexpected Order Type "+order.getType()+" != TAKE_PROFIT"); 340 | 341 | System.out.println("TEST - PUT /accounts/{accountID}/orders/{orderSpecifier}/cancel"); 342 | System.out.println("CHECK 200 - The Order was cancelled as specified, expecting cancelled order"); 343 | 344 | ctx.order.cancel(accountId, new OrderSpecifier(orderId)).getOrderCancelTransaction(); 345 | 346 | // 404 - The Order in the Account could not be cancelled 347 | 348 | // put /accounts/{accountID}/orders/{orderSpecifier}/clientExtensions 349 | // ctx.order.setClientExtensions(); 350 | // 200 - The Order's Client Extensions were successfully modified 351 | // 400 - The Order Client Extensions specification was invalid 352 | 353 | System.out.println("TEST GET /accounts/{accountID}/openPositions"); 354 | System.out.println("CHECK 200 - The Account's open Positions are provided, expecting 1 EUR/USD position of 10 units."); 355 | 356 | List positions = ctx.position.listOpen(accountId).getPositions(); 357 | if (positions.size() != 1) 358 | throw new TestFailureException("Position count "+positions.size()+" != 1"); 359 | Position position = positions.get(0); 360 | if (position.getLong().getUnits().doubleValue() != 10) 361 | throw new TestFailureException("Position units "+position.getLong()+" != 10"); 362 | 363 | System.out.println("TEST - PUT /accounts/{accountID}/positions/{instrument}/close"); 364 | System.out.println("CHECK 200 - The Position closeout request has been successfully processed, expecting 1 10 unit position closed."); 365 | 366 | fillTrans = ctx.position.close(new PositionCloseRequest(accountId, tradeableInstrument) 367 | .setLongUnits("ALL") 368 | ).getLongOrderFillTransaction(); 369 | if (fillTrans.getUnits().doubleValue() != -10) 370 | throw new TestFailureException("Position units "+fillTrans.getUnits()+"!= -10"); 371 | 372 | // 400 - The Parameters provided that describe the Position closeout are 373 | // invalid. 374 | 375 | // get /instruments/{instrument}/candles 376 | // ctx.instrument.candles(); 377 | // 200 - Pricing information has been successfully provided. 378 | 379 | System.out.println("TEST - GET /accounts/{accountID}/transactions/sinceid"); 380 | System.out.println("CHECK 200 - The requested time range of Transactions are provided, expecting 16 transactions."); 381 | 382 | List transactions = ctx.transaction.since(accountId, firstTransId).getTransactions(); 383 | System.out.println("Executed a total of "+transactions.size()+" transactions:"); 384 | for (Transaction t : transactions) { 385 | System.out.println(t.getId() + " " + t.getType()); 386 | } 387 | if (transactions.size() != 16) 388 | throw new TestFailureException("Number of transactions "+transactions.size()+" != 16"); 389 | 390 | System.out.println("SUCCESS"); 391 | } 392 | } 393 | --------------------------------------------------------------------------------