diff --git a/src/main/java/ats/orders/ClientExtensions.java b/src/main/java/ats/orders/ClientExtensions.java
new file mode 100644
index 0000000..a3d4232
--- /dev/null
+++ b/src/main/java/ats/orders/ClientExtensions.java
@@ -0,0 +1,26 @@
+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
new file mode 100644
index 0000000..4812ce8
--- /dev/null
+++ b/src/main/java/ats/orders/LimitOrderRequest.java
@@ -0,0 +1,248 @@
+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
new file mode 100644
index 0000000..9d1f020
--- /dev/null
+++ b/src/main/java/ats/orders/MarketIfTouchedOrderRequest.java
@@ -0,0 +1,272 @@
+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
new file mode 100644
index 0000000..daff38a
--- /dev/null
+++ b/src/main/java/ats/orders/MarketOrderRequest.java
@@ -0,0 +1,177 @@
+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
new file mode 100644
index 0000000..b2b64bd
--- /dev/null
+++ b/src/main/java/ats/orders/OrderPositionFill.java
@@ -0,0 +1,33 @@
+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/OrderRequest.java b/src/main/java/ats/orders/OrderRequest.java
new file mode 100644
index 0000000..dbc6ee1
--- /dev/null
+++ b/src/main/java/ats/orders/OrderRequest.java
@@ -0,0 +1,66 @@
+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;
+
+/**
+ * Base class for order requests to send to the OANDA API.
+ */
+public class OrderRequest {
+ /**
+ * 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;
+ }
+
+ /**
+ * Return all properties of the request. Subclasses should
+ * override to add their own properties to the parent class'.
+ */
+ // public Map getOrderParams() {
+ // Map params = new HashMap<>();
+
+ // params.put("type", orderType.toString());
+
+ // return params;
+ // }
+
+ /**
+ * 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;
+ }
+}
diff --git a/src/main/java/ats/orders/OrderTriggerCondition.java b/src/main/java/ats/orders/OrderTriggerCondition.java
new file mode 100644
index 0000000..7d5f2f7
--- /dev/null
+++ b/src/main/java/ats/orders/OrderTriggerCondition.java
@@ -0,0 +1,59 @@
+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
new file mode 100644
index 0000000..00cf278
--- /dev/null
+++ b/src/main/java/ats/orders/OrderType.java
@@ -0,0 +1,17 @@
+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
new file mode 100644
index 0000000..1ef57d2
--- /dev/null
+++ b/src/main/java/ats/orders/StopLossDetails.java
@@ -0,0 +1,57 @@
+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
new file mode 100644
index 0000000..c95253f
--- /dev/null
+++ b/src/main/java/ats/orders/StopLossOrderRequest.java
@@ -0,0 +1,185 @@
+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
new file mode 100644
index 0000000..ac0aea4
--- /dev/null
+++ b/src/main/java/ats/orders/StopOrderRequest.java
@@ -0,0 +1,264 @@
+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
new file mode 100644
index 0000000..3cf2708
--- /dev/null
+++ b/src/main/java/ats/orders/TakeProfitDetails.java
@@ -0,0 +1,40 @@
+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
new file mode 100644
index 0000000..d93cdb9
--- /dev/null
+++ b/src/main/java/ats/orders/TakeProfitOrderRequest.java
@@ -0,0 +1,170 @@
+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
new file mode 100644
index 0000000..935dcf6
--- /dev/null
+++ b/src/main/java/ats/orders/TimeInForce.java
@@ -0,0 +1,35 @@
+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
new file mode 100644
index 0000000..97f2421
--- /dev/null
+++ b/src/main/java/ats/orders/TrailingStopLossDetails.java
@@ -0,0 +1,41 @@
+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
new file mode 100644
index 0000000..0bbaf13
--- /dev/null
+++ b/src/main/java/ats/orders/TrailingStopLossOrderRequest.java
@@ -0,0 +1,166 @@
+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
new file mode 100644
index 0000000..4b6e6f5
--- /dev/null
+++ b/src/test/java/ats/orders/MarketOrderRequestTest.java
@@ -0,0 +1,64 @@
+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
new file mode 100644
index 0000000..8a80b37
--- /dev/null
+++ b/src/test/java/ats/orders/OrderSerializationTestBase.java
@@ -0,0 +1,42 @@
+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
new file mode 100644
index 0000000..72737c0
--- /dev/null
+++ b/src/test/java/ats/orders/StopLossDetailsTest.java
@@ -0,0 +1,53 @@
+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
new file mode 100644
index 0000000..8a529a7
--- /dev/null
+++ b/src/test/java/ats/orders/TakeProfitDetailsTest.java
@@ -0,0 +1,46 @@
+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
new file mode 100644
index 0000000..fc4e8b2
--- /dev/null
+++ b/src/test/java/ats/orders/TakeProfitOrderRequestTest.java
@@ -0,0 +1,54 @@
+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
new file mode 100644
index 0000000..194cbaa
--- /dev/null
+++ b/src/test/java/ats/orders/TrailingStopLossDetailsTest.java
@@ -0,0 +1,53 @@
+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);
+ }
+}