diff --git a/build.gradle b/build.gradle index edd2305..3c33742 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation 'commons-cli:commons-cli:1.4' implementation 'joda-time:joda-time:2.9.9' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.5' + implementation 'com.oanda.v20:v20:3.0.25' } repositories { diff --git a/src/main/java/DebugTradingManager.java b/src/main/java/DebugTradingManager.java index 60b0549..e9124f9 100644 --- a/src/main/java/DebugTradingManager.java +++ b/src/main/java/DebugTradingManager.java @@ -1,7 +1,10 @@ +import java.math.BigDecimal; + +import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ats.orders.OrderRequest; +import ats.orders.OrderReply; /** @@ -9,6 +12,19 @@ import ats.orders.OrderRequest; */ public class DebugTradingManager implements TradingManager { static final Logger log = LoggerFactory.getLogger("DebugTradingManager"); + static int orderID = 1; + private EsperProcessor processor; + + + public DebugTradingManager() { + } + + /** + * Set the Esper processor for this trading manager. + */ + public void setProcessor(EsperProcessor processor) { + this.processor = processor; + } /** * Place an order request. diff --git a/src/main/java/EsperProcessor.java b/src/main/java/EsperProcessor.java index 5a2c186..96db03e 100644 --- a/src/main/java/EsperProcessor.java +++ b/src/main/java/EsperProcessor.java @@ -2,18 +2,20 @@ import java.util.Arrays; import java.util.stream.Collectors; import com.espertech.esper.client.Configuration; +import com.espertech.esper.client.EPOnDemandPreparedQueryParameterized; +import com.espertech.esper.client.EPOnDemandQueryResult; import com.espertech.esper.client.EPServiceProvider; import com.espertech.esper.client.EPServiceProviderManager; import com.espertech.esper.client.EPStatement; import com.espertech.esper.client.StatementAwareUpdateListener; import com.espertech.esper.client.UpdateListener; +import com.espertech.esper.client.soda.EPStatementObjectModel; import com.espertech.esper.client.time.CurrentTimeEvent; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ats.orders.MarketOrderRequest; import ats.plugin.OHLCEvent; import ats.plugin.OHLCPlugInViewFactory; @@ -26,6 +28,7 @@ public class EsperProcessor implements TickProcessor { public EsperProcessor(String epl, TradingManager trader) { this.trader = trader; + trader.setProcessor(this); Configuration config = new Configuration(); // disable esper's internal clock. we use tick data for our @@ -196,6 +199,39 @@ public class EsperProcessor implements TickProcessor { return statement; } + /** + * Add a single fire and forget EPL statement to the Esper engine. + */ + public void executeQuery(String query) { + // EPStatement statement = engine.getEPAdministrator().create(query); + // log.debug("Adding query: {}", statement.getText()); + + EPOnDemandQueryResult result = engine.getEPRuntime().executeQuery(query); + log.info(result.toString()); + } + + /** + * Add a single fire and forget EPL statement to the Esper engine. + */ + public void executeQuery(EPStatementObjectModel query) { + // EPStatement statement = engine.getEPAdministrator().create(query); + // log.debug("Adding query: {}", statement.getText()); + + EPOnDemandQueryResult result = engine.getEPRuntime().executeQuery(query); + log.info(result.toString()); + } + + /** + * Add a single fire and forget EPL statement to the Esper engine. + */ + public void executeQuery(EPOnDemandPreparedQueryParameterized query) { + // EPStatement statement = engine.getEPAdministrator().create(query); + // log.debug("Adding query: {}", statement.getText()); + + EPOnDemandQueryResult result = engine.getEPRuntime().executeQuery(query); + log.info(result.toString()); + } + /** * Send a single TickEvent to Esper. */ diff --git a/src/main/java/OANDATradingManager.java b/src/main/java/OANDATradingManager.java index a1f318a..53d325c 100644 --- a/src/main/java/OANDATradingManager.java +++ b/src/main/java/OANDATradingManager.java @@ -1,16 +1,28 @@ -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; +import java.math.BigDecimal; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.oanda.v20.Context; +import com.oanda.v20.ExecuteException; +import com.oanda.v20.RequestException; +import com.oanda.v20.account.AccountID; +import com.oanda.v20.order.MarketOrderRequest; +import com.oanda.v20.order.Order; +import com.oanda.v20.order.OrderAdapter; +import com.oanda.v20.order.OrderCreateRequest; +import com.oanda.v20.order.OrderCreateResponse; +import com.oanda.v20.transaction.OrderCancelReason; +import com.oanda.v20.transaction.OrderCancelTransaction; +import com.oanda.v20.transaction.OrderFillTransaction; +import com.oanda.v20.transaction.Transaction; +import com.oanda.v20.transaction.TransactionAdapter; + +import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ats.orders.OrderRequest; +import ats.orders.OrderReply; + /** * OANDATradingManager manages orders via the OANDA API. @@ -18,6 +30,7 @@ import ats.orders.OrderRequest; public class OANDATradingManager implements TradingManager { static final Logger log = LoggerFactory.getLogger("OANDATradingManager"); private Config config; + private EsperProcessor processor; /** @@ -27,73 +40,82 @@ public class OANDATradingManager implements TradingManager { public OANDATradingManager(Config config) { this.config = config; } - + /** - * Place an order request. + * Set the Esper processor for this trading manager. */ - @Override - public void placeOrder(OrderRequest order) { - log.info("Placing order: {}", order); + public void setProcessor(EsperProcessor processor) { + this.processor = processor; + } + /** + * Place an order request to open a new position. + */ + @Override + public OrderReply openPosition(String instrument, BigDecimal requestUnits) { try { - String orderJSON = order.toJSON(); - byte[] postData = orderJSON.getBytes(StandardCharsets.UTF_8); - int postDataLength = postData.length; + MarketOrderRequest orderRequest = new MarketOrderRequest(); + orderRequest.setInstrument(instrument); + orderRequest.setUnits(requestUnits); - URL url = new URL(orderURL()); + OrderCreateRequest createRequest = new OrderCreateRequest(new AccountID(config.accountID())); + createRequest.setOrder(orderRequest); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - conn.setDoOutput(true); - conn.setInstanceFollowRedirects(false); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type", "application/json"); - conn.setRequestProperty("charset", "utf-8"); - conn.setRequestProperty("Content-Length", Integer.toString(postDataLength)); - conn.setRequestProperty("Authorization", "Bearer " + config.accessToken()); - conn.setUseCaches(false); + OrderCreateResponse response = getContext().order.create(createRequest); - try (DataOutputStream dos = new DataOutputStream(conn.getOutputStream())) { - dos.write(postData); - dos.flush(); - dos.close(); + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .registerTypeAdapter(Order.class, new OrderAdapter()) + .registerTypeAdapter(Transaction.class, new TransactionAdapter()) + .create(); + + // log.info(gson.toJson(response)); + + // Transaction create = response.getOrderCreateTransaction(); + // log.info(create.toString()); + + OrderFillTransaction fill = response.getOrderFillTransaction(); + // log.info(fill.toString()); + + if (fill == null) { + OrderCancelTransaction cancel = response.getOrderCancelTransaction(); + OrderCancelReason reason = cancel.getReason(); + log.warn("Open position order cancelled. Reason: " + reason.toString()); + log.info(cancel.toString()); + return null; } - int responseCode = conn.getResponseCode(); + String orderID = fill.getOrderID().toString(); + DateTime time = DateTime.parse(fill.getTime().toString()); + BigDecimal price = fill.getTradeOpened().getPrice().bigDecimalValue(); + BigDecimal actualUnits = fill.getTradeOpened().getUnits().bigDecimalValue(); + OrderReply orderReply = new OrderReply(orderID, time, instrument, price, actualUnits); - log.debug("Sending request to " + url); - log.debug("Params: " + new String(postData)); - log.debug("Response code: " + responseCode); + // log.info(response.toString()); - // read response - InputStream is; - if (responseCode < 400) { - log.debug("Reading input stream"); - is = conn.getInputStream(); - } else { - log.debug("Reading error stream"); - is = conn.getErrorStream(); - } - BufferedReader in = new BufferedReader(new InputStreamReader(is)); - String inputLine; - StringBuffer response = new StringBuffer(); - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); - } - in.close(); + processor.executeQuery(orderReply.toEPL()); - log.info("Response: " + response); - log.info("Finished placing order."); - } catch (IOException e) { - log.warn("Error sending order", e); + return orderReply; + } catch (RequestException | ExecuteException e) { + log.warn("Error opening position", e); + return null; } } /** - * Return the OANDA API endpoint for placing orders. + * Place an order request to close an existing position. */ - private String orderURL() { + @Override + public void closePosition(String orderID) { + throw new UnsupportedOperationException(); + } + + /** + * Return the OANDA context. + */ + private Context getContext() { String type = config.isLiveAccount() ? "fxlive" : "fxpractice"; - return String.format("https://api-%s.oanda.com/v3/accounts/%s/orders", - type, config.accountID()); + String url = String.format("https://api-%s.oanda.com/", type); + return new Context(url, config.accessToken()); } } diff --git a/src/main/java/TradingManager.java b/src/main/java/TradingManager.java index bd891e2..68850bf 100644 --- a/src/main/java/TradingManager.java +++ b/src/main/java/TradingManager.java @@ -1,4 +1,6 @@ -import ats.orders.OrderRequest; +import java.math.BigDecimal; + +import ats.orders.OrderReply; /** * TradingManager describes the interface with a trading system. @@ -6,8 +8,23 @@ import ats.orders.OrderRequest; interface TradingManager { /** - * Place an order request. + * Set the Esper processor for this trading manager. */ - public void placeOrder(OrderRequest order); + public void setProcessor(EsperProcessor processor); + /** + * Place an order request to open a new position. + */ + public OrderReply openPosition(String instrument, BigDecimal units); + + /** + * Place an order request to close an existing position. + */ + public void closePosition(String orderID); + + /** + * Place an order request. Lower level than openPosition() and + * closePosition(). + */ + // public void placeOrder(OrderRequest order); } diff --git a/src/main/java/ats/orders/ClientExtensions.java b/src/main/java/ats/orders/ClientExtensions.java deleted file mode 100644 index a3d4232..0000000 --- a/src/main/java/ats/orders/ClientExtensions.java +++ /dev/null @@ -1,26 +0,0 @@ -package ats.orders; - -/** - * A ClientExtensions object allows a client to attach a clientID, tag - * and comment to Orders and Trades in their Account. Do not set, - * modify, or delete this field if your account is associated with - * MT4. - * - * @see OANDA API docs - */ -public class ClientExtensions { - /** - * The Client ID of the Order/Trade - */ - public String id; - - /** - * A tag associated with the Order/Trade - */ - public String tag; - - /** - * A comment associated with the Order/Trade - */ - public String comment; -} diff --git a/src/main/java/ats/orders/LimitOrderRequest.java b/src/main/java/ats/orders/LimitOrderRequest.java deleted file mode 100644 index 4812ce8..0000000 --- a/src/main/java/ats/orders/LimitOrderRequest.java +++ /dev/null @@ -1,248 +0,0 @@ -package ats.orders; - -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; - -/** - * Create a new limit order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class LimitOrderRequest extends OrderRequest { - - /** - * Instrument to open the order on. Example: "EUR_USD" - */ - public String instrument; - - /** - * The quantity requested to be filled by the Order. A - * posititive number of units results in a long Order, and a - * negative number of units results in a short Order. - */ - public int units; - - /** - * The price threshold specified for the Limit Order. The Limit - * Order will only be filled by a market price that is equal to or - * better than this price. - */ - public String price; - - /** - * The time-in-force requested for the Order. - */ - public TimeInForce timeInForce; - - /** - * The date/time when the Limit Order will be cancelled if its - * timeInForce is “GTD”. - */ - public DateTime gtdTime; - - /** - * Specification of how Positions in the Account are modified when - * the Order is filled. - */ - public OrderPositionFill positionFill; - - /** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This - * allows Orders to be triggered based on the bid, ask, mid, - * default (ask for buy, bid for sell) or inverse (ask for sell, - * bid for buy) price depending on the desired behaviour. Orders - * are always filled using their default price component. This - * feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see - * it reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s - * trigger condition is set to the default value when indicating - * the distance from an Order’s trigger price, and will always - * provide the default trigger condition when creating or - * modifying an Order. A special restriction applies when creating - * a guaranteed Stop Loss Order. In this case the TriggerCondition - * value must either be “DEFAULT”, or the “natural” trigger side - * “DEFAULT” results in. So for a String top Loss Order for a long - * trade valid values are “DEFAULT” and “BID”, and for short - * trades “DEFAULT” and “ASK” are valid. - */ - public OrderTriggerCondition triggerCondition; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - /** - * TakeProfitDetails specifies the details of a Take Profit Order - * to be created on behalf of a client. This may happen when an - * Order is filled that opens a Trade requiring a Take Profit, or - * when a Trade’s dependent Take Profit Order is modified directly - * through the Trade. - */ - public TakeProfitDetails takeProfitOnFill; - - /** - * StopLossDetails specifies the details of a Stop Loss Order to - * be created on behalf of a client. This may happen when an Order - * is filled that opens a Trade requiring a Stop Loss, or when a - * Trade’s dependent Stop Loss Order is modified directly through - * the Trade. - */ - public StopLossDetails stopLossOnFill; - - /** - * TrailingStopLossDetails specifies the details of a Trailing - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a - * Trailing Stop Loss, or when a Trade’s dependent Trailing Stop - * Loss Order is modified directly through the Trade. - */ - public TrailingStopLossDetails trailingStopLossOnFill; - - /** - * Client Extensions to add to the Trade created when the Order is - * filled (if such a Trade is created). Do not set, modify, or - * delete tradeClientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions tradeClientExtensions; - - - - /** - * Create a new limit order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the - * Order. A posititive number of units results in a long Order, - * and a negative number of units results in a short Order. - * - * @param price The price threshold specified for the Limit - * Order. The Limit Order will only be filled by a market price - * that is equal to or better than this price. - */ - public LimitOrderRequest(String instrument, int units, String price) - { - this(instrument, units, price, null, null, null, - null, null, null, null, null, null); - } - - /** - * Create a new limit order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the - * Order. A posititive number of units results in a long Order, - * and a negative number of units results in a short Order. - * - * @param price The price threshold specified for the Limit - * Order. The Limit Order will only be filled by a market price - * that is equal to or better than this price. - * - * @param timeInForce The time-in-force requested for the Limit - * Order. The default is TimeInForce.GTC. - * - * @param gtdTime The date when the Limit Order will be cancelled - * on if timeInForce is GTD. - * - * @param positionFill Specification of how Positions in the Account - * are modified when the Order is filled. The default is - * OrderPositionFill.DEFAULT. - * - * @param triggerCondition Specification of which price component - * should be used when determining if an Order should be triggered - * and filled. This allows Orders to be triggered based on the - * bid, ask, mid, default (ask for buy, bid for sell) or inverse - * (ask for sell, bid for buy) price depending on the desired - * behaviour. Orders are always filled using their default price - * component. This feature is only provided through the REST - * API. Clients who choose to specify a non-default trigger - * condition will not see it reflected in any of OANDA’s - * proprietary or partner trading platforms, their transaction - * history or their account statements. OANDA platforms always - * assume that an Order’s trigger condition is set to the default - * value when indicating the distance from an Order’s trigger - * price, and will always provide the default trigger condition - * when creating or modifying an Order. A special restriction - * applies when creating a guaranteed Stop Loss Order. In this - * case the TriggerCondition value must either be “DEFAULT”, or - * the “natural” trigger side “DEFAULT” results in. So for a Stop - * Loss Order for a long trade valid values are “DEFAULT” and - * “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * The default is OrderTriggerCondition.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - * - * @param takeProfitOnFill TakeProfitDetails specifies the details of - * a Take Profit Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Take - * Profit, or when a Trade’s dependent Take Profit Order is modified - * directly through the Trade. - * - * @param stopLossOnFill StopLossDetails specifies the details of a - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Stop - * Loss, or when a Trade’s dependent Stop Loss Order is modified - * directly through the Trade. - * - * @param trailingStopLossOnFill TrailingStopLossDetails specifies the - * details of a Trailing Stop Loss Order to be created on behalf of a - * client. This may happen when an Order is filled that opens a Trade - * requiring a Trailing Stop Loss, or when a Trade’s dependent - * Trailing Stop Loss Order is modified directly through the Trade. - * - * @param tradeClientExtensions Client Extensions to add to the Trade - * created when the Order is filled (if such a Trade is created). Do - * not set, modify, or delete tradeClientExtensions if your account is - * associated with MT4. - */ - public LimitOrderRequest(String instrument, - int units, - String price, - TimeInForce timeInForce, - DateTime gtdTime, - OrderPositionFill positionFill, - OrderTriggerCondition triggerCondition, - ClientExtensions clientExtensions, - TakeProfitDetails takeProfitOnFill, - StopLossDetails stopLossOnFill, - TrailingStopLossDetails trailingStopLossOnFill, - ClientExtensions tradeClientExtensions) - { - super(OrderType.LIMIT); - - this.instrument = instrument; - this.units = units; - this.price = price; - this.timeInForce = timeInForce; - this.gtdTime = gtdTime; - this.positionFill = positionFill; - this.triggerCondition = triggerCondition; - this.clientExtensions = clientExtensions; - this.takeProfitOnFill = takeProfitOnFill; - this.stopLossOnFill = stopLossOnFill; - this.trailingStopLossOnFill = trailingStopLossOnFill; - this.tradeClientExtensions = tradeClientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.GTC; - - if (this.positionFill == null) - this.positionFill = OrderPositionFill.DEFAULT; - - if (this.triggerCondition == null) - this.triggerCondition = OrderTriggerCondition.DEFAULT; - } -} diff --git a/src/main/java/ats/orders/MarketIfTouchedOrderRequest.java b/src/main/java/ats/orders/MarketIfTouchedOrderRequest.java deleted file mode 100644 index 9d1f020..0000000 --- a/src/main/java/ats/orders/MarketIfTouchedOrderRequest.java +++ /dev/null @@ -1,272 +0,0 @@ -package ats.orders; - -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; - -/** - * Create a new market-if-touched order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class MarketIfTouchedOrderRequest extends OrderRequest { - - /** - * Instrument to open the order on. Example: "EUR_USD" - */ - public String instrument; - - /** - * The quantity requested to be filled by the order. A posititive - * number of units results in a long Order, and a negative number - * of units results in a short Order. - */ - public int units; - - /** - * The price threshold specified for the MarketIfTouched - * Order. The MarketIfTouched Order will only be filled by a - * market price that crosses this price from the direction of the - * market price at the time when the Order was created (the - * initialMarketPrice). Depending on the value of the Order’s - * price and initialMarketPrice, the MarketIfTouchedOrder will - * behave like a Limit or a Stop Order. - */ - public String price; - - /** - * The worst market price that may be used to fill this - * MarketIfTouched Order. - */ - public String priceBound; - - /** - * The time-in-force requested for the order. The default is - * TimeInForce.GTC. - */ - public TimeInForce timeInForce; - - /** - * The date/time when the order will be cancelled if its - * timeInForce is “GTD”. - */ - public DateTime gtdTime; - - /** - * Specification of how Positions in the Account are modified when - * the Order is filled. - */ - public OrderPositionFill positionFill; - - /** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This - * allows Orders to be triggered based on the bid, ask, mid, - * default (ask for buy, bid for sell) or inverse (ask for sell, - * bid for buy) price depending on the desired behaviour. Orders - * are always filled using their default price component. This - * feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see - * it reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s - * trigger condition is set to the default value when indicating - * the distance from an Order’s trigger price, and will always - * provide the default trigger condition when creating or - * modifying an Order. A special restriction applies when creating - * a guaranteed Stop Loss Order. In this case the TriggerCondition - * value must either be “DEFAULT”, or the “natural” trigger side - * “DEFAULT” results in. So for a String top Loss Order for a long - * trade valid values are “DEFAULT” and “BID”, and for short - * trades “DEFAULT” and “ASK” are valid. - */ - public OrderTriggerCondition triggerCondition; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - /** - * TakeProfitDetails specifies the details of a Take Profit Order - * to be created on behalf of a client. This may happen when an - * Order is filled that opens a Trade requiring a Take Profit, or - * when a Trade’s dependent Take Profit Order is modified directly - * through the Trade. - */ - public TakeProfitDetails takeProfitOnFill; - - /** - * StopLossDetails specifies the details of a Stop Loss Order to - * be created on behalf of a client. This may happen when an Order - * is filled that opens a Trade requiring a Stop Loss, or when a - * Trade’s dependent Stop Loss Order is modified directly through - * the Trade. - */ - public StopLossDetails stopLossOnFill; - - /** - * TrailingStopLossDetails specifies the details of a Trailing - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a - * Trailing Stop Loss, or when a Trade’s dependent Trailing Stop - * Loss Order is modified directly through the Trade. - */ - public TrailingStopLossDetails trailingStopLossOnFill; - - /** - * Client Extensions to add to the Trade created when the Order is - * filled (if such a Trade is created). Do not set, modify, or - * delete tradeClientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions tradeClientExtensions; - - - - /** - * Create a new stop order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the - * Order. A posititive number of units results in a long Order, - * and a negative number of units results in a short Order. - * - * @param price The price threshold specified for the - * MarketIfTouched Order. The MarketIfTouched Order will only be - * filled by a market price that crosses this price from the - * direction of the market price at the time when the Order was - * created (the initialMarketPrice). Depending on the value of the - * Order’s price and initialMarketPrice, the MarketIfTouchedOrder - * will behave like a Limit or a Stop Order. - */ - public MarketIfTouchedOrderRequest(String instrument, int units, String price) - { - this(instrument, units, price, null, null, null, - null, null, null, null, null, null, null); - } - - /** - * Create a new stop order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the - * Order. A posititive number of units results in a long Order, - * and a negative number of units results in a short Order. - * - * @param price The price threshold specified for the - * MarketIfTouched Order. The MarketIfTouched Order will only be - * filled by a market price that crosses this price from the - * direction of the market price at the time when the Order was - * created (the initialMarketPrice). Depending on the value of the - * Order’s price and initialMarketPrice, the MarketIfTouchedOrder - * will behave like a Limit or a Stop Order. - * - * @param priceBound The worst market price that may be used to - * fill this MarketIfTouched Order. - * - * @param timeInForce The time-in-force requested for the Order. - * The default is TimeInForce.GTC. - * - * @param gtdTime The date when the Order will be cancelled on if - * timeInForce is GTD. - * - * @param positionFill Specification of how Positions in the Account - * are modified when the Order is filled. The default is - * OrderPositionFill.DEFAULT. - * - * @param triggerCondition Specification of which price component - * should be used when determining if an Order should be triggered - * and filled. This allows Orders to be triggered based on the - * bid, ask, mid, default (ask for buy, bid for sell) or inverse - * (ask for sell, bid for buy) price depending on the desired - * behaviour. Orders are always filled using their default price - * component. This feature is only provided through the REST - * API. Clients who choose to specify a non-default trigger - * condition will not see it reflected in any of OANDA’s - * proprietary or partner trading platforms, their transaction - * history or their account statements. OANDA platforms always - * assume that an Order’s trigger condition is set to the default - * value when indicating the distance from an Order’s trigger - * price, and will always provide the default trigger condition - * when creating or modifying an Order. A special restriction - * applies when creating a guaranteed Stop Loss Order. In this - * case the TriggerCondition value must either be “DEFAULT”, or - * the “natural” trigger side “DEFAULT” results in. So for a Stop - * Loss Order for a long trade valid values are “DEFAULT” and - * “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * The default is OrderTriggerCondition.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - * - * @param takeProfitOnFill TakeProfitDetails specifies the details of - * a Take Profit Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Take - * Profit, or when a Trade’s dependent Take Profit Order is modified - * directly through the Trade. - * - * @param stopLossOnFill StopLossDetails specifies the details of a - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Stop - * Loss, or when a Trade’s dependent Stop Loss Order is modified - * directly through the Trade. - * - * @param trailingStopLossOnFill TrailingStopLossDetails specifies the - * details of a Trailing Stop Loss Order to be created on behalf of a - * client. This may happen when an Order is filled that opens a Trade - * requiring a Trailing Stop Loss, or when a Trade’s dependent - * Trailing Stop Loss Order is modified directly through the Trade. - * - * @param tradeClientExtensions Client Extensions to add to the Trade - * created when the Order is filled (if such a Trade is created). Do - * not set, modify, or delete tradeClientExtensions if your account is - * associated with MT4. - */ - public MarketIfTouchedOrderRequest(String instrument, - int units, - String price, - String priceBound, - TimeInForce timeInForce, - DateTime gtdTime, - OrderPositionFill positionFill, - OrderTriggerCondition triggerCondition, - ClientExtensions clientExtensions, - TakeProfitDetails takeProfitOnFill, - StopLossDetails stopLossOnFill, - TrailingStopLossDetails trailingStopLossOnFill, - ClientExtensions tradeClientExtensions) - { - super(OrderType.MARKET_IF_TOUCHED); - - this.instrument = instrument; - this.units = units; - this.price = price; - this.priceBound = priceBound; - this.timeInForce = timeInForce; - this.gtdTime = gtdTime; - this.positionFill = positionFill; - this.triggerCondition = triggerCondition; - this.clientExtensions = clientExtensions; - this.takeProfitOnFill = takeProfitOnFill; - this.stopLossOnFill = stopLossOnFill; - this.trailingStopLossOnFill = trailingStopLossOnFill; - this.tradeClientExtensions = tradeClientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.GTC; - - if (this.positionFill == null) - this.positionFill = OrderPositionFill.DEFAULT; - - if (this.triggerCondition == null) - this.triggerCondition = OrderTriggerCondition.DEFAULT; - } -} diff --git a/src/main/java/ats/orders/MarketOrderRequest.java b/src/main/java/ats/orders/MarketOrderRequest.java deleted file mode 100644 index daff38a..0000000 --- a/src/main/java/ats/orders/MarketOrderRequest.java +++ /dev/null @@ -1,177 +0,0 @@ -package ats.orders; - -/** - * Create a new market order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class MarketOrderRequest extends OrderRequest { - - /** - * Instrument to open the order on. Example: "EUR_USD" - */ - public String instrument; - - /** - * The quantity requested to be filled by the Market Order. A - * posititive number of units results in a long Order, and a - * negative number of units results in a short Order. - */ - public int units; - - /** - * The time-in-force requested for the Market Order. Restricted to - * FOK or IOC for a MarketOrder. - */ - public TimeInForce timeInForce; - - /** - * The worst price that the client is willing to have the Market - * Order filled at. - */ - public String priceBound; - - /** - * Specification of how Positions in the Account are modified when - * the Order is filled. - */ - public OrderPositionFill positionFill; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - /** - * TakeProfitDetails specifies the details of a Take Profit Order - * to be created on behalf of a client. This may happen when an - * Order is filled that opens a Trade requiring a Take Profit, or - * when a Trade’s dependent Take Profit Order is modified directly - * through the Trade. - */ - public TakeProfitDetails takeProfitOnFill; - - /** - * StopLossDetails specifies the details of a Stop Loss Order to - * be created on behalf of a client. This may happen when an Order - * is filled that opens a Trade requiring a Stop Loss, or when a - * Trade’s dependent Stop Loss Order is modified directly through - * the Trade. - */ - public StopLossDetails stopLossOnFill; - - /** - * TrailingStopLossDetails specifies the details of a Trailing - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a - * Trailing Stop Loss, or when a Trade’s dependent Trailing Stop - * Loss Order is modified directly through the Trade. - */ - public TrailingStopLossDetails trailingStopLossOnFill; - - /** - * Client Extensions to add to the Trade created when the Order is - * filled (if such a Trade is created). Do not set, modify, or - * delete tradeClientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions tradeClientExtensions; - - - /** - * Create a new market order request to send to the OANDA API. - * Use empty or default values for any unspecified properties. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the Market - * Order. A posititive number of units results in a long Order, and a - * negative number of units results in a short Order. - */ - public MarketOrderRequest(String instrument, int units) - { - this(instrument, units, null, null, null, null, null, null, null, null); - } - - /** - * Create a new market order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the Market - * Order. A posititive number of units results in a long Order, and a - * negative number of units results in a short Order. - * - * @param timeInForce The time-in-force requested for the Market - * Order. Restricted to FOK or IOC for a MarketOrder. The default is - * TimeInForce.FOK. - * - * @param priceBound The worst price that the client is willing to - * have the Market Order filled at. - * - * @param positionFill Specification of how Positions in the Account - * are modified when the Order is filled. The default is - * OrderPositionFill.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - * - * @param takeProfitOnFill TakeProfitDetails specifies the details of - * a Take Profit Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Take - * Profit, or when a Trade’s dependent Take Profit Order is modified - * directly through the Trade. - * - * @param stopLossOnFill StopLossDetails specifies the details of a - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Stop - * Loss, or when a Trade’s dependent Stop Loss Order is modified - * directly through the Trade. - * - * @param trailingStopLossOnFill TrailingStopLossDetails specifies the - * details of a Trailing Stop Loss Order to be created on behalf of a - * client. This may happen when an Order is filled that opens a Trade - * requiring a Trailing Stop Loss, or when a Trade’s dependent - * Trailing Stop Loss Order is modified directly through the Trade. - * - * @param tradeClientExtensions Client Extensions to add to the Trade - * created when the Order is filled (if such a Trade is created). Do - * not set, modify, or delete tradeClientExtensions if your account is - * associated with MT4. - */ - public MarketOrderRequest(String instrument, - int units, - TimeInForce timeInForce, - String priceBound, - OrderPositionFill positionFill, - ClientExtensions clientExtensions, - TakeProfitDetails takeProfitOnFill, - StopLossDetails stopLossOnFill, - TrailingStopLossDetails trailingStopLossOnFill, - ClientExtensions tradeClientExtensions) - { - super(OrderType.MARKET); - - this.instrument = instrument; - this.units = units; - this.timeInForce = timeInForce; - this.priceBound = priceBound; - this.positionFill = positionFill; - this.clientExtensions = clientExtensions; - this.takeProfitOnFill = takeProfitOnFill; - this.stopLossOnFill = stopLossOnFill; - this.trailingStopLossOnFill = trailingStopLossOnFill; - this.tradeClientExtensions = tradeClientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.FOK; - - if (this.positionFill == null) - this.positionFill = OrderPositionFill.DEFAULT; - } -} diff --git a/src/main/java/ats/orders/OrderPositionFill.java b/src/main/java/ats/orders/OrderPositionFill.java deleted file mode 100644 index b2b64bd..0000000 --- a/src/main/java/ats/orders/OrderPositionFill.java +++ /dev/null @@ -1,33 +0,0 @@ -package ats.orders; - -/** - * Specification of how Positions in the Account are modified when the - * Order is filled. - * - * @see OANDA API docs - */ -public enum OrderPositionFill { - /** - * When the Order is filled, only allow Positions to be opened - * or extended. - */ - OPEN_ONLY, - - /** - * When the Order is filled, always fully reduce an existing - * Position before opening a new Position. - */ - REDUCE_FIRST, - - /** - * When the Order is filled, only reduce an existing Position. - */ - REDUCE_ONLY, - - /** - * When the Order is filled, use REDUCE_FIRST behaviour for - * non-client hedging Accounts, and OPEN_ONLY behaviour for - * client hedging Accounts. - */ - DEFAULT -}; diff --git a/src/main/java/ats/orders/OrderReply.java b/src/main/java/ats/orders/OrderReply.java new file mode 100644 index 0000000..8b48fd4 --- /dev/null +++ b/src/main/java/ats/orders/OrderReply.java @@ -0,0 +1,66 @@ +package ats.orders; + +import java.math.BigDecimal; + +import com.espertech.esper.client.EPOnDemandPreparedQueryParameterized; +import com.espertech.esper.client.soda.ConstantExpression; +import com.espertech.esper.client.soda.EPStatementObjectModel; +import com.espertech.esper.client.soda.FireAndForgetInsert; +import com.espertech.esper.client.soda.FromClause; +import com.espertech.esper.client.soda.InsertIntoClause; +import com.espertech.esper.client.soda.SelectClause; +import com.espertech.esper.core.service.EPPreparedStatementImpl; + +import org.joda.time.DateTime; + +/** + * TODO + */ +public class OrderReply { + private String orderID; + private DateTime time; + private String instrument; + private BigDecimal price; + private BigDecimal units; + + + public OrderReply(String orderID, DateTime time, String instrument, + BigDecimal price, BigDecimal actualUnits) + { + this.orderID = orderID; + this.time = time; + this.instrument = instrument; + this.price = price; + this.units = actualUnits; + } + + /** + * Return an epl insert statement to add this to the Esper order + * table. + */ + public EPOnDemandPreparedQueryParameterized toEPL() { + EPStatementObjectModel model = new EPStatementObjectModel(); + model.setFireAndForgetClause(new FireAndForgetInsert()); + model.insertInto(InsertIntoClause.create("OrderTable", "id", "time", "instrument", "price", "units", "open", "stopBarCount")); + + SelectClause select = SelectClause.create(); + select.add(new ConstantExpression(orderID)); + select.add(new ConstantExpression(time)); + select.add(new ConstantExpression(instrument)); + select.add(new ConstantExpression(price)); + select.add(new ConstantExpression(units)); + select.add(new ConstantExpression(true)); // open + select.add(new ConstantExpression(0)); // stopBarCount + model.setSelectClause(select); + + model.setFromClause(FromClause.create()); + + return new EPPreparedStatementImpl(model, null, null); + } + + @Override + public String toString() { + return String.format("OrderReply[id=%s, time=%s, instr=%s, units=%d, price=%s]", + orderID, time, instrument, units, price); + } +} diff --git a/src/main/java/ats/orders/OrderRequest.java b/src/main/java/ats/orders/OrderRequest.java deleted file mode 100644 index 3bb4943..0000000 --- a/src/main/java/ats/orders/OrderRequest.java +++ /dev/null @@ -1,72 +0,0 @@ -package ats.orders; - -import java.util.HashMap; -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.joda.JodaModule; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Base class for order requests to send to the OANDA API. - */ -public class OrderRequest { - final Logger log = LoggerFactory.getLogger(OrderRequest.class); - - /** - * The type of the Order to Create. - */ - public OrderType type; - - - /** - * Create an order. Subclasses only will call this. Not for user - * code. - */ - public OrderRequest(OrderType orderType) - { - this.type = orderType; - } - - /** - * Create a JSON representation of the order suitable for sending - * to the OANDA API. - * - * @see OANDA API docs - */ - public String toJSON() throws JsonProcessingException { - Map order = new HashMap<>(); - order.put("order", this); - return getJSONMapper().writeValueAsString(order); - } - - /** - * Return a new JSON object mapper suitable for serializing orders - * for the OANDA api. - */ - public static ObjectMapper getJSONMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new JodaModule()); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.setSerializationInclusion(Include.NON_NULL); - return mapper; - } - - /** - * Return a better description of the order. - */ - @Override - public String toString() { - try { - return toJSON(); - } catch (JsonProcessingException e) { - log.warn("Error converting to JSON", e); - return super.toString(); - } - } -} diff --git a/src/main/java/ats/orders/OrderTriggerCondition.java b/src/main/java/ats/orders/OrderTriggerCondition.java deleted file mode 100644 index 7d5f2f7..0000000 --- a/src/main/java/ats/orders/OrderTriggerCondition.java +++ /dev/null @@ -1,59 +0,0 @@ -package ats.orders; - -/** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This allows - * Orders to be triggered based on the bid, ask, mid, default (ask for - * buy, bid for sell) or inverse (ask for sell, bid for buy) price - * depending on the desired behaviour. Orders are always filled using - * their default price component. - * - * This feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see it - * reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s trigger - * condition is set to the default value when indicating the distance - * from an Order’s trigger price, and will always provide the default - * trigger condition when creating or modifying an Order. - * - * A special restriction applies when creating a guaranteed Stop Loss - * Order. In this case the TriggerCondition value must either be - * “DEFAULT”, or the “natural” trigger side “DEFAULT” results in. So - * for a Stop Loss Order for a long trade valid values are “DEFAULT” - * and “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * - * @see OANDA API docs - */ -public enum OrderTriggerCondition { - - /** - * Trigger an Order the “natural” way: compare its price to the - * ask for long Orders and bid for short Orders. - */ - DEFAULT, - - /** - * Trigger an Order the opposite of the “natural” way: compare its - * price the bid for long Orders and ask for short Orders. - */ - INVERSE, - - /** - * Trigger an Order by comparing its price to the bid regardless - * of whether it is long or short. - */ - BID, - - /** - * Trigger an Order by comparing its price to the ask regardless - * of whether it is long or short. - */ - ASK, - - /** - * Trigger an Order by comparing its price to the midpoint - * regardless of whether it is long or short. - */ - MID -} diff --git a/src/main/java/ats/orders/OrderType.java b/src/main/java/ats/orders/OrderType.java deleted file mode 100644 index 00cf278..0000000 --- a/src/main/java/ats/orders/OrderType.java +++ /dev/null @@ -1,17 +0,0 @@ -package ats.orders; - -/** - * Order type. - * - * @see OANDA API docs - */ -public enum OrderType { - MARKET, - LIMIT, - STOP, - MARKET_IF_TOUCHED, - TAKE_PROFIT, - STOP_LOSS, - TRAILING_STOP_LOSS, - FIXED_PRICE -}; diff --git a/src/main/java/ats/orders/StopLossDetails.java b/src/main/java/ats/orders/StopLossDetails.java deleted file mode 100644 index 1ef57d2..0000000 --- a/src/main/java/ats/orders/StopLossDetails.java +++ /dev/null @@ -1,57 +0,0 @@ -package ats.orders; - -import java.math.BigDecimal; - -import org.joda.time.DateTime; - -/** - * StopLossDetails specifies the details of a Stop Loss Order to be - * created on behalf of a client. This may happen when an Order is - * filled that opens a Trade requiring a Stop Loss, or when a Trade’s - * dependent Stop Loss Order is modified directly through the Trade. - * - * @see OANDA API docs - */ -public class StopLossDetails { - - /** - * The price that the Stop Loss Order will be triggered - * at. Only one of the price and distance fields may be - * specified. - */ - public String price; - - /** - * Specifies the distance (in price units) from the Trade’s - * open price to use as the Stop Loss Order price. Only one of - * the distance and price fields may be specified. - */ - public BigDecimal distance; - - /** - * The time in force for the created Stop Loss Order. This may - * only be GTC, GTD or GFD. The default is GTC. - */ - public TimeInForce timeInForce = TimeInForce.GTC; - - /** - * The date when the Stop Loss Order will be cancelled on if - * timeInForce is GTD. - */ - public DateTime gtdTime; - - /** - * The Client Extensions to add to the Stop Loss Order when - * created. - */ - public ClientExtensions clientExtensions; - - /** - * Flag indicating that the price for the Stop Loss Order is - * guaranteed. The default value depends on the - * GuaranteedStopLossOrderMode of the account, if it is - * REQUIRED, the default will be true, for DISABLED or ENABLED - * the default is false. - */ - public boolean guaranteed; -} diff --git a/src/main/java/ats/orders/StopLossOrderRequest.java b/src/main/java/ats/orders/StopLossOrderRequest.java deleted file mode 100644 index c95253f..0000000 --- a/src/main/java/ats/orders/StopLossOrderRequest.java +++ /dev/null @@ -1,185 +0,0 @@ -package ats.orders; - -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; - -/** - * Create a new stop loss order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class StopLossOrderRequest extends OrderRequest { - - /** - * The ID of the Trade to close when the price threshold is - * breached. - */ - public String tradeID; - - /** - * The client ID of the Trade to be closed when the price - * threshold is breached. - */ - public String clientTradeID; - - /** - * The price threshold specified for the Stop Loss Order. If the - * guaranteed flag is false, the associated Trade will be closed - * by a market price that is equal to or worse than this - * threshold. If the flag is true the associated Trade will be - * closed at this price. - */ - public String price; - - /** - * Specifies the distance (in price units) from the Account’s - * current price to use as the StopLoss Order price. If the Trade - * is short the Instrument’s bid price is used, and for long - * Trades the ask is used. - */ - public String distance; - - /** - * The time-in-force requested for the StopLoss Order. Restricted - * to “GTC”, “GFD” and “GTD” for StopLoss Orders. The default - * is TimeInForce.GTC. - */ - public TimeInForce timeInForce; - - /** - * The date/time when the order will be cancelled if its - * timeInForce is “GTD”. - */ - public DateTime gtdTime; - - /** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This - * allows Orders to be triggered based on the bid, ask, mid, - * default (ask for buy, bid for sell) or inverse (ask for sell, - * bid for buy) price depending on the desired behaviour. Orders - * are always filled using their default price component. This - * feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see - * it reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s - * trigger condition is set to the default value when indicating - * the distance from an Order’s trigger price, and will always - * provide the default trigger condition when creating or - * modifying an Order. A special restriction applies when creating - * a guaranteed Stop Loss Order. In this case the TriggerCondition - * value must either be “DEFAULT”, or the “natural” trigger side - * “DEFAULT” results in. So for a Stop Loss Order for a long trade - * valid values are “DEFAULT” and “BID”, and for short trades - * “DEFAULT” and “ASK” are valid. The default is - * OrderTriggerCondition.DEFAULT. - */ - public OrderTriggerCondition triggerCondition; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - - - /** - * Create a new stop loss order request to send to the OANDA API. - * - * @param tradeID The ID of the Trade to close when the price - * threshold is breached. - * - * @param clientTradeID The client ID of the Trade to be closed - * when the price threshold is breached. - * - * @param price The price threshold specified for the TakeProfit - * Order. The associated Trade will be closed by a market price - * that is equal to or better than this threshold. - */ - public StopLossOrderRequest(String tradeID, String clientTradeID, String price) - { - this(tradeID, clientTradeID, price, null, null, null, null, null); - } - - /** - * Create a new stop loss order request to send to the OANDA API. - * - * @param tradeID The ID of the Trade to close when the price - * threshold is breached. - * - * @param clientTradeID The client ID of the Trade to be closed - * when the price threshold is breached. - * - * @param price The price threshold specified for the TakeProfit - * Order. The associated Trade will be closed by a market price - * that is equal to or better than this threshold. - * - * @param distance Specifies the distance (in price units) from - * the Account’s current price to use as the Stop Loss Order - * price. If the Trade is short the Instrument’s bid price is - * used, and for long Trades the ask is used. - * - * @param timeInForce The time-in-force requested for the Order. - * Restricted to “GTC”, “GFD” and “GTD” for StopLoss Orders. - * The default is TimeInForce.GTC. - * - * @param gtdTime The date when the Order will be cancelled on if - * timeInForce is GTD. - * - * @param triggerCondition Specification of which price component - * should be used when determining if an Order should be triggered - * and filled. This allows Orders to be triggered based on the - * bid, ask, mid, default (ask for buy, bid for sell) or inverse - * (ask for sell, bid for buy) price depending on the desired - * behaviour. Orders are always filled using their default price - * component. This feature is only provided through the REST - * API. Clients who choose to specify a non-default trigger - * condition will not see it reflected in any of OANDA’s - * proprietary or partner trading platforms, their transaction - * history or their account statements. OANDA platforms always - * assume that an Order’s trigger condition is set to the default - * value when indicating the distance from an Order’s trigger - * price, and will always provide the default trigger condition - * when creating or modifying an Order. A special restriction - * applies when creating a guaranteed Stop Loss Order. In this - * case the TriggerCondition value must either be “DEFAULT”, or - * the “natural” trigger side “DEFAULT” results in. So for a Stop - * Loss Order for a long trade valid values are “DEFAULT” and - * “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * The default is OrderTriggerCondition.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - */ - public StopLossOrderRequest(String tradeID, - String clientTradeID, - String price, - String distance, - TimeInForce timeInForce, - DateTime gtdTime, - OrderTriggerCondition triggerCondition, - ClientExtensions clientExtensions) - { - super(OrderType.STOP_LOSS); - - this.tradeID = tradeID; - this.clientTradeID = clientTradeID; - this.price = price; - this.distance = distance; - this.timeInForce = timeInForce; - this.gtdTime = gtdTime; - this.triggerCondition = triggerCondition; - this.clientExtensions = clientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.GTC; - - if (this.triggerCondition == null) - this.triggerCondition = OrderTriggerCondition.DEFAULT; - } -} diff --git a/src/main/java/ats/orders/StopOrderRequest.java b/src/main/java/ats/orders/StopOrderRequest.java deleted file mode 100644 index ac0aea4..0000000 --- a/src/main/java/ats/orders/StopOrderRequest.java +++ /dev/null @@ -1,264 +0,0 @@ -package ats.orders; - -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; - -/** - * Create a new stop order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class StopOrderRequest extends OrderRequest { - - /** - * Instrument to open the order on. Example: "EUR_USD" - */ - public String instrument; - - /** - * The quantity requested to be filled by the order. A - * posititive number of units results in a long Order, and a - * negative number of units results in a short Order. - */ - public int units; - - /** - * The price threshold specified for the order. The order will - * only be filled by a market price that is equal to or worse than - * this price. - */ - public String price; - - /** - * The worst market price that may be used to fill this Stop - * Order. If the market gaps and crosses through both the price - * and the priceBound, the Stop Order will be cancelled instead of - * being filled. - */ - public String priceBound; - - /** - * The time-in-force requested for the order. The default is - * TimeInForce.GTC. - */ - public TimeInForce timeInForce; - - /** - * The date/time when the order will be cancelled if its - * timeInForce is “GTD”. - */ - public DateTime gtdTime; - - /** - * Specification of how Positions in the Account are modified when - * the Order is filled. - */ - public OrderPositionFill positionFill; - - /** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This - * allows Orders to be triggered based on the bid, ask, mid, - * default (ask for buy, bid for sell) or inverse (ask for sell, - * bid for buy) price depending on the desired behaviour. Orders - * are always filled using their default price component. This - * feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see - * it reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s - * trigger condition is set to the default value when indicating - * the distance from an Order’s trigger price, and will always - * provide the default trigger condition when creating or - * modifying an Order. A special restriction applies when creating - * a guaranteed Stop Loss Order. In this case the TriggerCondition - * value must either be “DEFAULT”, or the “natural” trigger side - * “DEFAULT” results in. So for a String top Loss Order for a long - * trade valid values are “DEFAULT” and “BID”, and for short - * trades “DEFAULT” and “ASK” are valid. - */ - public OrderTriggerCondition triggerCondition; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - /** - * TakeProfitDetails specifies the details of a Take Profit Order - * to be created on behalf of a client. This may happen when an - * Order is filled that opens a Trade requiring a Take Profit, or - * when a Trade’s dependent Take Profit Order is modified directly - * through the Trade. - */ - public TakeProfitDetails takeProfitOnFill; - - /** - * StopLossDetails specifies the details of a Stop Loss Order to - * be created on behalf of a client. This may happen when an Order - * is filled that opens a Trade requiring a Stop Loss, or when a - * Trade’s dependent Stop Loss Order is modified directly through - * the Trade. - */ - public StopLossDetails stopLossOnFill; - - /** - * TrailingStopLossDetails specifies the details of a Trailing - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a - * Trailing Stop Loss, or when a Trade’s dependent Trailing Stop - * Loss Order is modified directly through the Trade. - */ - public TrailingStopLossDetails trailingStopLossOnFill; - - /** - * Client Extensions to add to the Trade created when the Order is - * filled (if such a Trade is created). Do not set, modify, or - * delete tradeClientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions tradeClientExtensions; - - - - /** - * Create a new stop order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the - * Order. A posititive number of units results in a long Order, - * and a negative number of units results in a short Order. - * - * @param price The price threshold specified for the order. The - * order will only be filled by a market price that is equal to or - * worse than this price. - */ - public StopOrderRequest(String instrument, int units, String price) - { - this(instrument, units, price, null, null, null, - null, null, null, null, null, null, null); - } - - /** - * Create a new stop order request to send to the OANDA API. - * - * @param instrument Instrument to open the order on. - * Example: "EUR_USD" - * - * @param units The quantity requested to be filled by the - * Order. A posititive number of units results in a long Order, - * and a negative number of units results in a short Order. - * - * @param price The price threshold specified for the Order. The - * Order will only be filled by a market price that is equal to or - * worse than this price. - * - * @param priceBound The worst market price that may be used to - * fill this Stop Order. If the market gaps and crosses through - * both the price and the priceBound, the Stop Order will be - * cancelled instead of being filled. - * - * @param timeInForce The time-in-force requested for the Order. - * The default is TimeInForce.GTC. - * - * @param gtdTime The date when the Order will be cancelled on if - * timeInForce is GTD. - * - * @param positionFill Specification of how Positions in the Account - * are modified when the Order is filled. The default is - * OrderPositionFill.DEFAULT. - * - * @param triggerCondition Specification of which price component - * should be used when determining if an Order should be triggered - * and filled. This allows Orders to be triggered based on the - * bid, ask, mid, default (ask for buy, bid for sell) or inverse - * (ask for sell, bid for buy) price depending on the desired - * behaviour. Orders are always filled using their default price - * component. This feature is only provided through the REST - * API. Clients who choose to specify a non-default trigger - * condition will not see it reflected in any of OANDA’s - * proprietary or partner trading platforms, their transaction - * history or their account statements. OANDA platforms always - * assume that an Order’s trigger condition is set to the default - * value when indicating the distance from an Order’s trigger - * price, and will always provide the default trigger condition - * when creating or modifying an Order. A special restriction - * applies when creating a guaranteed Stop Loss Order. In this - * case the TriggerCondition value must either be “DEFAULT”, or - * the “natural” trigger side “DEFAULT” results in. So for a Stop - * Loss Order for a long trade valid values are “DEFAULT” and - * “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * The default is OrderTriggerCondition.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - * - * @param takeProfitOnFill TakeProfitDetails specifies the details of - * a Take Profit Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Take - * Profit, or when a Trade’s dependent Take Profit Order is modified - * directly through the Trade. - * - * @param stopLossOnFill StopLossDetails specifies the details of a - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a Stop - * Loss, or when a Trade’s dependent Stop Loss Order is modified - * directly through the Trade. - * - * @param trailingStopLossOnFill TrailingStopLossDetails specifies the - * details of a Trailing Stop Loss Order to be created on behalf of a - * client. This may happen when an Order is filled that opens a Trade - * requiring a Trailing Stop Loss, or when a Trade’s dependent - * Trailing Stop Loss Order is modified directly through the Trade. - * - * @param tradeClientExtensions Client Extensions to add to the Trade - * created when the Order is filled (if such a Trade is created). Do - * not set, modify, or delete tradeClientExtensions if your account is - * associated with MT4. - */ - public StopOrderRequest(String instrument, - int units, - String price, - String priceBound, - TimeInForce timeInForce, - DateTime gtdTime, - OrderPositionFill positionFill, - OrderTriggerCondition triggerCondition, - ClientExtensions clientExtensions, - TakeProfitDetails takeProfitOnFill, - StopLossDetails stopLossOnFill, - TrailingStopLossDetails trailingStopLossOnFill, - ClientExtensions tradeClientExtensions) - { - super(OrderType.STOP); - - this.instrument = instrument; - this.units = units; - this.price = price; - this.priceBound = priceBound; - this.timeInForce = timeInForce; - this.gtdTime = gtdTime; - this.positionFill = positionFill; - this.triggerCondition = triggerCondition; - this.clientExtensions = clientExtensions; - this.takeProfitOnFill = takeProfitOnFill; - this.stopLossOnFill = stopLossOnFill; - this.trailingStopLossOnFill = trailingStopLossOnFill; - this.tradeClientExtensions = tradeClientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.GTC; - - if (this.positionFill == null) - this.positionFill = OrderPositionFill.DEFAULT; - - if (this.triggerCondition == null) - this.triggerCondition = OrderTriggerCondition.DEFAULT; - } -} diff --git a/src/main/java/ats/orders/TakeProfitDetails.java b/src/main/java/ats/orders/TakeProfitDetails.java deleted file mode 100644 index 3cf2708..0000000 --- a/src/main/java/ats/orders/TakeProfitDetails.java +++ /dev/null @@ -1,40 +0,0 @@ -package ats.orders; - -import org.joda.time.DateTime; - -/** - * TakeProfitDetails specifies the details of a Take Profit Order to - * be created on behalf of a client. This may happen when an Order is - * filled that opens a Trade requiring a Take Profit, or when a - * Trade’s dependent Take Profit Order is modified directly through - * the Trade. - * - * @see OANDA API docs - */ -public class TakeProfitDetails { - - /** - * The price that the Take Profit Order will be triggered - * at. Only one of the price and distance fields may be - * specified. - */ - public String price; - - /** - * The time in force for the created Take Profit Order. This - * may only be GTC, GTD or GFD. Default is GTC. - */ - public TimeInForce timeInForce = TimeInForce.GTC; - - /** - * The date when the Take Profit Order will be cancelled on if - * timeInForce is GTD. - */ - public DateTime gtdTime; - - /** - * The Client Extensions to add to the Take Profit Order when - * created. - */ - public ClientExtensions clientExtensions; -} diff --git a/src/main/java/ats/orders/TakeProfitOrderRequest.java b/src/main/java/ats/orders/TakeProfitOrderRequest.java deleted file mode 100644 index d93cdb9..0000000 --- a/src/main/java/ats/orders/TakeProfitOrderRequest.java +++ /dev/null @@ -1,170 +0,0 @@ -package ats.orders; - -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; - -/** - * Create a new market-if-touched order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class TakeProfitOrderRequest extends OrderRequest { - - /** - * The ID of the Trade to close when the price threshold is - * breached. - */ - public String tradeID; - - /** - * The client ID of the Trade to be closed when the price - * threshold is breached. - */ - public String clientTradeID; - - /** - * The price threshold specified for the TakeProfit Order. The - * associated Trade will be closed by a market price that is equal - * to or better than this threshold. - */ - public String price; - - /** - * The time-in-force requested for the TakeProfit - * Order. Restricted to “GTC”, “GFD” and “GTD” for TakeProfit - * Orders. The default is TimeInForce.GTC. - */ - public TimeInForce timeInForce; - - /** - * The date/time when the order will be cancelled if its - * timeInForce is “GTD”. - */ - public DateTime gtdTime; - - /** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This - * allows Orders to be triggered based on the bid, ask, mid, - * default (ask for buy, bid for sell) or inverse (ask for sell, - * bid for buy) price depending on the desired behaviour. Orders - * are always filled using their default price component. This - * feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see - * it reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s - * trigger condition is set to the default value when indicating - * the distance from an Order’s trigger price, and will always - * provide the default trigger condition when creating or - * modifying an Order. A special restriction applies when creating - * a guaranteed Stop Loss Order. In this case the TriggerCondition - * value must either be “DEFAULT”, or the “natural” trigger side - * “DEFAULT” results in. So for a Stop Loss Order for a long trade - * valid values are “DEFAULT” and “BID”, and for short trades - * “DEFAULT” and “ASK” are valid. The default is - * OrderTriggerCondition.DEFAULT. - */ - public OrderTriggerCondition triggerCondition; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - - - /** - * Create a new take profit order request to send to the OANDA - * API. - * - * @param tradeID The ID of the Trade to close when the price - * threshold is breached. - * - * @param clientTradeID The client ID of the Trade to be closed - * when the price threshold is breached. - * - * @param price The price threshold specified for the TakeProfit - * Order. The associated Trade will be closed by a market price - * that is equal to or better than this threshold. - */ - public TakeProfitOrderRequest(String tradeID, String clientTradeID, String price) - { - this(tradeID, clientTradeID, price, null, null, null, null); - } - - /** - * Create a new take profit order request to send to the OANDA - * API. - * - * @param tradeID The ID of the Trade to close when the price - * threshold is breached. - * - * @param clientTradeID The client ID of the Trade to be closed - * when the price threshold is breached. - * - * @param price The price threshold specified for the TakeProfit - * Order. The associated Trade will be closed by a market price - * that is equal to or better than this threshold. - * - * @param timeInForce The time-in-force requested for the Order. - * Restricted to “GTC”, “GFD” and “GTD” for TakeProfit Orders. - * The default is TimeInForce.GTC. - * - * @param gtdTime The date when the Order will be cancelled on if - * timeInForce is GTD. - * - * @param triggerCondition Specification of which price component - * should be used when determining if an Order should be triggered - * and filled. This allows Orders to be triggered based on the - * bid, ask, mid, default (ask for buy, bid for sell) or inverse - * (ask for sell, bid for buy) price depending on the desired - * behaviour. Orders are always filled using their default price - * component. This feature is only provided through the REST - * API. Clients who choose to specify a non-default trigger - * condition will not see it reflected in any of OANDA’s - * proprietary or partner trading platforms, their transaction - * history or their account statements. OANDA platforms always - * assume that an Order’s trigger condition is set to the default - * value when indicating the distance from an Order’s trigger - * price, and will always provide the default trigger condition - * when creating or modifying an Order. A special restriction - * applies when creating a guaranteed Stop Loss Order. In this - * case the TriggerCondition value must either be “DEFAULT”, or - * the “natural” trigger side “DEFAULT” results in. So for a Stop - * Loss Order for a long trade valid values are “DEFAULT” and - * “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * The default is OrderTriggerCondition.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - */ - public TakeProfitOrderRequest(String tradeID, - String clientTradeID, - String price, - TimeInForce timeInForce, - DateTime gtdTime, - OrderTriggerCondition triggerCondition, - ClientExtensions clientExtensions) - { - super(OrderType.TAKE_PROFIT); - - this.tradeID = tradeID; - this.clientTradeID = clientTradeID; - this.price = price; - this.timeInForce = timeInForce; - this.gtdTime = gtdTime; - this.triggerCondition = triggerCondition; - this.clientExtensions = clientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.GTC; - - if (this.triggerCondition == null) - this.triggerCondition = OrderTriggerCondition.DEFAULT; - } -} diff --git a/src/main/java/ats/orders/TimeInForce.java b/src/main/java/ats/orders/TimeInForce.java deleted file mode 100644 index 935dcf6..0000000 --- a/src/main/java/ats/orders/TimeInForce.java +++ /dev/null @@ -1,35 +0,0 @@ -package ats.orders; - -/** - * The time-in-force of an Order. TimeInForce describes how long - * an Order should remain pending before being automatically - * cancelled by the execution system. - * - * @see OANDA API docs - */ -public enum TimeInForce { - /** - * The Order is “Good unTil Cancelled” - */ - GTC, - - /** - * The Order is “Good unTil Date” and will be cancelled at the provided time - */ - GTD, - - /** - * The Order is “Good For Day” and will be cancelled at 5pm New York time - */ - GFD, - - /** - * The Order must be immediately “Filled Or Killed” - */ - FOK, - - /** - * The Order must be “Immediatedly paritally filled Or Cancelled” - */ - IOC -}; diff --git a/src/main/java/ats/orders/TrailingStopLossDetails.java b/src/main/java/ats/orders/TrailingStopLossDetails.java deleted file mode 100644 index 97f2421..0000000 --- a/src/main/java/ats/orders/TrailingStopLossDetails.java +++ /dev/null @@ -1,41 +0,0 @@ -package ats.orders; - -import java.math.BigDecimal; - -import org.joda.time.DateTime; - -/** - * TrailingStopLossDetails specifies the details of a Trailing - * Stop Loss Order to be created on behalf of a client. This may - * happen when an Order is filled that opens a Trade requiring a - * Trailing Stop Loss, or when a Trade’s dependent Trailing Stop - * Loss Order is modified directly through the Trade. - * - * @see OANDA API docs - */ -public class TrailingStopLossDetails { - /** - * The distance (in price units) from the Trade’s fill price - * that the Trailing Stop Loss Order will be triggered at. - */ - public BigDecimal distance; - - /** - * The time in force for the created Trailing Stop Loss - * Order. This may only be GTC, GTD or GFD. The default is - * GTC. - */ - public TimeInForce timeInForce = TimeInForce.GTC; - - /** - * The date when the Trailing Stop Loss Order will be - * cancelled on if timeInForce is GTD. - */ - public DateTime gtdTime; - - /** - * The Client Extensions to add to the Trailing Stop Loss Order when - * created. - */ - public ClientExtensions clientExtensions; -} diff --git a/src/main/java/ats/orders/TrailingStopLossOrderRequest.java b/src/main/java/ats/orders/TrailingStopLossOrderRequest.java deleted file mode 100644 index 0bbaf13..0000000 --- a/src/main/java/ats/orders/TrailingStopLossOrderRequest.java +++ /dev/null @@ -1,166 +0,0 @@ -package ats.orders; - -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; - -/** - * Create a new trailing stop loss order request to send to the OANDA API. - * - * @see OANDA API docs - */ -public class TrailingStopLossOrderRequest extends OrderRequest { - - /** - * The ID of the Trade to close when the price threshold is - * breached. - */ - public String tradeID; - - /** - * The client ID of the Trade to be closed when the price - * threshold is breached. - */ - public String clientTradeID; - - /** - * The price distance (in price units) specified for the - * TrailingStopLoss Order. - */ - public String distance; - - /** - * The time-in-force requested for the TrailingStopLoss - * Order. Restricted to “GTC”, “GFD” and “GTD” for - * TrailingStopLoss Orders. The default is TimeInForce.GTC. - */ - public TimeInForce timeInForce; - - /** - * The date/time when the order will be cancelled if its - * timeInForce is “GTD”. - */ - public DateTime gtdTime; - - /** - * Specification of which price component should be used when - * determining if an Order should be triggered and filled. This - * allows Orders to be triggered based on the bid, ask, mid, - * default (ask for buy, bid for sell) or inverse (ask for sell, - * bid for buy) price depending on the desired behaviour. Orders - * are always filled using their default price component. This - * feature is only provided through the REST API. Clients who - * choose to specify a non-default trigger condition will not see - * it reflected in any of OANDA’s proprietary or partner trading - * platforms, their transaction history or their account - * statements. OANDA platforms always assume that an Order’s - * trigger condition is set to the default value when indicating - * the distance from an Order’s trigger price, and will always - * provide the default trigger condition when creating or - * modifying an Order. A special restriction applies when creating - * a guaranteed Stop Loss Order. In this case the TriggerCondition - * value must either be “DEFAULT”, or the “natural” trigger side - * “DEFAULT” results in. So for a Stop Loss Order for a long trade - * valid values are “DEFAULT” and “BID”, and for short trades - * “DEFAULT” and “ASK” are valid. The default is - * OrderTriggerCondition.DEFAULT. - */ - public OrderTriggerCondition triggerCondition; - - /** - * The client extensions to add to the Order. Do not set, modify, - * or delete clientExtensions if your account is associated with - * MT4. - */ - public ClientExtensions clientExtensions; - - - - /** - * Create a new stop loss order request to send to the OANDA API. - * - * @param tradeID The ID of the Trade to close when the price - * threshold is breached. - * - * @param clientTradeID The client ID of the Trade to be closed - * when the price threshold is breached. - * - * @param price The price threshold specified for the TakeProfit - * Order. The associated Trade will be closed by a market price - * that is equal to or better than this threshold. - */ - public TrailingStopLossOrderRequest(String tradeID, String clientTradeID, String distance) - { - this(tradeID, clientTradeID, distance, null, null, null, null); - } - - /** - * Create a new stop loss order request to send to the OANDA API. - * - * @param tradeID The ID of the Trade to close when the price - * threshold is breached. - * - * @param clientTradeID The client ID of the Trade to be closed - * when the price threshold is breached. - * - * @param distance The price distance (in price units) specified - * for the TrailingStopLoss Order. - * - * @param timeInForce The time-in-force requested for the Order. - * Restricted to “GTC”, “GFD” and “GTD” for TrailingStopLoss Orders. - * The default is TimeInForce.GTC. - * - * @param gtdTime The date when the Order will be cancelled on if - * timeInForce is GTD. - * - * @param triggerCondition Specification of which price component - * should be used when determining if an Order should be triggered - * and filled. This allows Orders to be triggered based on the - * bid, ask, mid, default (ask for buy, bid for sell) or inverse - * (ask for sell, bid for buy) price depending on the desired - * behaviour. Orders are always filled using their default price - * component. This feature is only provided through the REST - * API. Clients who choose to specify a non-default trigger - * condition will not see it reflected in any of OANDA’s - * proprietary or partner trading platforms, their transaction - * history or their account statements. OANDA platforms always - * assume that an Order’s trigger condition is set to the default - * value when indicating the distance from an Order’s trigger - * price, and will always provide the default trigger condition - * when creating or modifying an Order. A special restriction - * applies when creating a guaranteed Stop Loss Order. In this - * case the TriggerCondition value must either be “DEFAULT”, or - * the “natural” trigger side “DEFAULT” results in. So for a Stop - * Loss Order for a long trade valid values are “DEFAULT” and - * “BID”, and for short trades “DEFAULT” and “ASK” are valid. - * The default is OrderTriggerCondition.DEFAULT. - * - * @param clientExtensions The client extensions to add to the - * Order. Do not set, modify, or delete clientExtensions if your - * account is associated with MT4. - */ - public TrailingStopLossOrderRequest(String tradeID, - String clientTradeID, - String distance, - TimeInForce timeInForce, - DateTime gtdTime, - OrderTriggerCondition triggerCondition, - ClientExtensions clientExtensions) - { - super(OrderType.TRAILING_STOP_LOSS); - - this.tradeID = tradeID; - this.clientTradeID = clientTradeID; - this.distance = distance; - this.timeInForce = timeInForce; - this.gtdTime = gtdTime; - this.triggerCondition = triggerCondition; - this.clientExtensions = clientExtensions; - - if (this.timeInForce == null) - this.timeInForce = TimeInForce.GTC; - - if (this.triggerCondition == null) - this.triggerCondition = OrderTriggerCondition.DEFAULT; - } -} diff --git a/src/test/java/ats/orders/MarketOrderRequestTest.java b/src/test/java/ats/orders/MarketOrderRequestTest.java deleted file mode 100644 index 4b6e6f5..0000000 --- a/src/test/java/ats/orders/MarketOrderRequestTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package ats.orders; - -import java.math.BigDecimal; - -import com.fasterxml.jackson.core.JsonProcessingException; - -import org.joda.time.DateTime; -import org.json.JSONException; -import org.junit.Test; - -/** - * MarketOrderRequestTest tests JSON format serialization of - * MarketOrderRequest objects. - */ -public class MarketOrderRequestTest extends OrderSerializationTestBase { - - - /** - * Test the simplest form, including default values. - */ - @Test - public void testToJSONSmall() - throws JsonProcessingException, JSONException - { - MarketOrderRequest obj = new MarketOrderRequest("EUR_USD", 34); - - String expected = "{\"type\":\"MARKET\",\"instrument\":\"EUR_USD\",\"units\":34,\"timeInForce\":\"FOK\",\"positionFill\":\"DEFAULT\"}"; - - doTest(obj, expected); - } - - /** - * Test a fully filled out object. - */ - @Test - public void testToJSONLarge() - throws JsonProcessingException, JSONException - { - TakeProfitDetails tpd = new TakeProfitDetails(); - tpd.price = "66.2"; - tpd.timeInForce = TimeInForce.GTD; - tpd.gtdTime = new DateTime("2010-10-10T14:15:16.000Z"); - - StopLossDetails sld = new StopLossDetails(); - sld.distance = new BigDecimal("22.7"); - sld.timeInForce = TimeInForce.IOC; - sld.gtdTime = new DateTime("2012-12-12T14:15:16.000Z"); - sld.guaranteed = true; - - TrailingStopLossDetails tsld = new TrailingStopLossDetails(); - tsld.distance = new BigDecimal("33.6"); - tsld.timeInForce = TimeInForce.IOC; - tsld.gtdTime = new DateTime("2013-3-13T14:15:16.000Z"); - - MarketOrderRequest obj = - new MarketOrderRequest("EUR_USD", 34, TimeInForce.IOC, - "99.44", OrderPositionFill.REDUCE_ONLY, - null, tpd, sld, tsld, null); - - String expected = "{\"stopLossOnFill\":{\"distance\":22.7,\"timeInForce\":\"IOC\",\"gtdTime\":\"2012-12-12T14:15:16.000Z\",\"guaranteed\":true},\"takeProfitOnFill\":{\"price\":\"66.2\",\"timeInForce\":\"GTD\",\"gtdTime\":\"2010-10-10T14:15:16.000Z\"},\"instrument\":\"EUR_USD\",\"units\":34,\"priceBound\":\"99.44\",\"type\":\"MARKET\",\"timeInForce\":\"IOC\",\"positionFill\":\"REDUCE_ONLY\",\"trailingStopLossOnFill\":{\"distance\":33.6,\"timeInForce\":\"IOC\",\"gtdTime\":\"2013-03-13T14:15:16.000Z\"}}"; - - doTest(obj, expected); - } -} diff --git a/src/test/java/ats/orders/OrderSerializationTestBase.java b/src/test/java/ats/orders/OrderSerializationTestBase.java deleted file mode 100644 index 8a80b37..0000000 --- a/src/test/java/ats/orders/OrderSerializationTestBase.java +++ /dev/null @@ -1,42 +0,0 @@ -package ats.orders; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import org.json.JSONException; -import org.skyscreamer.jsonassert.JSONAssert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * OrderSerializationTestBase is a base class for testing JSON format - * serialization of order types for sending to the OANDA api. - */ -public class OrderSerializationTestBase { - private static final Logger log = LoggerFactory.getLogger(OrderSerializationTestBase.class); - - /** - * Test an object against its expected json representation. - */ - protected void doTest(Object obj, String expected) - throws JsonProcessingException, JSONException - { - doTest(obj, expected, false); - } - - /** - * Test an object against its expected json representation. - * - * @param verbose Log a little extra if true. - */ - protected void doTest(Object obj, String expected, boolean verbose) - throws JsonProcessingException, JSONException - { - ObjectMapper mapper = OrderRequest.getJSONMapper(); - String actual = mapper.writeValueAsString(obj); - - if (verbose) log.warn(actual); - - JSONAssert.assertEquals(expected, actual, true); - } -} diff --git a/src/test/java/ats/orders/StopLossDetailsTest.java b/src/test/java/ats/orders/StopLossDetailsTest.java deleted file mode 100644 index 72737c0..0000000 --- a/src/test/java/ats/orders/StopLossDetailsTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package ats.orders; - -import java.math.BigDecimal; - -import com.fasterxml.jackson.core.JsonProcessingException; - -import org.joda.time.DateTime; -import org.json.JSONException; -import org.junit.Test; - -/** - * StopLossDetailsTest tests JSON format serialization of - * StopLossDetails objects. - */ -public class StopLossDetailsTest extends OrderSerializationTestBase { - - - /** - * Test the simplest form, including default values. - */ - @Test - public void testToJSONSmall() - throws JsonProcessingException, JSONException - { - StopLossDetails obj = new StopLossDetails(); - obj.price = "12.34"; - - String expected = "{\"price\":\"12.34\",\"timeInForce\":\"GTC\",\"guaranteed\":false}"; - - doTest(obj, expected); - } - - /** - * Test a fully filled out object. - */ - @Test - public void testToJSONLarge() - throws JsonProcessingException, JSONException - { - StopLossDetails obj = new StopLossDetails(); - obj.distance = new BigDecimal("12.34"); - obj.timeInForce = TimeInForce.GFD; - obj.gtdTime = new DateTime("2000-09-17T18:02:52.957Z"); - - obj.clientExtensions = new ClientExtensions(); - obj.clientExtensions.id = "my id"; - obj.clientExtensions.tag = "my tag"; - obj.clientExtensions.comment = "my comment"; - - String expected = "{\"distance\":12.34,\"timeInForce\":\"GFD\",\"gtdTime\":\"2000-09-17T18:02:52.957Z\",\"clientExtensions\":{\"id\":\"my id\",\"tag\":\"my tag\",\"comment\":\"my comment\"},\"guaranteed\":false}"; - doTest(obj, expected); - } -} diff --git a/src/test/java/ats/orders/TakeProfitDetailsTest.java b/src/test/java/ats/orders/TakeProfitDetailsTest.java deleted file mode 100644 index 8a529a7..0000000 --- a/src/test/java/ats/orders/TakeProfitDetailsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package ats.orders; - -import com.fasterxml.jackson.core.JsonProcessingException; - -import org.joda.time.DateTime; -import org.json.JSONException; -import org.junit.Test; - -/** - * TakeProfitDetailsTest tests JSON format serialization of - * TakeProfitDetails objects. - */ -public class TakeProfitDetailsTest extends OrderSerializationTestBase { - - - /** - * Test the simplest form, including default values. - */ - @Test - public void testToJSONSmall() throws JsonProcessingException, JSONException { - TakeProfitDetails obj = new TakeProfitDetails(); - obj.price = "12.34"; - - String expected = "{\"price\":\"12.34\",\"timeInForce\":\"GTC\"}"; - doTest(obj, expected); - } - - /** - * Test a fully filled out object. - */ - @Test - public void testToJSONLarge() throws JsonProcessingException, JSONException { - TakeProfitDetails obj = new TakeProfitDetails(); - obj.price = "12.34"; - obj.timeInForce = TimeInForce.GFD; - obj.gtdTime = new DateTime("2000-09-17T18:02:52.957Z"); - - obj.clientExtensions = new ClientExtensions(); - obj.clientExtensions.id = "my id"; - obj.clientExtensions.tag = "my tag"; - obj.clientExtensions.comment = "my comment"; - - String expected = "{\"price\":\"12.34\",\"timeInForce\":\"GFD\",\"gtdTime\":\"2000-09-17T18:02:52.957Z\",\"clientExtensions\":{\"id\":\"my id\",\"tag\":\"my tag\",\"comment\":\"my comment\"}}"; - doTest(obj, expected); - } -} diff --git a/src/test/java/ats/orders/TakeProfitOrderRequestTest.java b/src/test/java/ats/orders/TakeProfitOrderRequestTest.java deleted file mode 100644 index fc4e8b2..0000000 --- a/src/test/java/ats/orders/TakeProfitOrderRequestTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package ats.orders; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.oanda.v20.order.OrderTriggerCondition; - -import org.joda.time.DateTime; -import org.json.JSONException; -import org.junit.Test; - -/** - * TakeProfitOrderRequestTest tests JSON format serialization of - * TakeProfitOrderRequest objects. - */ -public class TakeProfitOrderRequestTest extends OrderSerializationTestBase { - - - /** - * Test the simplest form, including default values. - */ - @Test - public void testToJSONSmall() - throws JsonProcessingException, JSONException - { - TakeProfitOrderRequest obj = new TakeProfitOrderRequest("12", "23", "45.67"); - - String expected = "{\"type\":\"TAKE_PROFIT\",\"tradeID\":\"12\",\"clientTradeID\":\"23\",\"price\":\"45.67\",\"timeInForce\":\"GTC\",\"triggerCondition\":\"DEFAULT\"}"; - - doTest(obj, expected); - } - - /** - * Test a fully filled out object. - */ - @Test - public void testToJSONLarge() - throws JsonProcessingException, JSONException - { - ClientExtensions clientExtensions = new ClientExtensions(); - clientExtensions.id = "my id"; - clientExtensions.tag = "my tag"; - clientExtensions.comment = "my comment"; - - TakeProfitOrderRequest obj = new TakeProfitOrderRequest("12", "23", "45.67", - TimeInForce.IOC, - new DateTime("2000-09-17T18:02:52.957Z"), - OrderTriggerCondition.MID, - clientExtensions); - - - String expected = "{\"type\":\"TAKE_PROFIT\",\"tradeID\":\"12\",\"clientTradeID\":\"23\",\"price\":\"45.67\",\"timeInForce\":\"IOC\",\"gtdTime\":\"2000-09-17T18:02:52.957Z\",\"triggerCondition\":\"MID\",\"clientExtensions\":{\"id\":\"my id\",\"tag\":\"my tag\",\"comment\":\"my comment\"}}"; - - doTest(obj, expected); - } -} diff --git a/src/test/java/ats/orders/TrailingStopLossDetailsTest.java b/src/test/java/ats/orders/TrailingStopLossDetailsTest.java deleted file mode 100644 index 194cbaa..0000000 --- a/src/test/java/ats/orders/TrailingStopLossDetailsTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package ats.orders; - -import java.math.BigDecimal; - -import com.fasterxml.jackson.core.JsonProcessingException; - -import org.joda.time.DateTime; -import org.json.JSONException; -import org.junit.Test; - -/** - * TrailingStopLossDetailsTest tests JSON format serialization of - * TrailingStopLossDetails objects. - */ -public class TrailingStopLossDetailsTest extends OrderSerializationTestBase { - - - /** - * Test the simplest form, including default values. - */ - @Test - public void testToJSONSmall() - throws JsonProcessingException, JSONException - { - TrailingStopLossDetails obj = new TrailingStopLossDetails(); - obj.distance = new BigDecimal("12.34"); - - String expected = "{\"distance\":12.34,\"timeInForce\":\"GTC\"}"; - - doTest(obj, expected); - } - - /** - * Test a fully filled out object. - */ - @Test - public void testToJSONLarge() - throws JsonProcessingException, JSONException - { - TrailingStopLossDetails obj = new TrailingStopLossDetails(); - obj.distance = new BigDecimal("12.34"); - obj.timeInForce = TimeInForce.GFD; - obj.gtdTime = new DateTime("2000-09-17T18:02:52.957Z"); - - obj.clientExtensions = new ClientExtensions(); - obj.clientExtensions.id = "my id"; - obj.clientExtensions.tag = "my tag"; - obj.clientExtensions.comment = "my comment"; - - String expected = "{\"distance\":12.34,\"timeInForce\":\"GFD\",\"gtdTime\":\"2000-09-17T18:02:52.957Z\",\"clientExtensions\":{\"id\":\"my id\",\"tag\":\"my tag\",\"comment\":\"my comment\"}}"; - doTest(obj, expected); - } -}