public Alert ExitAlertCreate(Bar exitBar, Position position, double stopOrLimitPrice, string signalName,
			Direction direction, MarketLimitStop exitMarketLimitStop) {

			this.checkThrowEntryBarIsValid(exitBar);
			this.checkThrowPositionToCloseIsValid(position);

			double priceScriptOrStreaming = stopOrLimitPrice;
			OrderSpreadSide orderSpreadSide = OrderSpreadSide.Unknown;
			if (exitMarketLimitStop == MarketLimitStop.Market) {
				priceScriptOrStreaming = this.getStreamingPriceForMarketOrder(exitMarketLimitStop, direction, out orderSpreadSide);
			}

			PositionLongShort longShortFromDirection = MarketConverter.LongShortFromDirection(direction);
			double exitPriceScript = exitBar.ParentBars.SymbolInfo.RoundAlertPriceToPriceLevel(
				priceScriptOrStreaming, true, longShortFromDirection, exitMarketLimitStop);

			Alert alert = new Alert(exitBar, position.Shares, exitPriceScript, signalName,
				direction, exitMarketLimitStop, orderSpreadSide,
				//this.executor.Script,
				this.executor.Strategy);
			alert.AbsorbFromExecutor(executor);
			alert.PositionAffected = position;
			// moved to CallbackAlertFilled - we can exit by TP or SL - and position has no clue which Alert was filled!!!
			//position.ExitCopyFromAlert(alert);
			alert.PositionAffected.ExitAlertAttach(alert);

			return alert;
		}
		public Alert EntryAlertCreate(Bar entryBar, double stopOrLimitPrice, string entrySignalName,
			Direction direction, MarketLimitStop entryMarketLimitStop) {

			this.checkThrowEntryBarIsValid(entryBar);

			double priceScriptOrStreaming = stopOrLimitPrice;
			OrderSpreadSide orderSpreadSide = OrderSpreadSide.Unknown;
			if (entryMarketLimitStop == MarketLimitStop.Market) {
				priceScriptOrStreaming = this.getStreamingPriceForMarketOrder(entryMarketLimitStop, direction, out orderSpreadSide);
			}

			PositionLongShort longShortFromDirection = MarketConverter.LongShortFromDirection(direction);
			// ALREADY_ALIGNED_AFTER GetAlignedBidOrAskForTidalOrCrossMarketFromStreaming
			double entryPriceScript = entryBar.ParentBars.SymbolInfo.RoundAlertPriceToPriceLevel(
				priceScriptOrStreaming, true, longShortFromDirection, entryMarketLimitStop);

			double shares = this.executor.PositionSizeCalculate(entryBar, entryPriceScript);

			Alert alert = new Alert(entryBar, shares, entryPriceScript, entrySignalName,
				direction, entryMarketLimitStop, orderSpreadSide,
				//this.executor.Script,
				this.executor.Strategy);
			alert.AbsorbFromExecutor(executor);

			return alert;
		}
		public override void SelectAlert(Alert alert) {
			this.ActivateParentForm();
			if (alert == null) {
				string msg = "DONT_PASS_ALERT=NULL_TO_CHART_SHADOW ChartControl.SelectAlert()";
				Assembler.PopupException(msg);
				#if DEBUG
				Debugger.Break();
				#endif
				return;
			}
			if (alert.PlacedBar == null) {
				string msg = "DONT_PASS_ALERT.PLACEDBAR=NULL_TO_CHART_SHADOW ChartControl.SelectAlert()";
				Assembler.PopupException(msg);
				#if DEBUG
				Debugger.Break();
				#endif
				return;
			}
			if (alert.PlacedBar.HasParentBars == false) {
				string msg = "DONT_PASS_ALERT.PLACEDBAR.HASPARENTBARS=FALSE_TO_CHART_SHADOW ChartControl.SelectAlert()";
				Assembler.PopupException(msg);
				#if DEBUG
				Debugger.Break();
				#endif
				return;
			}
			int bar = alert.PlacedBar.ParentBarsIndex;		
			this.scrollToBarSafely(bar);
		}		
		public bool SimulateFill(Alert alert, out bool abortTryFill, out string abortTryFillReason) {
			abortTryFill = false;
			abortTryFillReason = "ABORT_NO_REASON_SO_SHOULD_CONTINUE_TRY_FILL";
			if (alert.DataSource.BrokerProviderName.Contains("Mock") == false) {
				string msg = "SimulateRealtimeOrderFill() should be called only from BrokerProvidersName.Contains(Mock)"
					+ "; here you have MOCK Realtime Streaming and Broker,"
					+ " it's not a time-insensitive QuotesFromBar-generated Streaming Backtest"
					+ " (both are routed to here, MarketSim, hypothetical order execution)";
				throw new Exception(msg);
			}

			if (alert.PositionAffected == null) {
				string msg = "alertToBeKilled always has a PositionAffected, even for OnChartManual Buy/Short Market/Stop/Limit";
				throw new Exception(msg);
			}

			bool filled = false;
			double priceFill = -1;
			double slippageFill = -1;
			Quote quote = this.executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetForSymbol(alert.Symbol);
			if (quote == null) {
				string msg = "how come LastQuoteGetForSymbol(" + alert.Symbol + ")=null??? StreamingProvider[" + this.executor.DataSource.StreamingProvider + "]";
				//this.executor.PopupException(new Exception(msg));
				return false;
			}

			if (alert.IsEntryAlert) {
				if (alert.PositionAffected.IsEntryFilled) {
					string msg = "PositionAffected.EntryFilled => did you create many threads in your QuikTerminalMock?";
					throw new Exception(msg);
				}
				filled = this.CheckEntryAlertWillBeFilledByQuote(alert, quote, out priceFill, out slippageFill);
			} else {
				if (alert.PositionAffected.IsEntryFilled == false) {
					string msg = "I refuse to tryFill an ExitOrder because ExitOrder.Alert.PositionAffected.EntryFilled=false";
					throw new Exception(msg);
				}
				if (alert.PositionAffected.IsExitFilled) {
					string msg = null;
					if (alert.PositionAffected.IsExitFilledWithPrototypedAlert) {
						msg = "ExitAlert already filled and Counterparty.Status=["
							+ alert.PositionAffected.PrototypedExitCounterpartyAlert.OrderFollowed.State + "] (does it look OK for you?)";
					} else {
						msg = "I refuse to tryFill non-Prototype based ExitOrder having PositionAffected.IsExitFilled=true";
					}
					abortTryFill = true;
					abortTryFillReason = msg;
					// abortTryFillReason goes to the order.Message inside the caller
					//this.executor.ThrowPopup(new Exception(msg));
					return false;
				}
				try {
					filled = this.CheckExitAlertWillBeFilledByQuote(alert, quote, out priceFill, out slippageFill);
				} catch (Exception e) {
					int a = 1;
				}
			}
			return filled;
		}
		bool checkIfAlertDoesntHaveAnArrow(List<AlertArrow> alertArrowsSameBar, Alert alert) {
			Alert mustBeNull = null;
			foreach (AlertArrow each in alertArrowsSameBar) {
				Alert alertSameDirection = each.ArrowIsForPositionEntry ? each.Position.EntryAlert : each.Position.ExitAlert;
				if (alertSameDirection != alert) continue;
				mustBeNull = alertSameDirection;
				break;
			}
			if (mustBeNull != null) {
				string msg = "DUPLICATE_ALERTARROW mustBeNull=[" + mustBeNull + "])";
				Assembler.PopupException(msg);
			}
			return mustBeNull == null;
		}
		public static Brush AlertPendingToBrushColor(Alert alert) {
			Brush brush = Brushes.Black;
			switch (alert.Direction) {
				case Direction.Buy:
					brush = Brushes.Blue;
					break;
				case Direction.Sell:
					brush = Brushes.Red;
					break;
				case Direction.Short:
					brush = Brushes.Fuchsia;
					break;
				case Direction.Cover:
					brush = Brushes.Green;
					break;
			}
			return brush;
		}
		public Order CreatePropagateOrderFromAlert(Alert alert, bool setStatusSubmitting, bool fromAutoTrading) {
			if (alert.MarketLimitStop == MarketLimitStop.AtClose) {
				string msg = "NYI: alert.OrderType= OrderType.AtClose [" + alert + "]";
				throw new Exception(msg);
			}
			Order newborn = new Order(alert, fromAutoTrading, false);
			try {
				newborn.Alert.DataSource.BrokerProvider.ModifyOrderTypeAccordingToMarketOrderAs(newborn);
			} catch (Exception e) {
				string msg = "hoping that MarketOrderAs.MarketMinMax influenced order.Alert.MarketLimitStop["
					+ newborn.Alert.MarketLimitStop + "]=MarketLimitStop.Limit for further match; PREV=" + newborn.LastMessage;
				this.AppendOrderMessageAndPropagateCheckThrowOrderNull(newborn, msg);
			}
			if (alert.IsExitAlert) {
				if (this.isExitOrderConsistentLogInconsistency(newborn) == false) {
					this.DataSnapshot.OrderAddSynchronizedAndPropagate(newborn);
					string reason = newborn.LastMessage;
					return null;
				}
				//adjustExitOrderQtyRequestedToMatchEntry(order);
				alert.PositionAffected.EntryAlert.OrderFollowed.DerivedOrdersAdd(newborn);
			}

			OrderState newbornOrderState = OrderState.AutoSubmitNotEnabled;
			string newbornMessage = "alert[" + alert + "]";

			if (setStatusSubmitting == true) {
				if (newborn.hasBrokerProvider("CreatePropagateOrderFromAlert(): ") == false) {
					string msg = "CRAZY #61";
					Assembler.PopupException(msg);
					return null;
				}
				newbornOrderState = this.IsOrderEatable(newborn) ? OrderState.Submitting : OrderState.ErrorSubmittingNotEatable;
				//string isPastDue = newborn.Alert.IsAlertCreatedOnPreviousBar;
				//if (fromAutoTrading && String.IsNullOrEmpty(isPastDue) == false) {
				//	newbornMessage += "; " + isPastDue;
				//	newbornOrderState = OrderState.AlertCreatedOnPreviousBarNotAutoSubmitted;
				//}
			}
			this.UpdateOrderStateNoPostProcess(newborn, new OrderStateMessage(newborn, newbornOrderState, newbornMessage));
			this.DataSnapshot.OrderAddSynchronizedAndPropagate(newborn);
			this.DataSnapshot.SerializerLogrotateOrders.HasChangesToSave = true;
			return newborn;
		}
		public List<Alert> AlertFilledCreateSlTpOrAnnihilateCounterparty(Alert alert) {
			List<Alert> ret = new List<Alert>();
			if (alert.PositionAffected == null) return ret;
			if (alert.PositionAffected.Prototype == null) return ret;
			if (alert.IsEntryAlert) {
				return this.CreateStopLossAndTakeProfitAlertsFromPositionPrototype(alert.PositionAffected);
			} else {
				bool killed = this.AnnihilateCounterpartyForClosedPosition(alert.PositionAffected);
				return ret;
			}
		}
		public void CallbackAlertFilledMoveAroundInvokeScript(Alert alertFilled, Quote quote,
					 int barFillRelno, double priceFill, double qtyFill, double slippageFill, double commissionFill) {
			string msig = " CallbackAlertFilledMoveAroundInvokeScript(" + alertFilled + ", " + quote + ")";
			List<Alert> alertsNewAfterAlertFilled = new List<Alert>();
			List<Position> positionsOpenedAfterAlertFilled = new List<Position>();
			List<Position> positionsClosedAfterAlertFilled = new List<Position>();

			//"Excuse me, what bar is it now?" I'm just guessing! does BrokerProvider knows to pass Bar here?...
			Bar barFill = (this.IsStreaming) ? alertFilled.Bars.BarStreamingCloneReadonly : alertFilled.Bars.BarStaticLast;
			if (barFillRelno != barFill.ParentBarsIndex) {
				string msg = "barFillRelno[" + barFillRelno + "] != barFill.ParentBarsIndex["
					+ barFill.ParentBarsIndex + "]; barFill=[" + barFill + "]";
				Assembler.PopupException(msg);
			}
			if (priceFill == -1) {
				string msg = "won't set priceFill=-1 for alert [" + alertFilled + "]";
				throw new Exception(msg);
			}
			if (alertFilled.PositionAffected == null) {
				string msg = "CallbackAlertFilled can't do its job: alert.PositionAffected=null for alert [" + alertFilled + "]";
				throw new Exception(msg);
			}
			if (alertFilled.IsEntryAlert) {
				if (alertFilled.PositionAffected.EntryFilledBarIndex != -1) {
					string msg = "DUPE: CallbackAlertFilled can't do its job: alert.PositionAffected.EntryBar!=-1 for alert [" + alertFilled + "]";
					throw new Exception(msg);
				} else {
					string msg = "initializing EntryBar=[" + barFill + "] on AlertFilled";
				}
			} else {
				if (alertFilled.PositionAffected.ExitFilledBarIndex != -1) {
					string msg = "DUPE: CallbackAlertFilled can't do its job: alert.PositionAffected.ExitBar!=-1 for alert [" + alertFilled + "]";
					throw new Exception(msg);
					return;
				} else {
					string msg = "initializing ExitBar=[" + barFill + "] on AlertFilled";
				}
			}

			if (quote == null) {
				quote = this.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetForSymbol(alertFilled.Symbol);
				// TODO: here quote will have NO_PARENT_BARS, since StreamingDataSnapshot contains anonymous quote;
				// I should keep per-timeframe / per-distributionChannel LastQuote to have ParentBar= different StreamingBar 's
				// bindStreamingBarForQuoteAndPushQuoteToConsumers(quoteSernoEnrichedWithUnboundStreamingBar.Clone());
			}
			alertFilled.QuoteLastWhenThisAlertFilled = quote;
			try {
				alertFilled.FillPositionAffectedEntryOrExitRespectively(barFill, barFillRelno, priceFill, qtyFill, slippageFill, commissionFill);
			} catch (Exception ex) {
				string msg = "REMOVE_FILLED_FROM_PENDING? DONT_USE_Bar.ContainsPrice()?";
				Assembler.PopupException(msg + msig, ex);
				//Debugger.Break();
			}
			bool removed = this.ExecutionDataSnapshot.AlertsPendingRemove(alertFilled);
			if (removed == false) {
				Debugger.Break();
			}
			if (alertFilled.IsEntryAlert) {
				// position has its parent alert in Position.ctor()
				//// REFACTORED_POSITION_HAS_AN_ALERT_AFTER_ALERTS_CONSTRUCTOR
				//alert.PositionAffected.EntryCopyFromAlert(alert);
				this.ExecutionDataSnapshot.PositionsMasterOpenNewAdd(alertFilled.PositionAffected);
				positionsOpenedAfterAlertFilled.Add(alertFilled.PositionAffected);
			} else {
				//// REFACTORED_POSITION_HAS_AN_ALERT_AFTER_ALERTS_CONSTRUCTOR we can exit by TP or SL - position doesn't have an ExitAlert assigned until Alert was filled!!!
				//alertFilled.PositionAffected.ExitAlertAttach(alertFilled);
				this.ExecutionDataSnapshot.MovePositionOpenToClosed(alertFilled.PositionAffected);
				positionsClosedAfterAlertFilled.Add(alertFilled.PositionAffected);
			}

			bool willPlace = this.Backtester.IsBacktestingNow == false && this.OrderProcessor != null && this.IsAutoSubmitting;
			bool setStatusSubmitting = this.IsStreaming && this.IsAutoSubmitting;

			PositionPrototype proto = alertFilled.PositionAffected.Prototype;
			if (proto != null) {
				// 0. once again, set ExitAlert to What was actually filled, because prototypeEntry created SL & TP, which were both written into ExitAlert;
				// so if we caught the Loss and SL was executed, position.ExitAlert will still contain TP if we don't set it here
				bool exitIsDifferent = alertFilled.PositionAffected.ExitAlert != null && alertFilled.PositionAffected.ExitAlert != alertFilled;
				if (alertFilled.IsExitAlert && exitIsDifferent) {
					alertFilled.PositionAffected.ExitAlertAttach(alertFilled);
				}
				// 1. alert.PositionAffected.Prototype.StopLossAlertForAnnihilation and TP will get assigned
				alertsNewAfterAlertFilled = this.PositionPrototypeActivator.AlertFilledCreateSlTpOrAnnihilateCounterparty(alertFilled);
				// quick check: there must be {SL+TP} OR Annihilator
				//this.BacktesterFacade.IsBacktestingNow == false &&
				if (alertFilled.IsEntryAlert) {
					if (proto.StopLossAlertForAnnihilation == null) {
						string msg = "NONSENSE@Entry: proto.StopLossAlert is NULL???..";
						throw new Exception(msg);
					}
					if (proto.TakeProfitAlertForAnnihilation == null) {
						string msg = "NONSENSE@Entry: proto.TakeProfitAlert is NULL???..";
						throw new Exception(msg);
					}
					if (alertsNewAfterAlertFilled.Count == 0) {
						string msg = "NONSENSE@Entry: alertsNewSlAndTp.Count=0"
							+ "; this.PositionPrototypeActivator.AlertFilledCreateSlTpOrAnnihilateCounterparty(alertFilled)"
							+ " should return 2 alerts; I don't want to create new list from {proto.SL, proto.TP}";
						throw new Exception(msg);
					}
				}
				if (alertFilled.IsExitAlert) {
					if (alertsNewAfterAlertFilled.Count > 0) {
						string msg = "NONSENSE@Exit: there must be no alerts (got " + alertsNewAfterAlertFilled.Count + "): killer works silently";
						throw new Exception(msg);
					}
				}

				if (alertsNewAfterAlertFilled.Count > 0 && willPlace) {
					this.OrderProcessor.CreateOrdersSubmitToBrokerProviderInNewThreadGroups(alertsNewAfterAlertFilled, setStatusSubmitting, true);

					// 3. Script using proto might move SL and TP which require ORDERS to be moved, not NULLs
					int twoMinutes = 120000;
					if (alertFilled.IsEntryAlert) {
						// there must be SL.OrderFollowed!=null and TP.OrderFollowed!=null
						if (proto.StopLossAlertForAnnihilation.OrderFollowed == null) {
							string msg = "StopLossAlert.OrderFollowed is NULL!!! engaging ManualResetEvent.WaitOne()";
							this.PopupException(msg);
							Stopwatch waitedForStopLossOrder = new Stopwatch();
							waitedForStopLossOrder.Start();
							proto.StopLossAlertForAnnihilation.MreOrderFollowedIsNotNull.WaitOne(twoMinutes);
							waitedForStopLossOrder.Stop();
							msg = "waited " + waitedForStopLossOrder.ElapsedMilliseconds + "ms for StopLossAlert.OrderFollowed";
							if (proto.StopLossAlertForAnnihilation.OrderFollowed == null) {
								msg += ": NO_SUCCESS still null!!!";
								this.PopupException(msg);
							} else {
								proto.StopLossAlertForAnnihilation.OrderFollowed.AppendMessage(msg);
								this.PopupException(msg);
							}
						} else {
							string msg = "you are definitely crazy, StopLossAlert.OrderFollowed is a single-threaded assignment";
							//this.ThrowPopup(new Exception(msg));
						}

						if (proto.TakeProfitAlertForAnnihilation.OrderFollowed == null) {
							string msg = "TakeProfitAlert.OrderFollowed is NULL!!! engaging ManualResetEvent.WaitOne()";
							this.PopupException(msg);
							Stopwatch waitedForTakeProfitOrder = new Stopwatch();
							waitedForTakeProfitOrder.Start();
							proto.TakeProfitAlertForAnnihilation.MreOrderFollowedIsNotNull.WaitOne();
							waitedForTakeProfitOrder.Stop();
							msg = "waited " + waitedForTakeProfitOrder.ElapsedMilliseconds + "ms for TakeProfitAlert.OrderFollowed";
							if (proto.TakeProfitAlertForAnnihilation.OrderFollowed == null) {
								msg += ": NO_SUCCESS still null!!!";
								this.PopupException(msg);
							} else {
								proto.TakeProfitAlertForAnnihilation.OrderFollowed.AppendMessage(msg);
								this.PopupException(msg);
							}
						} else {
							string msg = "you are definitely crazy, TakeProfitAlert.OrderFollowed is a single-threaded assignment";
							//this.ThrowPopup(new Exception(msg));
						}
					}
				}
			}

			if (this.Backtester.IsBacktestingNow == false) {
				ReporterPokeUnit pokeUnit = new ReporterPokeUnit(quote);
				pokeUnit.AlertsNew = alertsNewAfterAlertFilled;
				pokeUnit.PositionsOpened = positionsOpenedAfterAlertFilled;
				pokeUnit.PositionsClosed = positionsClosedAfterAlertFilled;
				this.PushPositionsOpenedClosedToReportersAsyncUnsafe(pokeUnit);
			}

			// 4. Script event will generate a StopLossMove PostponedHook
			this.invokeScriptEvents(alertFilled);

			// reasons for (alertsNewAfterExec.Count > 0) include:
			// 2.1. PrototypeActivator::AlertFilledPlaceSlTpOrAnnihilateCounterparty
			// 2.2. Script.OnAlertFilledCallback(alert)
			// 2.3. Script.OnPositionOpenedPrototypeSlTpPlacedCallback(alert.PositionAffected)
			// 2.4. Script.OnPositionClosedCallback(alert.PositionAffected)
		}
Exemplo n.º 10
0
		public Position(Alert alertEntry, double basisPrice) : this(alertEntry.Bars
				, alertEntry.PositionLongShortFromDirection, alertEntry.StrategyID.ToString()
				, basisPrice, alertEntry.Qty) {
			this.EntryAlert = alertEntry;
			this.EntryMarketLimitStop = alertEntry.MarketLimitStop;
			this.EntryPriceScript = alertEntry.PriceScript;
			this.EntrySignal = alertEntry.SignalName;
		}
Exemplo n.º 11
0
		public void ExitAlertAttach(Alert alertExit) {
			if (this.Prototype == null) {
				if (this.ExitAlert != null) {
					string msg = "POSITION_WAS_ALREADY_ATTCHED_TO_EXIT_ALERT ExitAlert[" + this.ExitAlert + "] ";
					throw new Exception(msg);
				}
				if (this.ExitMarketLimitStop != MarketLimitStop.Unknown) {
					string msg = "POSITION_WAS_ALREADY_SYNCHED_WITH_FILLED_ALERT_ON_ALERT_FILLED_CALLBACK: ExitPriceScript[" + this.ExitPriceScript + "]";
					throw new Exception(msg);
				}
			} else {
				if (this.ExitAlert != null) {
					if (alertExit.IsFilled == false) {
						string msg = "REPLACING_FIRST_CREATED_STOPLOSS_WITH_SECOND_CREATED_TAKEPROFIT ExitAlert[" + this.ExitAlert.SignalName + "] shouldBeTakeprofit[" + alertExit.SignalName + "]";
					} else {
						string msg = "REPLACING_EXIT_ALERT_WITH_PROTOTYPED_TP_OR_SL_WHICHEVER_FILLED_FIRST ExitAlert[" + this.ExitAlert + "] filledFirst[" + alertExit + "]";
					}
				}
			}
			this.ExitAlert = alertExit;
			this.ExitMarketLimitStop = alertExit.MarketLimitStop;
			this.ExitPriceScript = alertExit.PriceScript;
			this.ExitSignal = alertExit.SignalName;
		}
		public void RemovePendingExitAlert(Alert alert, string msig) {
			string msg = "";
			ExecutionDataSnapshot snap = alert.Strategy.Script.Executor.ExecutionDataSnapshot;
			//this.executor.ExecutionDataSnapshot.AlertsPendingRemove(alert);
			string orderState = (alert.OrderFollowed == null) ? "alert.OrderFollowed=NULL" : alert.OrderFollowed.State.ToString();
			if (snap.AlertsPendingContains(alert)) {
				bool removed = snap.AlertsPendingRemove(alert);
				msg = "REMOVED " + orderState + " Pending alert[" + alert + "] ";
			} else {
				msg = "CANT_BE_REMOVED " + orderState + " isn't Pending alert[" + alert + "] ";
			}
			if (alert.OrderFollowed == null) {
				if (this.Backtester.IsBacktestingNow == false) {
					msg = "RealTime alerts should NOT have OrderFollowed=null; " + msg;
					throw new Exception(msg);
				}
				return;
			}
			// OrderFollowed=null when executeStrategyBacktestEntryPoint() is in the call stack
			this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
		}
Exemplo n.º 13
0
		public void AlertKillPending(Alert alert) {
			this.Executor.AlertKillPending(alert);
		}
		public override void OnAlertNotSubmittedCallback(Alert alertNotSubmitted, int barNotSubmittedRelno) {
			Debugger.Break();
		}
		public void CreatedOrderWontBePlacedPastDueInvokeScript(Alert alert, int barNotSubmittedRelno) {
			//this.ExecutionDataSnapshot.AlertsPendingRemove(alert);
			if (alert.IsEntryAlert) {
				this.RemovePendingEntry(alert);
				this.ClosePositionWithAlertClonedFromEntryBacktestEnded(alert);
			} else {
				string msg = "checkPositionCanBeClosed() will later interrupt the flow saying {Sorry I don't serve alerts.IsExitAlert=true}";
				this.RemovePendingExitAlertPastDueClosePosition(alert);
			}
			if (this.Strategy.Script == null) return;
			try {
				this.Strategy.Script.OnAlertNotSubmittedCallback(alert, barNotSubmittedRelno);
			} catch (Exception e) {
				string msg = "fix your OnAlertNotSubmittedCallback() in script[" + this.Strategy.Script.StrategyName + "]"
					+ "; was invoked with alert[" + alert + "] and barNotSubmittedRelno["
					+ barNotSubmittedRelno + "]";
				this.PopupException(msg, e);
			}
		}
		public static BidOrAsk BidOrAskWillFillAlert(Alert alert) {
			BidOrAsk ret = BidOrAsk.UNKNOWN;
			switch (alert.MarketLimitStop) {
				case MarketLimitStop.Market:
				case MarketLimitStop.Limit:
					switch (alert.Direction) {
						//http://www.metatrader5.com/en/terminal/help/trading/general_concept/order_types
						case Direction.Short:
						case Direction.Sell:
							ret = BidOrAsk.Bid;
							break;
						case Direction.Buy:
						case Direction.Cover:
							ret = BidOrAsk.Ask;
							break;
						default:
							throw new Exception("BidOrAskWillFillAlert(): NYI direction[" + alert.Direction + "] for [" + alert + "]");
					}
					break;
				case MarketLimitStop.Stop:
				case MarketLimitStop.StopLimit:
					switch (alert.Direction) {
						//http://www.metatrader5.com/en/terminal/help/trading/general_concept/order_types
						case Direction.Short:
						case Direction.Sell:
							ret = BidOrAsk.Bid;
							break;
						case Direction.Buy:
						case Direction.Cover:
							ret = BidOrAsk.Ask;
							break;
						default:
							throw new Exception("BidOrAskWillFillAlert(): NYI direction[" + alert.Direction + "] for [" + alert + "]");
					}
					break;
			}
			return ret;
		}
		public override void OnAlertFilledCallback(Alert alertFilled) {
			if (alertFilled.IsExitAlert) return;
			Position position = alertFilled.PositionAffected;
		}
		public void AlertKillPending(Alert alert) {
			if (this.Backtester.IsBacktestingNow) {
				this.MarketSimStreaming.SimulateAlertKillPending(alert);
			} else {
				this.MarketRealStreaming.AlertKillPending(alert);
			}
		}
		private bool checkPositionCanBeClosed(Alert alert, string msig, bool checkPositionOpenNow = true) {
			if (alert.PositionAffected == null) {
				string msg = "can't close PositionAffected and remove Position from PositionsOpenNow"
					+ ": alert.PositionAffected=null for alert [" + alert + "]";
				//throw new Exception(msig + msg);
				this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
				return false;
			}
			if (alert.IsExitAlert) {
				string msg = "Sorry I don't serve alerts.IsExitAlert=true, only .IsEntryAlert's: alert [" + alert + "]";
				//throw new Exception(msig + msg);
				this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
				return false;
			}
			if (checkPositionOpenNow == true) {
				bool shouldRemove = this.ExecutionDataSnapshot.HasPositionOpenNow(alert.PositionAffected);

				if (alert.FilledBarIndex > -1) {
					if (shouldRemove) {
						int a = 1;
					}
					string msg = "CHECK_POSITION_OPEN_NOW Sorry I serve only BarRelnoFilled==-1"
						+ " otherwize alert.FillPositionAffectedEntryOrExitRespectively() with throw: alert [" + alert + "]";
					this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
					return false;
				}
				if (alert.PositionAffected.ExitFilledBarIndex > -1) {
					if (shouldRemove) {
						int a = 1;
					}
					string msg = "CHECK_POSITION_OPEN_NOW Sorry I serve only alert.PositionAffected.ExitBar==-1"
						+ " otherwize PositionAffected.FillExitAlert() will throw: alert [" + alert + "]";
					this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
					return false;
				}
			} else {
				Bar barFill = (this.IsStreaming) ? alert.Bars.BarStreamingCloneReadonly : alert.Bars.BarStaticLast;
				if (alert.PositionAffected.EntryFilledBarIndex != -1) {
					string msg = "DUPE: can't do my job: alert.PositionAffected.EntryBar!=-1 for alert [" + alert + "]";
					//throw new Exception(msig + msg);
					this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
					//return;
				} else {
					string msg = "Forcibly closing at EntryBar=[" + barFill + "]";
					this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(alert.OrderFollowed, msig + msg);
				}

			}
			return true;
		}
		public void ClosePositionWithAlertClonedFromEntryBacktestEnded(Alert alert) {
			string msig = " ClosePositionWithAlertClonedFromEntryBacktestEnded():";
			this.RemovePendingExitAlert(alert, msig);
			bool checkPositionOpenNow = true;
			if (this.checkPositionCanBeClosed(alert, msig, checkPositionOpenNow) == false) return;
			if (alert.FilledBar == null) {
				string msg = "BACKTEST_ENDED_ALERT_UNFILLED strategy[" + this.Strategy.ToString() + "] alert[" + alert + "]";
				Assembler.PopupException(msg + msig);
				return;
			}
			//Alert alertExitClonedStub = alert.CloneToRefactor();
			//alertExitClonedStub.SignalName += " ClosePositionWithAlertClonedFromEntryBacktestEnded Forced";
			//alertExitClonedStub.Direction = MarketConverter.ExitDirectionFromLongShort(alert.PositionLongShortFromDirection);
			//// REFACTORED_POSITION_HAS_AN_ALERT_AFTER_ALERTS_CONSTRUCTOR we can exit by TP or SL - position doesn't have an ExitAlert assigned until Position.EntryAlert was filled!!!
			//alert.PositionAffected.ExitAlertAttach(alertExitClonedStub);
			alert.PositionAffected.FillExitWith(alert.FilledBar, alert.PriceScript, alert.Qty, 0, 0);
			//alertFilled.FillPositionAffectedEntryOrExitRespectively(barFill, barFillRelno, priceFill, qtyFill, slippageFill, commissionFill);

			bool absenseInPositionsOpenNowIsAnError = false;
			this.ExecutionDataSnapshot.MovePositionOpenToClosed(alert.PositionAffected, absenseInPositionsOpenNowIsAnError);
		}
		public void RemovePendingEntry(Alert alert) {
			string msig = "RemovePendingEntry(): ";

			//"Excuse me, what bar is it now?" I'm just guessing! does BrokerProvider knows to pass Bar here?...
			Bar barFill = (this.IsStreaming) ? alert.Bars.BarStreamingCloneReadonly : alert.Bars.BarStaticLast;
			alert.FillPositionAffectedEntryOrExitRespectively(barFill, barFill.ParentBarsIndex, barFill.Close, alert.Qty, 0, 0);
			alert.SignalName += " RemovePendingEntryAlertClosePosition Forced";
		}
		public void RemovePendingExitAlertPastDueClosePosition(Alert alert) {
			string msig = "RemovePendingEntryCloneToExitAlertClosePosition(): ";
			this.RemovePendingExitAlert(alert, msig);
			//bool checkPositionOpenNow = true;
			//if (this.checkPositionCanBeClosed(alert, msig, checkPositionOpenNow) == false) return;

			//"Excuse me, what bar is it now?" I'm just guessing! does BrokerProvider knows to pass Bar here?...
			Bar barFill = (this.IsStreaming) ? alert.Bars.BarStreamingCloneReadonly : alert.Bars.BarStaticLast;
			alert.FillPositionAffectedEntryOrExitRespectively(barFill, barFill.ParentBarsIndex, barFill.Close, alert.Qty, 0, 0);
			alert.SignalName += " RemovePendingExitAlertClosePosition Forced";
			// REFACTORED_POSITION_HAS_AN_ALERT_AFTER_ALERTS_CONSTRUCTOR we can exit by TP or SL - position doesn't have an ExitAlert assigned until Position.EntryAlert was filled!!!
			//alert.PositionAffected.ExitAlertAttach(alert);

			bool absenseInPositionsOpenNowIsAnError = true;
			this.ExecutionDataSnapshot.MovePositionOpenToClosed(alert.PositionAffected, absenseInPositionsOpenNowIsAnError);
		}
		public override void OnAlertKilledCallback(Alert alertKilled) {
			//Debugger.Break();
		}
		public void CallbackAlertKilledInvokeScript(Alert alert) {
			if (this.ExecutionDataSnapshot.AlertsPendingContains(alert) == false) {
				string msg = "Alert wasn't found in snap.AlertsPending";
				throw new Exception(msg);
			}
			bool removed = this.ExecutionDataSnapshot.AlertsPendingRemove(alert);
			alert.Strategy.Script.OnAlertKilledCallback(alert);
		}
		internal bool AnnihilateCounterpartyAlert(Alert alert) {
			if (alert.OrderFollowed == null) {
				string msg = "can't AnnihilateCounterparty: OrderFollowed=null for alert=[" + alert + "]";
				throw new Exception(msg);
				//this.executor.ThrowPopup(new Exception(msg));
			}
			if (alert.PositionAffected == null) {
				string msg = "can't AnnihilateCounterparty: PositionAffected=null for alert=[" + alert + "]";
				throw new Exception(msg);
				//this.executor.ThrowPopup(new Exception(msg));
			}
			if (alert.IsEntryAlert) {
				string msg = "can't AnnihilateCounterparty: alert.isEntryAlert for alert=[" + alert + "]";
				throw new Exception(msg);
				//this.executor.ThrowPopup(new Exception(msg));
			}

			OrderStateMessage newOrderState = null;
			if (alert.PositionAffected.ClosedByTakeProfitLogically) {	//copy from dispatcher (caller of a caller)
				string msg = "position ClosedByTakeProfit@" + alert.PriceScript + ", annihilating StopLoss";
				newOrderState = new OrderStateMessage(alert.OrderFollowed, OrderState.SLAnnihilated, msg);
			} else {
				string msg = "position ClosedByStopLoss@" + alert.PriceScript + ", annihilating TakeProfit";
				newOrderState = new OrderStateMessage(alert.OrderFollowed, OrderState.TPAnnihilated, msg);
			}
			executor.OrderProcessor.UpdateOrderStateNoPostProcess(alert.OrderFollowed, newOrderState);
			executor.OrderProcessor.KillOrderUsingKillerOrder(alert.OrderFollowed);

			//this.executor.RemovePendingExitAlert(alert, "MarketRealtime:AnnihilateCounterparty(): ");
			bool removed = this.executor.ExecutionDataSnapshot.AlertsPendingRemove(alert);
			return true;
		}
Exemplo n.º 26
0
		public virtual void OnAlertNotSubmittedCallback(Alert alertNotSubmitted, int barNotSubmittedRelno) {
		}
		public bool AlertKillPending(Alert alert) {
			throw new NotImplementedException();
		}
		void invokeScriptEvents(Alert alert) {
			if (this.Strategy.Script == null) return;
			try {
				this.Strategy.Script.OnAlertFilledCallback(alert);
			} catch (Exception e) {
				string msg = "fix your OnAlertFilledCallback() in script[" + this.Strategy.Script.StrategyName + "]"
					+ "; was invoked with alert[" + alert + "]";
				this.PopupException(msg, e);
			}
			if (alert.IsEntryAlert) {
				try {
					if (alert.PositionAffected.Prototype != null) {
						this.Strategy.Script.OnPositionOpenedPrototypeSlTpPlacedCallback(alert.PositionAffected);
					} else {
						this.Strategy.Script.OnPositionOpenedCallback(alert.PositionAffected);
					}
				} catch (Exception e) {
					string msg = "fix your ExecuteOnPositionOpened() in script[" + this.Strategy.Script.StrategyName + "]"
						+ "; was invoked with PositionAffected[" + alert.PositionAffected + "]";
					this.PopupException(msg, e);
				}
			} else {
				try {
					this.Strategy.Script.OnPositionClosedCallback(alert.PositionAffected);
				} catch (Exception e) {
					string msg = "fix your OnPositionClosedCallback() in script[" + this.Strategy.Script.StrategyName + "]"
						+ "; was invoked with PositionAffected[" + alert.PositionAffected + "]";
					this.PopupException(msg, e);
				}
			}
		}
		Quote modelQuoteThatCouldFillAlert(Alert alert) {
			string err;

			Quote quoteModel = new Quote();
			quoteModel.Source = "GENERATED_TO_FILL_" + alert.ToString();
			quoteModel.Size = alert.Qty;

			double priceScriptAligned = this.backtester.Executor.AlignAlertPriceToPriceLevel(alert.Bars, alert.PriceScript, true,
				alert.PositionLongShortFromDirection, alert.MarketLimitStop);

			Quote quotePrev = this.backtester.BacktestDataSource.BacktestStreamingProvider.StreamingDataSnapshot
				.LastQuoteGetForSymbol(alert.Symbol);

			switch (alert.MarketLimitStop) {
				case MarketLimitStop.Limit:
					switch (alert.Direction) {
						case Direction.Buy:
						case Direction.Cover:
							if (priceScriptAligned > quotePrev.Ask) {
								err = "INVALID_PRICESCRIPT_FOR_LIMIT_BUY_MUST_NOT_BE_ABOVE_CURRENT_ASK";
								return null;
							}
							this.backtester.BacktestDataSource.BacktestStreamingProvider.SpreadModeler
								.GenerateFillBidBasedOnAsk(quoteModel, priceScriptAligned);
							break;
						case Direction.Short:
						case Direction.Sell:
							if (priceScriptAligned < quotePrev.Bid) {
								err = "INVALID_PRICESCRIPT_FOR_LIMIT_SELL_MUST_NOT_BE_BELOW_CURRENT_BID";
								return null;
							}
							this.backtester.BacktestDataSource.BacktestStreamingProvider.SpreadModeler
								.GenerateFillAskBasedOnBid(quoteModel, priceScriptAligned);
							break;
						default:
							throw new Exception("ALERT_LIMIT_DIRECTION_UNKNOWN direction[" + alert.Direction + "] is not Buy/Cover/Short/Sell modelQuoteThatCouldFillAlert()");
					}
					break;
				case MarketLimitStop.Stop:
					switch (alert.Direction) {
						case Direction.Buy:
						case Direction.Cover:
							if (priceScriptAligned < quotePrev.Ask) {
								err = "INVALID_PRICESCRIPT_FOR_STOP_BUY_MUST_NOT_BE_BELOW_CURRENT_ASK";
								return null;
							}
							this.backtester.BacktestDataSource.BacktestStreamingProvider.SpreadModeler
								.GenerateFillBidBasedOnAsk(quoteModel, priceScriptAligned);
							break;
						case Direction.Short:
						case Direction.Sell:
							if (priceScriptAligned > quotePrev.Bid) {
								err = "INVALID_PRICESCRIPT_FOR_STOP_SELL_MUST_NOT_BE_ABOVE_CURRENT_BID";
								return null;
							}
							this.backtester.BacktestDataSource.BacktestStreamingProvider.SpreadModeler
								.GenerateFillAskBasedOnBid(quoteModel, priceScriptAligned);
							break;
						default:
							throw new Exception("ALERT_STOP_DIRECTION_UNKNOWN direction[" + alert.Direction + "] is not Buy/Cover/Short/Sell modelQuoteThatCouldFillAlert()");
					}
					break;
				case MarketLimitStop.Market:
					switch (alert.Direction) {
						case Direction.Buy:
						case Direction.Cover:
							quoteModel.Ask = quotePrev.Ask;
							this.backtester.BacktestDataSource.BacktestStreamingProvider.SpreadModeler
								.GenerateFillBidBasedOnAsk(quoteModel, quotePrev.Ask);
							break;
						case Direction.Short:
						case Direction.Sell:
							quoteModel.Bid = quotePrev.Bid;
							this.backtester.BacktestDataSource.BacktestStreamingProvider.SpreadModeler
								.GenerateFillAskBasedOnBid(quoteModel, quotePrev.Bid);
							break;
						default:
							throw new Exception("ALERT_MARKET_DIRECTION_UNKNOWN direction[" + alert.Direction + "] is not Buy/Cover/Short/Sell modelQuoteThatCouldFillAlert()");
					}
					break;
				case MarketLimitStop.StopLimit: // HACK one quote might satisfy SLactivation, the other one might fill it; time to introduce state of SL into Alert???
					string msg = "STOP_LIMIT_QUOTE_FILLING_GENERATION_REQUIRES_TWO_STEPS_NYI"
						+ "; pass SLActivation=0 to PositionPrototypeActivator so that it generates STOP instead of STOPLOSS which I can't generate yet";
					//Debugger.Break();
					break;
				case MarketLimitStop.AtClose:
				default:
					throw new Exception("ALERT_TYPE_UNKNOWN MarketLimitStop[" + alert.MarketLimitStop + "] is not Market/Limit/Stop modelQuoteThatCouldFillAlert()");
			}

			return quoteModel;
		}
Exemplo n.º 30
0
		public virtual void OnAlertKilledCallback(Alert alertKilled) {
		}