/// <summary> /// /// </summary> /// <param name="tradeId"></param> /// <param name="takeProfitPrice"></param> /// <param name="stopLossPrice"></param> /// <returns></returns> protected virtual async Task UpdateOpenTrade(Thrust thrust, long tradeId, double?takeProfitPrice, double?stopLossPrice, int?places) { // create patch Dictionary <string, string> patchData = new Dictionary <string, string>(); if (takeProfitPrice.GetValueOrDefault() > 0) { patchData.Add("takeProfit", takeProfitPrice.ToString()); } if (stopLossPrice.GetValueOrDefault() > 0) { patchData.Add("stopLoss", stopLossPrice.ToString()); } TradeData response = null; // send patch if (patchData.Count > 0) { try { response = await Rest.PatchTradeAsync(_accountId, tradeId, patchData); } catch (Exception e) { throw e; } DateTime transactionTime = Convert.ToDateTime(response.time).ToUniversalTime(); thrust.SetOrUpdatePrices(null, takeProfitPrice, stopLossPrice, places, transactionTime); } }
/// <summary> /// /// </summary> /// <param name="signal"></param> /// <param name="instrument"></param> /// <param name="retracement"></param> /// <returns></returns> protected virtual async Task <int> CreateEntryOrder(MCE.Signal signal, Chart chart, Thrust thrust) { StrategyTransaction transaction = null; Tuple <double, double, double> orderPrices = GetOrderPrices(chart.HistoricBidAskSpread, signal.Side, thrust); double entryPrice = orderPrices.Item1; double stopLossPrice = orderPrices.Item2; double takeProfitPrice = orderPrices.Item3; int tradeUnits = await TradeUnitsCapacity(chart.Instrument, entryPrice, stopLossPrice); if (tradeUnits > 0) { // 12 hours for now .. how should this change? .. read from metaSetting? string expiry = MAOE.Utilities.GetTimeAsXmlSerializedUtc(DateTime.UtcNow.AddHours(12)); string type = "limit"; string side = signal.Side == MACC.Constants.SignalSide.Buy ? "buy" : "sell"; int places = ((FibonacciRetracement)thrust.Study).LevelPlaces(); // create order var orderData = new Dictionary <string, string> { { "instrument", chart.Instrument }, { "units", tradeUnits.ToString() }, { "side", side }, { "type", type }, { "expiry", expiry }, { "price", Math.Round(entryPrice, places).ToString() }, { "stopLoss", Math.Round(stopLossPrice, places).ToString() }, { "takeProfit", Math.Round(takeProfitPrice, places).ToString() } }; PostOrderResponse response = await PlaceLimitOrder(orderData); if (response.orderOpened != null && response.orderOpened.id > 0) { MarketMinerOrder orderOpened = new MarketMinerOrder(response.orderOpened); orderOpened.SignalID = signal.SignalID; transaction = CreateEntryTransaction(chart.Instrument, orderOpened.side, response.time, type, response.price.GetValueOrDefault(), orderOpened.takeProfit, orderOpened.stopLoss, orderOpened.id.ToString()); transaction = await StrategyCaller.Instance().SaveStrategyTransactionAsync(transaction, MarketMiner.Common.Constants.Brokers.OANDA); orderOpened.StrategyTransactionID = transaction.StrategyTransactionID; // add entry trans id to the signal signal.StrategyTransactionID = transaction.StrategyTransactionID; await SubscriptionCaller.Instance().UpdateSignalAsync(signal); AddOrUpdateAlgorithmOrder(orderOpened); DateTime transactionTime = Convert.ToDateTime(response.time).ToUniversalTime(); thrust.SetOrUpdatePrices(entryPrice, takeProfitPrice, stopLossPrice, places, transactionTime); } } else { string missedTradeReason = Utilities.GetMissedTradeReason(tradeUnits); AddAlgorithmMessage(string.Format("Missed trade: {0} for signalId: {1}", missedTradeReason, signal.SignalID), true, TraceEventType.Information); } return(transaction == null ? 0 : transaction.StrategyTransactionID); }
/// <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); } } }
protected virtual Thrust GetActiveThrust() { Thrust thrust = null; Signal signal = null; signal = SubscriptionCaller.Instance().GetActiveSignalsByType(MACC.Constants.SignalType.Thrust).FirstOrDefault(s => s.Granularity == _chart.Granularity && s.Instrument == _chart.Instrument); if (signal != null) { thrust = new Thrust(); thrust.Direction = signal.Side == MACC.Constants.SignalSide.Buy ? EPatternDirection.Up : EPatternDirection.Down; thrust.InjectWith(signal); if (signal.StrategyTransactionID.HasValue) { IEnumerable <StrategyTransaction> transactions; StrategyTransaction orderTransaction, lastOrderUpdate, lastTradeUpdate; // get transaction collection from db int orderTransactionID = signal.StrategyTransactionID.Value; transactions = StrategyCaller.Instance().GetStrategyTransactionsCollectionAsync(orderTransactionID).Result; transactions = transactions.OrderBy(t => t.BrokerTransactionID); orderTransaction = transactions.FirstOrDefault(t => t.StrategyTransactionID == orderTransactionID); lastOrderUpdate = transactions.LastOrDefault(t => t.Type == MACC.Constants.TransactionTypes.OrderUpdate); // update prices if (lastOrderUpdate != null) { thrust.SetOrUpdatePrices(lastOrderUpdate.Price, lastOrderUpdate.TakeProfit, lastOrderUpdate.StopLoss, null); } else { thrust.SetOrUpdatePrices(orderTransaction.Price, orderTransaction.TakeProfit, orderTransaction.StopLoss, null); } lastTradeUpdate = transactions.LastOrDefault(t => t.Type == MACC.Constants.TransactionTypes.TradeUpdate); if (lastTradeUpdate != null) { thrust.SetOrUpdatePrices(null, lastTradeUpdate.TakeProfit, lastTradeUpdate.StopLoss, null); } // update price times List <StrategyTransaction> updateTransactions = transactions.Where(t => t.Type == MACC.Constants.TransactionTypes.OrderUpdate || t.Type == MACC.Constants.TransactionTypes.TradeUpdate).ToList(); StrategyTransaction lastTakeProfitUpdate = orderTransaction; StrategyTransaction lastStopLossPriceUpdate = orderTransaction; if (updateTransactions.Count() > 0) { updateTransactions.OrderByDescending(t => t.BrokerTransactionID).ToList().ForEach(t => { if (t.TakeProfit != lastTakeProfitUpdate.TakeProfit) { lastTakeProfitUpdate = t; } if (t.StopLoss != lastStopLossPriceUpdate.StopLoss) { lastStopLossPriceUpdate = t; } }); } thrust.SetOrUpdatePriceUpdatedTimes(null, lastTakeProfitUpdate.Time, lastStopLossPriceUpdate.Time); } } return(thrust); }