/// <summary> /// /// </summary> /// <param name="quote"></param> /// <param name="isUp"></param> public void Update(Quote? quote, bool isUp) { _quote = quote; _isUpFromPrevious = isUp; _lastUpdate = DateTime.Now; }
public void BeginManagedOrdersUpdate(Quote? quote) { //List<Order> orders = _provider.Account.TradeEntities.GetOrdersByState(OrderStateEnum.Executed | OrderStateEnum.Submitted); if (quote.HasValue == false) { SystemMonitor.OperationError("Quote not assigned."); return; } decimal? ask = quote.Value.Ask; decimal? bid = quote.Value.Bid; decimal? spread = quote.Value.Spread; if (ask.HasValue == false || bid.HasValue == false || spread.HasValue == false) { return; } foreach (Order order in _orders.Values) { if (order.State != OrderStateEnum.Executed && order.State != OrderStateEnum.Submitted) { continue; } if (order.IsDelayed && order.State == OrderStateEnum.Submitted) {// Pending order, check for opening conditions. switch (order.Type) { case OrderTypeEnum.BUY_LIMIT_MARKET: // Submitted buy above the current price. if (order.OpenPrice <= ask) { order.AcceptPendingExecuted(ask.Value); } break; case OrderTypeEnum.BUY_STOP_MARKET: // Submitted buy below the current price. if (order.OpenPrice >= ask) { order.AcceptPendingExecuted(ask.Value); } break; case OrderTypeEnum.SELL_LIMIT_MARKET: // Submitted sell above the current price. if (order.OpenPrice <= bid) { order.AcceptPendingExecuted(bid.Value); } break; case OrderTypeEnum.SELL_STOP_MARKET: // Submitted sell below the current price. if (order.OpenPrice >= bid) { order.AcceptPendingExecuted(bid.Value); } break; } // A pending order is executed if it is between low and high. if (_lastDataBar.HasValue && order.OpenPrice.HasValue && order.State == OrderStateEnum.Submitted && order.OpenPrice <= _lastDataBar.Value.High && order.OpenPrice >= _lastDataBar.Value.Low) { order.AcceptPendingExecuted(order.OpenPrice.Value + spread.Value); } } if (order.StopLoss.HasValue && order.StopLoss.Value != 0) {// Check Stop Loss level. if ((order.IsBuy && bid <= order.StopLoss) || (order.IsBuy == false && ask >= order.StopLoss)) { if (order.State == OrderStateEnum.Executed) { string tmp; ((PassiveOrder)order).CloseOrCancel(null, null, out tmp); continue; } } } if (order.TakeProfit.HasValue && order.TakeProfit.Value != 0) {// Check Take Profit level. if ((order.IsBuy && bid >= order.TakeProfit) || (order.IsBuy == false && ask <= order.TakeProfit)) { if (order.State == OrderStateEnum.Executed) { string tmp; ((PassiveOrder)order).CloseOrCancel(null, null, out tmp); continue; } } } if ((CheckForConflictsInsideBar(order) || CheckStopLossInsideBar(order) || CheckTakeProfitInsideBar(order)) && order.State == OrderStateEnum.Executed) { string tmp; ((PassiveOrder)order).CloseOrCancel(null, null, out tmp); continue; } } // foreach }
void delivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { bool isUp = true; SymbolInformation information; lock (this) { if (_symbolQuotes.ContainsKey(session.Symbol) == false || _symbolQuotes[session.Symbol] == null) { information = new SymbolInformation(session.Symbol); _symbolQuotes.Add(session.Symbol, information); } else { information = _symbolQuotes[session.Symbol]; if (information.Quote.HasValue && quote.HasValue) { if (information.Quote.Value.Ask == quote.Value.Ask && information.Quote.Value.Bid == quote.Value.Bid) { return; } isUp = information.Quote.Value.Ask < quote.Value.Ask; } } information.Update(quote, isUp); } if (QuotesUpdateEvent != null) { QuotesUpdateEvent(this, information); } }
void _dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { if (session.Symbol == this.Symbol) { if (quote.HasValue) { lock(this) { if (this.Volume > 0) { _price = quote.Value.Ask; } else { _price = quote.Value.Bid; } } } else { _price = null; } RecalculateParameters(true); } }
void _dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { _lastDataQuote = quote; BeginAccountInfoUpdate(_account.Info); BeginManagedOrdersUpdate(quote); }
void _dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { if (_sessionInfo.Equals(session) == false) { return; } lock (this) { _lastQuoteTime = DateTime.Now; _currentQuote = quote; } if (QuoteUpdateEvent != null) { QuoteUpdateEvent(this); } }
/// <summary> /// This will work properly only for USD *BASED ACCOUNTS*. /// Code based on the forexOpenPnL.txt VB6 code file from the SDK. /// See here for details: http://finance.groups.yahoo.com/group/mbtsdk/message/6120 /// </summary> /// <returns></returns> bool CalculatePositionOpenPnLAndBasis(MbtPosition position, Quote? positionSymbolQuote, out double openPnL, out double basis) { openPnL = 0; basis = 0; if (positionSymbolQuote.HasValue == false || positionSymbolQuote.Value.Ask.HasValue == false || positionSymbolQuote.Value.Bid.HasValue == false) { return false; } long aggregatedPosition = position.AggregatePosition; if (aggregatedPosition == 0) { return true; } // This also assumes aggregatedPosition is not zero! basis = ((position.OvernightPrice * position.OvernightPosition) + (position.IntradayPrice * position.IntradayPosition)) / aggregatedPosition; Symbol? symbol = Symbol.CreateForexPairSymbol(position.Symbol); if (symbol.HasValue == false) { return false; } bool isLong = aggregatedPosition > 0; double ask = (double)positionSymbolQuote.Value.Ask.Value; double bid = (double)positionSymbolQuote.Value.Bid.Value; if (symbol.Value.ForexCurrency1 == "USD") {// Based C1. if (isLong) {// Long. long position - use Bid ' ((bid - basis) / bid) * qty openPnL = ((bid - basis) / bid) * aggregatedPosition; return true; } else {// Short. short position - use Ask ' ((ask - basis) / ask) * qty openPnL = ((ask - basis) / ask) * aggregatedPosition; return true; } } else if (symbol.Value.ForexCurrency2 == "USD") {// Based C2. if (isLong) {// Long. ' long position - use Bid ' (bid - basis) * qty openPnL = (bid - basis) * aggregatedPosition; return true; } else {// Short. ' short position - use Ask ' (ask - basis) * qty openPnL = (ask - basis) * aggregatedPosition; return true; } } else {// Not based. // This is the code that covers this scenario (from the forexOpenPnL.txt from the SDK), // however it requires the usage of other pairs data... so not implemented right now. //SystemMonitor.OperationWarning(string.Format("Position PnL not calculated for symbol [{0}] since pair not USD based.", position.Symbol)); return false; //' Neither C1 or C2 is our base. therefore, find a "related symbol" for //' C2 that will relate C2 back to our base "USD", and use the related //' symbol's Bid/Ask as part of the calculation. Do this by creating a //' temp variable "f" with the value of the Bid/Ask, inverted if necessary. //Dim f As Double // f = 0 // For j = 0 To mlSymCnt //' Find C1 base (e.g. EUR/CHF produces USD/CHF) // If Left(msSyms(j), 3) = "USD" And Right(s, 3) = Right(msSyms(j), 3) Then //' use Ask for short, Bid for long, and invert // f = 1 / (IIf(aggregatedPosition < 0, mdCAsk(j), mdCBid(j))) //' dOpenPnL = (IIf(aggregatedPosition < 0, a, b) - dBasis) * f * aggregatedPosition // Exit For ' found it ! // End If // Next // If f = 0 Then //' If C1 base not found, find C2 base (e.g. EUR/GBP produces GBP/USD) // For j = 0 To mlSymCnt // If Right(msSyms(j), 3) = "USD" And Right(s, 3) = Left(msSyms(j), 3) Then //' use Ask for short, Bid for long, but don't invert // f = IIf(aggregatedPosition < 0, mdCAsk(j), mdCBid(j)) //' dOpenPnL = (IIf(aggregatedPosition < 0, a, b) - dBasis) * f * aggregatedPosition // Exit For ' found it ! // End If // Next // End If // If f = 0 Then ' for some reason, none found (you should find out why) ! // Debug.Print "ERROR" // Else //' (bidOrAsk - basis) * f * qty //' f contains the Bid/Ask of the related symbol, inverted if necessary // dOpenPnL = (IIf(aggregatedPosition < 0, a, b) - dBasis) * f * aggregatedPosition // End If //End If } }
void ConvertQuoteRecord(ref Quote quote, QUOTERECORD pRec) { quote.Ask = (0 == pRec.dAsk) ? (decimal?)null : (decimal)pRec.dAsk; quote.Bid = (0 == pRec.dBid) ? (decimal?)null : (decimal)pRec.dBid; quote.High = (0 == pRec.dHigh) ? (decimal?)null : (decimal)pRec.dHigh; quote.Low = (0 == pRec.dLow) ? (decimal?)null : (decimal)pRec.dLow; quote.Open = (decimal)pRec.dOpen; quote.Volume = pRec.lVolume; quote.Time = pRec.UTCDateTime; }
public Quote? GetSingleSymbolQuote(string symbolName, TimeSpan timeOut, out string symbolMarket) { symbolMarket = string.Empty; if (IsInitialized == false) { return null; } string market = string.Empty; Quote? result = null; _messageLoopOperator.Invoke(delegate() { MbtQuotes client = _quotesClient; if (client == null) { return; } QUOTERECORD record = client.GetSingleQuote(symbolName, (int)timeOut.TotalMilliseconds); if (string.IsNullOrEmpty(record.bstrSymbol) == false && record.bstrSymbol.ToUpper() == symbolName.ToUpper()) {// Match found. Quote quoteResult = new Quote(); ConvertQuoteRecord(ref quoteResult, record); market = record.bstrMarket; result = quoteResult; } else { // Failed to find baseCurrency. SystemMonitor.OperationWarning("Failed to find requested symbol."); } }); if (result.HasValue) { symbolMarket = market; } return result; }
/// <summary> /// Create a dataDelivery bar based on quote. /// </summary> /// <param name="quote"></param> /// <returns></returns> public DataBar UpdateCurrentBar(DataBar currentBar, Quote quote) { if (quote.Bid.HasValue == false || quote.Ask.HasValue == false) { return currentBar; } currentBar.Low = Math.Min(quote.Bid.Value, currentBar.Low); currentBar.High = Math.Max(quote.Bid.Value, currentBar.High); currentBar.Close = quote.Bid.Value; if (quote.Volume.HasValue) { currentBar.Volume = quote.Volume.Value; } return currentBar; }
/// <summary> /// Follow quotes update. /// </summary> void _dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { if (_sessionInfo.Equals(session) == false || _period.HasValue == false || quote.HasValue == false) { return; } DataBar? lastBar = null; if (_dataBars.Count > 0) { lastBar = _dataBars[_dataBars.Count - 1]; } else {// If there are no existing bars, we do not operate, to evade mixing up start / end period etc. return; } TimeSpan? period = _period; DataBarUpdateType? updateType = null; // The time of a bar is its open time, so everything after a "period" closeVolume of time after it is part of that bar. if (lastBar.Value.DateTime + period < quote.Value.Time) {// We need to append a new bar. DateTime newBarDateTime = lastBar.Value.DateTime; int i = 0; while (newBarDateTime.Add(period.Value) < quote.Value.Time) {// Establish end time of new bar (max 1000 steps to evade potential lockups). newBarDateTime = newBarDateTime.Add(period.Value); i++; if (i > 1000) {// We have tried and failed to establish proper new period so just abort. SystemMonitor.OperationError("We have tried and failed to establish proper new period so quote aborted."); return; } } DataBar? newBar = BarFromQuote(lastBar, newBarDateTime, quote.Value); if (newBar.HasValue == false) {// Failed to establish bar from quote. return; } updateType = DataBarUpdateType.NewPeriod; lock (this) {// Add the new bar. _lastDataUpdate = DateTime.Now; _dataBars.Add(newBar.Value); } } else { updateType = DataBarUpdateType.CurrentBarUpdate; lock (this) {// Just update the current last bar. _lastDataUpdate = DateTime.Now; _dataBars[_dataBars.Count - 1] = UpdateCurrentBar(lastBar.Value, quote.Value); } } if (updateType.HasValue && DataBarHistoryUpdateEvent != null) { DataBarHistoryUpdateEvent(this, updateType.Value, 1); } }
public DataBar? BarFromQuote(DataBar? previousBar, DateTime time, Quote quote) { if ((quote.IsFullySet == false && previousBar.HasValue == false) || (quote.Ask.HasValue == false || quote.Bid.HasValue == false)) {// We need at least previous bar if quote is not fully set. return null; } decimal open = quote.Open.HasValue ? quote.Open.Value : previousBar.Value.Close; decimal close = quote.Bid.Value; DataBar result = new DataBar(time, open, Math.Max(open, close), Math.Min(open, close), close, 0); return result; }
public void BeginManagedOrdersUpdate(Quote? quote) { //List<Order> orders = _provider.Account.TradeEntities.GetOrdersByState(OrderStateEnum.Executed | OrderStateEnum.Submitted); if (quote.HasValue == false) { SystemMonitor.OperationError("Quote not assigned."); return; } decimal? ask = quote.Value.Ask; decimal? bid = quote.Value.Bid; decimal? spread = quote.Value.Spread; if (ask.HasValue == false || bid.HasValue == false || spread.HasValue == false) { return; } foreach (Order order in _orders.Values) { if (order.State != OrderStateEnum.Executed && order.State != OrderStateEnum.Submitted) { continue; } if (order.IsDelayed && order.State == OrderStateEnum.Submitted) {// Pending order, check for opening conditions. switch (order.Type) { case OrderTypeEnum.BUY_LIMIT_MARKET: // Submitted buy below the current price. if (order.OpenPrice >= ask) { DateTime? time = order.QuoteProvider != null && order.QuoteProvider.CurrentQuote.HasValue? order.QuoteProvider.CurrentQuote.Value.Time : null; order.AcceptPendingExecuted(ask.Value, time); string operationResultMessage; UpdatePosition(order.Symbol, order.CurrentDirectionalVolume, out operationResultMessage); } break; //case OrderTypeEnum.BUY_STOP_MARKET: // // Submitted buy below the current price. // if (order.OpenPrice >= ask) // { // order.AcceptPendingExecuted(ask.Value); // } // break; case OrderTypeEnum.SELL_LIMIT_MARKET: // Submitted sell above the current price. if (order.OpenPrice <= bid) { DateTime? time = order.QuoteProvider != null && order.QuoteProvider.CurrentQuote.HasValue ? order.QuoteProvider.CurrentQuote.Value.Time : null; order.AcceptPendingExecuted(bid.Value, time); string operationResultMessage; UpdatePosition(order.Symbol, order.CurrentDirectionalVolume, out operationResultMessage); } break; //case OrderTypeEnum.SELL_STOP_MARKET: // // Submitted sell below the current price. // if (order.OpenPrice >= bid) // { // order.AcceptPendingExecuted(bid.Value); // } // break; } // Don't think this is needed as it should be satisfied by the above?? // // A pending order is executed if it is between low and high. //if (_lastDataBar.HasValue // && order.OpenPrice.HasValue // && order.State == OrderStateEnum.Submitted // && order.OpenPrice <= _lastDataBar.Value.High // && order.OpenPrice >= _lastDataBar.Value.Low) //{ // order.AcceptPendingExecuted(order.OpenPrice.Value + spread.Value); //} } if (order.StopLoss.HasValue && order.StopLoss.Value != 0) {// Check Stop Loss level. if ((order.IsBuy && bid <= order.StopLoss) || (order.IsBuy == false && ask >= order.StopLoss)) { if (order.State == OrderStateEnum.Executed) { string tmp; ((PassiveOrder)order).CloseOrCancel(null, null, out tmp); continue; } } } if (order.TakeProfit.HasValue && order.TakeProfit.Value != 0) {// Check Take Profit level. if ((order.IsBuy && bid >= order.TakeProfit) || (order.IsBuy == false && ask <= order.TakeProfit)) { if (order.State == OrderStateEnum.Executed) { string tmp; ((PassiveOrder)order).CloseOrCancel(null, null, out tmp); continue; } } } if ((CheckForConflictsInsideBar(order) || CheckStopLossInsideBar(order) || CheckTakeProfitInsideBar(order)) && order.State == OrderStateEnum.Executed) { string tmp; ((PassiveOrder)order).CloseOrCancel(null, null, out tmp); continue; } } // foreach }
protected override void dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { base.dataDelivery_QuoteUpdateEvent(dataDelivery, session, quote); DoUpdate(); }
protected virtual void dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote? quote) { }
public void Quote(string sessionName, DateTime? sessionStart, Quote quote) { }
public bool RequestQuoteUpdate(DataSessionInfo sessionInfo, bool waitResult) { Quote? quote = null; lock (this) { if (_sourceDataBarProvider == null || _sourceDataBarProvider.BarCount == 0) {// No steps done yet. return true; } } lock (_sourceDataBarProvider) { if (_sourceDataBarProvider.BarCount < _step) { SystemMonitor.Error("Unexpected case."); return false; } else { if (_step - 1 >= 0 && _step - 1 < _sourceDataBarProvider.BarCount) { quote = new Quote(_sourceDataBarProvider.BarsUnsafe[_step - 1], _spreadPoints * _sessionInfo.DecimalIncrement); } } } if (quote.HasValue == false) {// No dataDelivery. return false; } if (QuoteUpdateEvent != null) { QuoteUpdateEvent(this, sessionInfo, quote); } return true; }
void ConvertQuoteRecord(ref Quote quote, Commission? commission, QUOTERECORD pRec) { quote.Ask = (0 == pRec.dAsk) ? (decimal?)null : (decimal)pRec.dAsk; quote.Bid = (0 == pRec.dBid) ? (decimal?)null : (decimal)pRec.dBid; MBTradingConnectionManager manager = _manager; if (commission.HasValue && (manager != null && manager.Adapter != null && manager.Adapter.ApplyQuoteCommission)) { commission.Value.ApplyCommissions(manager.Adapter, ref quote); } quote.High = (0 == pRec.dHigh) ? (decimal?)null : (decimal)pRec.dHigh; quote.Low = (0 == pRec.dLow) ? (decimal?)null : (decimal)pRec.dLow; quote.Open = (decimal)pRec.dOpen; quote.Volume = pRec.lVolume; quote.Time = pRec.UTCDateTime; }