public void UpdateOrderStateAndPostProcess(Order order, OrderStateMessage newStateOmsg, double priceFill = 0, double qtyFill = 0) {
			string msig = "UpdateOrderStateAndPostProcess(): ";

			try {
				if (order.State == OrderState.Killed) {
					int a = 1;
					// crawl in debugger if I can find VictimOrder.Alert.Executor.Script.OnAlertKilledCallback
					//this.RemovePendingAlertsForVictimOrderMustBePostKill(order, msig);
				}

				if (order.VictimToBeKilled != null) {
					this.PostProcessKillerOrder(order, newStateOmsg);
					return;
				}
				if (order.KillerOrder != null) {
					this.PostProcessVictimOrder(order, newStateOmsg);
					return;
				}

				if (order.hasBrokerProvider("handleOrderStatusUpdate():") == false) {
					string msg = "most likely QuikTerminal.CallbackOrderStatus got something wrong...";
					Assembler.PopupException(msg);
					return;
				}


				if (newStateOmsg.State == OrderState.Rejected && order.State == OrderState.EmergencyCloseLimitReached) {
					string prePostErrorMsg = "BrokerProvider CALLBACK DUPE: Status[" + newStateOmsg.State + "] delivered for EmergencyCloseLimitReached "
						//+ "; skipping PostProcess for [" + order + "]"
						;
					this.AppendOrderMessageAndPropagateCheckThrowOrderNull(order, prePostErrorMsg);
					return;
				}
				if (newStateOmsg.State == OrderState.Rejected && order.InEmergencyState) {
					string prePostErrorMsg = "BrokerProvider CALLBACK DUPE: Status[" + newStateOmsg.State + "] delivered for"
						+ " order.inEmergencyState[" + order.State + "] "
						//+ "; skipping PostProcess for [" + order + "]"
						;
					this.AppendOrderMessageAndPropagateCheckThrowOrderNull(order, prePostErrorMsg);
					return;
				}

				OrderCallbackDupesChecker dupesChecker = order.Alert.DataSource.BrokerProvider.OrderCallbackDupesChecker;
				if (dupesChecker != null) {
					string why = dupesChecker.OrderCallbackDupeResonWhy(order, newStateOmsg, priceFill, qtyFill);
					if (string.IsNullOrEmpty(why) == false) {
						string msgChecker = "OrderCallbackDupeResonWhy[" + why + "]; skipping PostProcess for [" + order + "]";
						this.AppendOrderMessageAndPropagateCheckThrowOrderNull(order, msgChecker);
						return;
					}
				}

				if (newStateOmsg.State == OrderState.Filled) {
					int a = 1;
				}

				/*if (qtyFill != 0) {
					if (order.QtyFill == 0 || order.QtyFill == -999) {
						order.QtyFill = qtyFill;
					} else {
						if (order.QtyFill != qtyFill && order.QtyFill != -qtyFill) {
							string msg = "got qtyFill[" + qtyFill + "] while order.QtyFill=[" + order.QtyFill
								+ "]; skipping update; trying to figure out why Filled orders get ZERO price from QUIK";
							order.AppendMessage(msg);
						}
					}
				}*/
				if (priceFill != 0) {
					if (order.PriceFill == 0 || order.PriceFill == -999.99) {
						order.PriceFill = priceFill;
						order.QtyFill = qtyFill;
					} else {
						bool marketWasSubstituted = order.Alert.MarketLimitStop == MarketLimitStop.Limit
								&& order.Alert.Bars.SymbolInfo.MarketOrderAs == MarketOrderAs.MarketMinMaxSentToBroker;
						if (order.PriceFill != priceFill && marketWasSubstituted == false) {
							string msg = "got priceFill[" + priceFill + "] while order.PriceFill=[" + order.PriceFill + "]"
								+ "; weird for Order.Alert.MarketLimitStop=[" + order.Alert.MarketLimitStop + "]";
							order.AppendMessage(msg);
						}
					}
				}
				this.UpdateOrderStateNoPostProcess(order, newStateOmsg);
				this.PostProcessOrderState(order, priceFill, qtyFill);
			} catch (Exception e) {
				string msg = "trying to figure out why SL is not getting placed - we didn't reach PostProcess??";
				this.PopupException(new Exception(msg, e));
			}
		}
		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 void CancelReplaceOrder(Order orderToReplace, Order orderReplacement) {
			string msgVictim = "expecting callback on successful REPLACEMENT completion [" + orderReplacement + "]";
			OrderStateMessage newOrderStateVictim = new OrderStateMessage(orderToReplace, OrderState.KillPending, msgVictim);
			this.UpdateOrderStateAndPostProcess(orderToReplace, newOrderStateVictim);

			orderReplacement.State = OrderState.Submitted;
			orderReplacement.IsReplacement = true;
			this.DataSnapshot.OrderAddSynchronizedAndPropagate(orderReplacement);

			if (orderToReplace.hasBrokerProvider("CancelReplaceOrder(): ") == false) {
				string msg = "CRAZY #65";
				Assembler.PopupException(msg);
				return;
			}
			orderToReplace.Alert.DataSource.BrokerProvider.CancelReplace(orderToReplace, orderReplacement);

			this.DataSnapshot.SerializerLogrotateOrders.HasChangesToSave = true;
			this.DataSnapshot.UpdateActiveOrdersCountEvent();
		}
		public Order CreateKillerOrder(Order victimOrder) {
			string msig = "CreateKillerOrder(): ";
			if (victimOrder == null) {
				string msg = "victimOrder == null why did you call me?";
				Assembler.PopupException(msg);
				return null;
			}
			if (victimOrder.hasBrokerProvider(msig) == false) {
				string msg = "CRAZY #62";
				Assembler.PopupException(msg);
				return null;
			}
			//this.RemovePendingAlertsForVictimOrderMustBePostKill(victimOrder, msig);

			Order killerOrder = victimOrder.DeriveKillerOrder();
			DateTime serverTimeNow = victimOrder.Alert.Bars.MarketInfo.ConvertLocalTimeToServer(DateTime.Now);
			killerOrder.TimeCreatedBroker = serverTimeNow;
			this.DataSnapshot.OrderAddSynchronizedAndPropagate(killerOrder);
			this.EventDistributor.RaiseOrderReplacementOrKillerCreatedForVictim(victimOrder);
			this.DataSnapshot.SerializerLogrotateOrders.HasChangesToSave = true;
			this.DataSnapshot.UpdateActiveOrdersCountEvent();
			return killerOrder;
		}
		public Order CreateReplacementOrderInsteadOfRejected(Order rejectedOrderToReplace) {
			if (rejectedOrderToReplace == null) {
				Assembler.PopupException("order2replace=null why did you call me?");
				return null;
			}
			Order replacement = this.findReplacementOrderForRejectedOrder(rejectedOrderToReplace);
			if (replacement != null) {
				string msg = "Rejected[" + rejectedOrderToReplace + "] already has a replacement[" + replacement + "] with State[" + replacement.State + "]; ignored rejection duplicates from broker";
				this.OrderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(rejectedOrderToReplace, msg);
				return null;
			}
			//DateTime todayDate = DateTime.Now.Date;
			//if (order.ReplacedByGUID != "" && order.OriginalAlertDate.Date == todayDate) {
			//	string msg = "order[" + order.ToString() + "] was already replaced today by [" + order.ReplacedByGUID + "]; continuing generating new order";
			//	Assembler.PopupException(msg);
			//order.addMessage(new OrderMessage(msg));
			//return null;
			//}
			if (rejectedOrderToReplace.hasBrokerProvider("CreateReplacementOrderInsteadOfRejected(): ") == false) {
				return null;
			}
			Order replacementOrder = rejectedOrderToReplace.DeriveReplacementOrder();
			DateTime serverTimeNow = rejectedOrderToReplace.Alert.Bars.MarketInfo.ConvertLocalTimeToServer(DateTime.Now);
			replacementOrder.TimeCreatedBroker = serverTimeNow;
			this.OrderProcessor.DataSnapshot.OrderAddSynchronizedAndPropagate(replacementOrder);
			this.OrderProcessor.EventDistributor.RaiseOrderStateChanged(this, rejectedOrderToReplace);
			this.OrderProcessor.EventDistributor.RaiseOrderReplacementOrKillerCreatedForVictim(this, rejectedOrderToReplace);
			return replacementOrder;
		}
		public void SubmitReplacementOrderInsteadOfRejected(Order replacementOrder) {
			if (replacementOrder == null) {
				Assembler.PopupException("replacementOrder == null why did you call me?");
				return;
			}
			if (replacementOrder.hasBrokerProvider("PlaceReplacementOrderInsteadOfRejected(): ") == false) {
				return;
			}

			string msg = "Scheduling SubmitOrdersThreadEntry [" + replacementOrder.ToString() + "] slippageIndex["
				+ replacementOrder.SlippageIndex + "] through [" + replacementOrder.Alert.DataSource.BrokerProvider + "]";
			OrderStateMessage newOrderState = new OrderStateMessage(replacementOrder, OrderState.PreSubmit, msg);
			this.OrderProcessor.UpdateOrderStateAndPostProcess(replacementOrder, newOrderState);

			//this.BrokerProvider.SubmitOrdersThreadEntry(ordersFromAlerts);
			ThreadPool.QueueUserWorkItem(new WaitCallback(replacementOrder.Alert.DataSource.BrokerProvider.SubmitOrdersThreadEntry),
				new object[] { new List<Order>() { replacementOrder } });

			//this.orderProcessor.UpdateActiveOrdersCountEvent();
		}
		private Order createEmergencyCloseOrderInsteadOfRejected(Order rejectedOrderToReplace) {
			if (rejectedOrderToReplace == null) {
				Assembler.PopupException("rejectedOrderToReplace=null why did you call me?");
				return null;
			}
			Order emergencyReplacement = this.findEmergencyReplacementForRejectedOrder(rejectedOrderToReplace);
			if (emergencyReplacement != null) {
				string msg = "Rejected[" + rejectedOrderToReplace + "] already has a"
					+ " emergencyReplacement[" + emergencyReplacement + "] with State[" + emergencyReplacement.State + "];"
					+ " ignoring rejection duplicates";
				this.orderProcessor.AppendOrderMessageAndPropagateCheckThrowOrderNull(rejectedOrderToReplace, msg);
				return null;
			}
			if (rejectedOrderToReplace.hasBrokerProvider("CreateEmergencyCloseOrderInsteadOfRejected(): ") == false) {
				return null;
			}
			emergencyReplacement = rejectedOrderToReplace.DeriveReplacementOrder();
			// for a first emergencyReplacement, set slippage=0;
			if (string.IsNullOrEmpty(rejectedOrderToReplace.EmergencyReplacementForGUID)) emergencyReplacement.SlippageIndex = 0;
			rejectedOrderToReplace.EmergencyReplacedByGUID = emergencyReplacement.GUID;
			emergencyReplacement.EmergencyReplacementForGUID = rejectedOrderToReplace.GUID;
			emergencyReplacement.IsEmergencyClose = true;
			if (rejectedOrderToReplace.IsEmergencyClose) {
				emergencyReplacement.EmergencyCloseAttemptSerno = rejectedOrderToReplace.EmergencyCloseAttemptSerno + 1;
			} else {
				emergencyReplacement.EmergencyCloseAttemptSerno = 1;
			}
			DateTime serverTimeNow = rejectedOrderToReplace.Alert.Bars.MarketInfo.ConvertLocalTimeToServer(DateTime.Now);
			emergencyReplacement.TimeCreatedBroker = serverTimeNow;

			this.orderProcessor.DataSnapshot.OrderAddSynchronizedAndPropagate(emergencyReplacement);
			this.orderProcessor.EventDistributor.RaiseOrderStateChanged(this, rejectedOrderToReplace);
			this.orderProcessor.EventDistributor.RaiseOrderReplacementOrKillerCreatedForVictim(this, rejectedOrderToReplace);
	
			return emergencyReplacement;
		}