private async Task RunOrdersTest() { // 2013-12-06T20:36:06Z var expiry = DateTime.Now.AddMonths(1); // XmlConvert.ToDateTime and ToString can be used for going to/from RCF3339 //string expiryString = XmlConvert.ToString(expiry, XmlDateTimeSerializationMode.Utc); // oco: dunno if this works yet .. req'd due to portable class library string expiryString = XmlConvert.ToString(expiry, "yyyy-MM-ddTHH:mm:ssZ"); // create new pending order var request = new Dictionary <string, string> { { "instrument", TestInstrument }, { "units", "1" }, { "side", "buy" }, { "type", "marketIfTouched" }, { "expiry", expiryString }, { "price", "1.0" } }; var response = await Rest.PostOrderAsync(_accountId, request); _results.Verify(response.orderOpened != null && response.orderOpened.id > 0, "Order successfully opened"); // Get open orders var orders = await Rest.GetOrderListAsync(_accountId); // Get order details if (orders.Count == 0) { _results.Add("Error: No orders to request details for..."); } else { var order = await Rest.GetOrderDetailsAsync(_accountId, orders[0].id); _results.Verify(order.id > 0, "Order details retrieved"); } // Modify an Existing order request["units"] += 10; var patchResponse = await Rest.PatchOrderAsync(_accountId, orders[0].id, request); _results.Verify(patchResponse.id > 0 && patchResponse.id == orders[0].id && patchResponse.units.ToString() == request["units"], "Order patched"); // close an order var deletedOrder = await Rest.DeleteOrderAsync(_accountId, orders[0].id); _results.Verify(deletedOrder.id > 0 && deletedOrder.units == patchResponse.units, "Order deleted"); }
public override async Task MakeRequest() { await InternalMakeRequest(() => Rest.DeleteOrderAsync(AccountDataSource.DefaultDataSource.Id, RequestHelpers.lastOrderId)); }
/// <summary> /// /// </summary> /// <param name="chart"></param> /// <param name="thrust"></param> /// <param name="retracement"></param> protected virtual async void ManageOrder(Chart chart, Thrust thrust) { StrategyTransaction[] transactions = null; StrategyTransaction orderTransaction, fillTransaction, cancelTransaction, exitTransaction; // get transaction collection from db int orderTransactionID = thrust.StrategyTransactionID.GetValueOrDefault(); transactions = await StrategyCaller.Instance().GetStrategyTransactionsCollectionAsync(orderTransactionID); orderTransaction = transactions.FirstOrDefault(t => t.StrategyTransactionID == orderTransactionID); fillTransaction = transactions.FirstOrDefault(t => t.BrokerOrderID != null && t.Type == MACC.Constants.TransactionTypes.OrderFilled); cancelTransaction = transactions.FirstOrDefault(t => t.BrokerOrderID != null && t.Type == MACC.Constants.TransactionTypes.OrderCancel); exitTransaction = transactions.FirstOrDefault(t => t.BrokerTradeID != null && t.Type != MACC.Constants.TransactionTypes.TradeUpdate); bool purgeInActiveThrust = true; if (fillTransaction == null) { if (cancelTransaction != null) { // order cancelled thrust.Active = false; } else { // order open if (!thrust.Active) { // cancel the order // the cancel transaction will be written to the db by the event stream handler await Rest.DeleteOrderAsync(_accountId, Convert.ToInt64(orderTransaction.BrokerTransactionID)); } else { if (thrust.FocusChanged() || (thrust.FillZoneReached() && thrust.TakeProfitZoneReached())) { AddAlgorithmMessage(string.Format("UPDATE ORDER: {0}: FCH-{1}: FZR-{2}: TPR-{3}", orderTransaction.Instrument, thrust.FocusChanged(), thrust.FillZoneReached(), thrust.TakeProfitZoneReached())); UpdateEntryOrder(orderTransaction, chart, thrust); } } } } else { if (exitTransaction == null) { // order filled purgeInActiveThrust = false; FibonacciRetracement retracement = (FibonacciRetracement)thrust.Study; #region get open trade info long tradeId = Convert.ToInt64(fillTransaction.BrokerTransactionID); Frame fillFrame = chart.Frames.LastOrDefault(f => Convert.ToDateTime(f.Bar.time).ToUniversalTime() <= fillTransaction.Time); int fillIndex = chart.Frames.IndexOf(fillFrame); #endregion #region get takeProfitPrice and stopLossPrice int profitWaitPeriods = Parameters.GetInteger("thrustProfitWaitPeriods") ?? 6; thrust.ProfitWindowClosed = (fillIndex + profitWaitPeriods) < chart.Frames.Count; IPriceBar lastBar = chart.Frames.Last().Bar; bool hasProfit = orderTransaction.Side == MACC.Constants.SignalSide.Buy ? lastBar.closeMid > fillTransaction.Price : lastBar.closeMid < fillTransaction.Price; #region stopLossPrice & takeProfitPrice logic // adjust stopLossPrice and takeProfitPrice // if a buy ... // move the stop to the lower of the .500 fib price or [patern lowMid price set by the post-fill price action] // move the profit target to 1 or 2 pips under .618 * (thrust.FocusPrice - [pattern lowMid price set by the post-fill price action]) // if a sell ... // move the stop to the higher of the .500 fib price or [patern highMid price set by the post-fill price action] // move the profit target to 1 or 2 pips above .618 * ([pattern lowMid price set by the post-fill price action] - thrust.FocusPrice) #endregion double?takeProfitPrice = GetAdjustedTakeProfitPrice(chart, thrust.Side, retracement); AddAlgorithmMessage(string.Format("GET SLP: {0}: TPZ-{1}: PWC-{2}: XTP-{3}: CLP-{4}: PFT-{5}", fillTransaction.Instrument, thrust.TakeProfitZoneReached(), thrust.ProfitWindowClosed, retracement.ExtremaPrice, lastBar.closeMid, hasProfit)); double?stopLossPrice = GetAdjustedStopLossPrice(chart, thrust.Side, thrust, hasProfit); #endregion #region kill or update the trade // not profitable && beyond r500 .. kill it if (stopLossPrice.GetValueOrDefault() == -1) { thrust.Active = false; purgeInActiveThrust = true; try { await Rest.DeleteTradeAsync(_accountId, tradeId); } catch (Exception e) { AddAlgorithmMessage(string.Format("CLOSE TRADE {0} Failed: {1}", tradeId, e.Message), true, TraceEventType.Error); } } else { if ((takeProfitPrice ?? thrust.TakeProfitPrice) != thrust.TakeProfitPrice || (stopLossPrice ?? thrust.StopLossPrice) != thrust.StopLossPrice) { AddAlgorithmMessage(string.Format("UPDATE TRADE: {0}: TPZ-{1}: PWC-{2}: XTP-{3}: CLP-{4}: TP-{5}: TTP-{6}: SL-{7}: TSL-{8}", fillTransaction.Instrument, thrust.TakeProfitZoneReached(), thrust.ProfitWindowClosed, retracement.ExtremaPrice, lastBar.closeMid, takeProfitPrice, thrust.TakeProfitPrice, stopLossPrice, thrust.StopLossPrice)); UpdateOpenTrade(thrust, tradeId, takeProfitPrice, stopLossPrice, retracement.LevelPlaces()); } } #endregion } else { // trade closed #region about closed trades // if coll includes a stopLossFilled or takeProfitFilled .. // set thrust.Active = false // this be done server side when the strategyTransaction from the stream is saved // the signal should be found on the server and signal.Active should be set to false // do it here also #endregion thrust.Active = false; } } if (!thrust.Active && purgeInActiveThrust) { await PurgeThrust(chart, thrust); } }
/// <summary> /// /// </summary> /// <param name="orderTransaction"></param> /// <param name="thrust"></param> /// <param name="retracement"></param> /// <returns></returns> protected virtual async Task UpdateEntryOrder(StrategyTransaction orderTransaction, Chart chart, Thrust thrust) { long orderId = Convert.ToInt64(orderTransaction.BrokerTransactionID); MarketMinerOrder currentOrder = Orders.FirstOrDefault(o => o.id == orderId) as MarketMinerOrder; string side = thrust.Side; Tuple <double, double, double> orderPrices = GetOrderPrices(chart.HistoricBidAskSpread, side, thrust); double entryPrice = orderPrices.Item1; double stopLossPrice = orderPrices.Item2; double takeProfitPrice = orderPrices.Item3; // round and review int places = ((FibonacciRetracement)thrust.Study).LevelPlaces(); bool updateOrder = false; if (currentOrder == null) { updateOrder = true; } else { if (Math.Round(entryPrice, places) != currentOrder.price) { updateOrder = true; } if (Math.Round(stopLossPrice, places) != currentOrder.stopLoss) { updateOrder = true; } if (Math.Round(takeProfitPrice, places) != currentOrder.takeProfit) { updateOrder = true; } } if (updateOrder) { int tradeUnits = await TradeUnitsCapacity(thrust.Instrument, entryPrice, stopLossPrice, true); // order size should never increase tradeUnits = currentOrder != null?Math.Min(currentOrder.units, tradeUnits) : tradeUnits; if (tradeUnits > 0) { // 12 hours for now .. how should this change? string expiry = MAOE.Utilities.GetTimeAsXmlSerializedUtc(DateTime.UtcNow.AddHours(12)); // create patch var patchData = new Dictionary <string, string> { { "units", tradeUnits.ToString() }, { "expiry", expiry }, { "price", Math.Round(entryPrice, places).ToString() }, { "stopLoss", Math.Round(stopLossPrice, places).ToString() }, { "takeProfit", Math.Round(takeProfitPrice, places).ToString() } }; // what if the fill happens just as execution arrives here? // this bit should somehow affirm that the order remains unfilled Order updatedOrder = await Rest.PatchOrderAsync(_accountId, orderId, patchData); if (updatedOrder != null) { MarketMinerOrder mmUpdatedOrder = new MarketMinerOrder(updatedOrder); mmUpdatedOrder.SignalID = thrust.SignalID; mmUpdatedOrder.StrategyTransactionID = orderTransaction.StrategyTransactionID; AddOrUpdateAlgorithmOrder(mmUpdatedOrder); DateTime transactionTime = Convert.ToDateTime(updatedOrder.time).ToUniversalTime(); thrust.SetOrUpdatePrices(entryPrice, takeProfitPrice, stopLossPrice, places, transactionTime); } } else { thrust.Active = false; // cancel the order await Rest.DeleteOrderAsync(_accountId, orderId); // clear the chart PurgeThrust(chart, thrust); string missedTradeReason = Utilities.GetMissedTradeReason(tradeUnits); AddAlgorithmMessage(string.Format("Missed trade: {0} for signalId: {1}", missedTradeReason, thrust.SignalID), true, TraceEventType.Information); } } }