public void PlaceOnce(PositionPrototype proto) { if (proto.PriceEntry == 0) { string msg = "market orders can't be found in OrdersPending"; } if (this.checkPrototypeAlreadyPlaced(proto)) return; //this.checkThrowPlacingProtoMakesSense(proto); proto.checkTPOffsetThrowBeforeAbsorbing(proto.TakeProfitPositiveOffset); proto.checkSLOffsetsThrowBeforeAbsorbing(proto.StopLossNegativeOffset, proto.StopLossActivationNegativeOffset); //bool a = this.executor.BacktesterFacade.IsBacktestingNow; Position posWithAlert = executor.BuyOrShortAlertCreateRegister ( executor.Bars.BarStreaming, proto.PriceEntry, "protoEntry@" + proto.PriceEntry, MarketConverter.EntryDirectionFromLongShort(proto.LongShort), MarketConverter.EntryMarketLimitStopFromDirection( executor.Bars.BarStreamingCloneReadonly.Close, proto.PriceEntry, proto.LongShort) ); if (posWithAlert == null) { string msg = "man I don't understand this null; out-of-bar limit should still leave a pending Alert.PositionAffected"; throw new Exception(msg); } if (posWithAlert.Prototype != null) { string msg = "CLEANUP: I was trying to catch MoveStopLoss::if(proto.StopLossAlertForAnnihilation==null)" + " so I thought there is a new prototype assigned to a position," + " since we never put null directly proto.StopLossAlertForAnnihilation"; throw new Exception(msg); } posWithAlert.Prototype = proto; }
public void TakeProfitNewPositiveOffsetUpdateActivate(Position position, double newTakeProfitPositiveOffset) { PositionPrototype proto = position.Prototype; if (proto == null) { string msg = "TakeProfitNewPositiveOffsetUpdateActivate() can't update TakeProfit for a position.Prototype=null: position=[" + position + "]"; throw new Exception(msg); } this.checkThrowNewTakeProfitOffsetMakesSense(position, newTakeProfitPositiveOffset); //proto.checkOffsetsThrowBeforeAbsorbing(newTakeProfitPositiveOffset, proto.StopLossNegativeOffset, proto.StopLossActivationNegativeOffset); if (executor.Backtester.IsBacktestingNow) { // NOPE!!! I WANT ALL ALERTS TO STAY IN HISTORY!!! just move TP in Alert, change Prices immediately; no orderKill/newOrder for TakeProfit (Alerts don't have OrdersFollowed) // PositionPrototypeActivator.checkThrowNewPriceMakesSense() made sure Alert!=null // TP_WILL_BE_KILLED proto.TakeProfitAlertForAnnihilation.PriceScript = proto.OffsetToPrice(newTakeProfitPositiveOffset); proto.SetNewTakeProfitOffset(newTakeProfitPositiveOffset); // TODO: don't forget about backtesting and MarketSim (implement OppMover for offline) executor.MarketSimStreaming.SimulateTakeProfitMoved(proto.TakeProfitAlertForAnnihilation); } else { executor.DataSource.BrokerProvider.MoveTakeProfitOrderProcessorInvoker(proto, newTakeProfitPositiveOffset); } }
public Alert CreateTakeProfitFromPositionPrototype(Position position) { PositionPrototype proto = position.Prototype; if (proto.TakeProfitPositiveOffset == 0) { string msg = "What should Activator do with proto.StopLossNegativeOffset=0?"; throw new Exception(msg); } Alert alertTakeProfit = executor.SellOrCoverAlertCreateDontRegister( executor.Bars.BarStreaming, position, proto.PriceTakeProfit, "protoTakeProfitExit:" + proto.TakeProfitPositiveOffset + "@" + proto.PriceTakeProfit + " for " + position.EntrySignal, MarketConverter.ExitDirectionFromLongShort(position.Prototype.LongShort), MarketLimitStop.Limit); if (alertTakeProfit == null) { string msg = "alertTakeProfit should NOT be null"; throw new Exception(msg); } proto.TakeProfitAlertForAnnihilation = alertTakeProfit; return(alertTakeProfit); }
public override void OnPositionOpenedPrototypeSlTpPlacedCallback(Position positionOpenedProto) { PositionPrototype proto = positionOpenedProto.Prototype; if (proto == null) { return; } double currentStopLossNegativeOffset = proto.StopLossNegativeOffset; double newStopLossNegativeOffset = currentStopLossNegativeOffset - 20; //string msg = base.Executor.PositionPrototypeActivator.ReasonWhyNewStopLossOffsetDoesntMakeSense(positionOpenedProto, newStopLossNegativeOffset); //if (String.IsNullOrEmpty(msg)) { base.Executor.PositionPrototypeActivator.StopLossNewNegativeOffsetUpdateActivate(positionOpenedProto, newStopLossNegativeOffset); //} else { // base.Executor.PopupException(new Exception("WONT_UPDATE_STOPLOSS: " + msg)); //} double newTakeProfitPositiveOffset = proto.TakeProfitPositiveOffset + 50; //msg = base.Executor.PositionPrototypeActivator.ReasonWhyNewTakeProfitOffsetDoesntMakeSense(positionOpenedProto, newTakeProfitPositiveOffset); //if (String.IsNullOrEmpty(msg)) { base.Executor.PositionPrototypeActivator.TakeProfitNewPositiveOffsetUpdateActivate(positionOpenedProto, newTakeProfitPositiveOffset); //} else { // base.Executor.PopupException(new Exception("WONT_UPDATE_TAKEPROFIT: " + msg)); //} }
private void placePrototypeOncePositionClosed(Bar bar) { bool isBacktesting = this.Executor.Backtester.IsBacktestingNow; //WHATS_THE_DIFFERENCE? if (isBacktesting) return; if (bar.ParentBarsIndex == 138) { //Debugger.Break(); } if (base.HasPositionsOpenNow) { return; } if (base.HasAlertsPending) { // only kill pending entries, but leave activated SL & TP for an open position UNTOUCHED !!!! ExecutionDataSnapshot snap = this.Executor.ExecutionDataSnapshot; List <Alert> pendings = snap.AlertsPendingSafeCopy; if (pendings.Count > 0) { string msg = pendings.Count + " last AlertsPending[" + snap.AlertsPending[pendings.Count - 1] + "]"; //PrintDebug(msg); foreach (Alert alert in pendings) { int wasntFilledDuringPastNbars = bar.ParentBarsIndex - alert.PlacedBarIndex; if (wasntFilledDuringPastNbars >= 30) { //if (alert.PositionAffected.Prototype != null) {} //base.Executor.CallbackAlertKilledInvokeScript(alert); base.AlertKillPending(alert); } } } return; } double protoPlacementOffsetPct = 1; double TPpct = 2; double SLpct = -1; double SLApct = -0.8; double protoPlacement = bar.Close + bar.Close * protoPlacementOffsetPct / 100; double TP = bar.Close * TPpct / 100; double SL = bar.Close * SLpct / 100; double SLactivation = bar.Close * SLApct / 100; SLactivation = 0; // when SLactivation == 0 Prototype generates Stop alert instead of StopLoss PositionPrototype protoLong = new PositionPrototype(this.Bars.Symbol, PositionLongShort.Long, protoPlacement, TP, SL, SLactivation); PositionPrototype protoShort = new PositionPrototype(this.Bars.Symbol, PositionLongShort.Short, -protoPlacement, TP, SL, SLactivation); //PositionPrototype protoFixed = new PositionPrototype(this.Bars.Symbol, PositionLongShort.Long, 158000, +150.0, -50.0, -40.0); //PositionPrototype proto = barNewStaticArrived.Close < 158000 ? protoLong : protoShort; PositionPrototype proto = protoLong; base.Executor.PositionPrototypeActivator.PlaceOnce(proto); }
private bool checkPrototypeAlreadyPlaced(PositionPrototype proto) { foreach (Alert alert in executor.ExecutionDataSnapshot.AlertsPending) { Position pos = alert.PositionAffected; if (pos == null) continue; if (pos.Prototype == null) continue; if (pos.Prototype.IsIdenticalTo(proto)) return true; } return false; }
void checkThrowPlacingProtoMakesSense(PositionPrototype proto) { string msg = this.ReasonWhyPlacingProtoDoesntMakeSense(proto); if (String.IsNullOrEmpty(msg) == false) { throw new Exception(msg); } }
public string ReasonWhyNewTakeProfitOffsetDoesntMakeSense(Position position, double newTakeProfitPositiveOffset, bool internalCallee = false) { PositionPrototype proto = position.Prototype; if (position.Symbol != proto.Symbol) { string msg1 = "NotYetImplemented: your script changes TakeProfitOffset for a proto.Symbol[" + proto.Symbol + "]!=position.Symbol[" + position.Symbol + "]"; throw new Exception(msg1); } Direction dir = MarketConverter.EntryDirectionFromLongShort(proto.LongShort); if (position.EntryAlert.Direction != dir) { string msg1 = "NotYetImplemented: Crazy check here"; throw new Exception(msg1); } Quote quote = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetForSymbol(proto.Symbol); double priceBestBidAsk = executor.DataSource.StreamingProvider.StreamingDataSnapshot.BidOrAskFor(proto.Symbol, proto.LongShort); double newTakeProfitPrice = proto.OffsetToPrice(newTakeProfitPositiveOffset); bool willBeExecutedImmediately = false; string ident = "TakeProfit{old[" + proto.PriceTakeProfit + "]:new[" + newTakeProfitPrice + "]}"; string msg = ""; switch (dir) { case Direction.Buy: if (newTakeProfitPrice < priceBestBidAsk) { willBeExecutedImmediately = true; msg = "will be filled immediately: newLongTakeProfitPrice[" + newTakeProfitPrice + "] < Ask[" + priceBestBidAsk + "] " + ident + " //position[" + position + "]"; } break; case Direction.Short: if (newTakeProfitPrice > priceBestBidAsk) { willBeExecutedImmediately = true; msg = "will be filled immediately: newShortTakeProfitPrice[" + newTakeProfitPrice + "] > Bid[" + priceBestBidAsk + "] " + ident + " //position[" + position + "]"; } break; default: msg = "I refuse to change TakeProfit when position.EntryAlert.Direction=[" + position.EntryAlert.Direction + "] - must be Buy or Sell only!!!"; break; } if (internalCallee == true) { msg += " (Script is strongly recommented to check TP price first so we don't pass unexpected position closures to the Market)"; } return(msg); }
public void StopLossNewNegativeOffsetUpdateActivate(Position position, double newStopLossNegativeOffset) { string msig = " StopLossNewNegativeOffsetUpdateActivate(position[" + position + "], newStopLossNegativeOffset[" + newStopLossNegativeOffset + "])"; PositionPrototype proto = position.Prototype; if (proto == null) { string msg = "StopLossNewNegativeOffsetUpdateActivate() can't update StopLoss for a position.Prototype=null: position=[" + position + "]"; throw new Exception(msg); } this.checkThrowNewStopLossOffsetMakesSense(position, newStopLossNegativeOffset); double newActivationOffset = proto.CalcActivationOffsetForNewClosing(newStopLossNegativeOffset); switch (proto.StopLossAlertForAnnihilation.MarketLimitStop) { case MarketLimitStop.StopLimit: #region StopLimit are considered NYI in Backtester.QuoteGenerator; switched to Stops since they do SL job perfectly; //proto.checkOffsetsThrowBeforeAbsorbing(proto.TakeProfitPositiveOffset, newStopLossNegativeOffset, newActivationOffset); if (executor.Backtester.IsBacktestingNow) { // NOPE!!! I WANT ALL ALERTS TO STAY IN HISTORY!!! just move SL in Alert, change Prices immediately; no orderKill/newOrder for StopLoss (Alerts don't have OrdersFollowed) // PositionPrototypeActivator.checkThrowNewPriceMakesSense() made sure Alert!=null // SL_WILL_BE_KILLED proto.StopLossAlertForAnnihilation.PriceScript = proto.OffsetToPrice(newStopLossNegativeOffset); // SL_WILL_BE_KILLED proto.StopLossAlertForAnnihilation.PriceStopLimitActivation = proto.OffsetToPrice(newActivationOffset); proto.SetNewStopLossOffsets(newStopLossNegativeOffset, newActivationOffset); // TODO: don't forget about backtesting and MarketSim (implement OppMover for offline) executor.MarketSimStreaming.SimulateStopLossMoved(proto.StopLossAlertForAnnihilation); } else { executor.DataSource.BrokerProvider.MoveStopLossOrderProcessorInvoker(proto, newActivationOffset, newStopLossNegativeOffset); } break; #endregion case MarketLimitStop.Stop: if (executor.Backtester.IsBacktestingNow) { proto.SetNewStopLossOffsets(newStopLossNegativeOffset, 0); // TODO: don't forget about backtesting and MarketSim (implement OppMover for offline) executor.MarketSimStreaming.SimulateStopLossMoved(proto.StopLossAlertForAnnihilation); } else { executor.DataSource.BrokerProvider.MoveStopLossOrderProcessorInvoker(proto, 0, newStopLossNegativeOffset); } break; default: string msg = "UNSUPPORTED_STOP_LOSS_CANT_MOVE [" + proto.StopLossAlertForAnnihilation.MarketLimitStop + "] must be Stop or StopLimit(weak support now, almost NYI)"; throw new Exception(msg + msig); } }
public Alert CreateStopLossFromPositionPrototype(Position position) { //if (this.executor.checkPrototypeAlreadyPlaced(position)) return; PositionPrototype proto = position.Prototype; if (proto.StopLossNegativeOffset == 0) { string msg = "What should Activator do with proto.StopLossNegativeOffset=0?"; throw new Exception(msg); } if (proto.StopLossNegativeOffset == 0) { string msg = this.ReasonWhyNewStopLossOffsetDoesntMakeSense(position, proto.StopLossNegativeOffset); if (String.IsNullOrEmpty(msg) == false) { string msg2 = "What should Activator do with sense-less proto.StopLossNegativeOffset[" + proto.StopLossNegativeOffset + "], "; throw new Exception(msg2, new Exception(msg)); } } MarketLimitStop simpleStopIfActivationZero = (proto.StopLossActivationNegativeOffset == 0) ? MarketLimitStop.Stop : MarketLimitStop.StopLimit; Alert alertStopLoss = executor.SellOrCoverAlertCreateDontRegister( executor.Bars.BarStreaming, position, proto.PriceStopLoss, "protoStopLossExit:" + proto.StopLossActivationNegativeOffset + "@" + proto.StopLossNegativeOffset + " for " + position.EntrySignal, MarketConverter.ExitDirectionFromLongShort(proto.LongShort), simpleStopIfActivationZero); if (alertStopLoss == null) { string msg = "alertStopLoss should NOT be null"; throw new Exception(msg); } alertStopLoss.PriceStopLimitActivation = 0; if (proto.StopLossActivationNegativeOffset < 0) { alertStopLoss.PriceStopLimitActivation = proto.PriceStopLossActivation; } if (proto.StopLossAlertForAnnihilation != null && this.executor.Backtester.IsBacktestingNow == false) { string msg = "CLEANUP: I was trying to catch MoveStopLoss::if(proto.StopLossAlertForAnnihilation==null)" + " so I thought there is a new prototype assigned to a position," + " since we never put null directly proto.StopLossAlertForAnnihilation"; throw new Exception(msg); } proto.StopLossAlertForAnnihilation = alertStopLoss; return(alertStopLoss); }
private void placePrototypeOncePositionClosed(Bar bar) { bool isBacktesting = this.Executor.Backtester.IsBacktestingNow; //WHATS_THE_DIFFERENCE? if (isBacktesting) return; if (bar.ParentBarsIndex == 138) { //Debugger.Break(); } if (base.HasPositionsOpenNow) return; if (base.HasAlertsPending) { // only kill pending entries, but leave activated SL & TP for an open position UNTOUCHED !!!! ExecutionDataSnapshot snap = this.Executor.ExecutionDataSnapshot; List<Alert> pendings = snap.AlertsPendingSafeCopy; if (pendings.Count > 0) { string msg = pendings.Count + " last AlertsPending[" + snap.AlertsPending[pendings.Count - 1] + "]"; //PrintDebug(msg); foreach (Alert alert in pendings) { int wasntFilledDuringPastNbars = bar.ParentBarsIndex - alert.PlacedBarIndex; if (wasntFilledDuringPastNbars >= 30) { //if (alert.PositionAffected.Prototype != null) {} //base.Executor.CallbackAlertKilledInvokeScript(alert); base.AlertKillPending(alert); } } } return; } double protoPlacementOffsetPct = 1; double TPpct = 2; double SLpct = -1; double SLApct = -0.8; double protoPlacement = bar.Close + bar.Close * protoPlacementOffsetPct / 100; double TP = bar.Close * TPpct / 100; double SL = bar.Close * SLpct / 100; double SLactivation = bar.Close * SLApct / 100; SLactivation = 0; // when SLactivation == 0 Prototype generates Stop alert instead of StopLoss PositionPrototype protoLong = new PositionPrototype(this.Bars.Symbol, PositionLongShort.Long, protoPlacement, TP, SL, SLactivation); PositionPrototype protoShort = new PositionPrototype(this.Bars.Symbol, PositionLongShort.Short, -protoPlacement, TP, SL, SLactivation); //PositionPrototype protoFixed = new PositionPrototype(this.Bars.Symbol, PositionLongShort.Long, 158000, +150.0, -50.0, -40.0); //PositionPrototype proto = barNewStaticArrived.Close < 158000 ? protoLong : protoShort; PositionPrototype proto = protoLong; base.Executor.PositionPrototypeActivator.PlaceOnce(proto); }
public List <Alert> PositionPrototypeKillWhateverIsPending(PositionPrototype proto, string signalName) { List <Alert> alertsSubmittedToKill = new List <Alert>(); if (proto.StopLossAlertForAnnihilation != null) { this.AlertKillPending(proto.StopLossAlertForAnnihilation); alertsSubmittedToKill.Add(proto.StopLossAlertForAnnihilation); } if (proto.TakeProfitAlertForAnnihilation != null) { this.AlertKillPending(proto.TakeProfitAlertForAnnihilation); alertsSubmittedToKill.Add(proto.TakeProfitAlertForAnnihilation); } return(alertsSubmittedToKill); }
public string ReasonWhyPlacingProtoDoesntMakeSense(PositionPrototype proto, bool internalCallee = false) { double lastPrice = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetPriceForMarketOrder(proto.Symbol); Quote quote = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetForSymbol(proto.Symbol); double priceBestBidAsk = executor.DataSource.StreamingProvider.StreamingDataSnapshot.BidOrAskFor(proto.Symbol, proto.LongShort); bool willBeExecutedImmediately = false; MarketLimitStop planningEntryUsing = MarketConverter.EntryMarketLimitStopFromDirection( executor.Bars.BarStreamingCloneReadonly.Close, proto.PriceEntry, proto.LongShort); string msg = ""; Direction dir = MarketConverter.EntryDirectionFromLongShort(proto.LongShort); switch (dir) { case Direction.Buy: if (proto.PriceEntry > priceBestBidAsk) { willBeExecutedImmediately = true; msg = "proto.PriceEntry[" + proto.PriceEntry + "] > Bid[" + priceBestBidAsk + "]" + " your Alert.EntryPrice goes above current price" + " so the planningEntryUsing[" + planningEntryUsing + "] will be activated/filled immediately..." + " //proto[" + proto + "]"; } break; case Direction.Short: if (proto.PriceEntry < priceBestBidAsk) { willBeExecutedImmediately = true; msg = "proto.PriceEntry[" + proto.PriceEntry + "] < Ask[" + priceBestBidAsk + "]" + " your Alert.EntryPrice goes below current price" + " so the planningEntryUsing[" + planningEntryUsing + "] will be activated/filled immediately..." + " //proto[" + proto + "]"; } break; default: msg = "I refuse to PlaceOnce(proto) for.Direction=[" + dir + "] - must be Buy or Sell only!!!"; break; } if (internalCallee == true) { msg += " (Script is strongly recommented to check proto.EntryPrice first so we don't pass unexpected position entries to the Market)"; } return(msg); }
private bool checkPrototypeAlreadyPlaced(PositionPrototype proto) { foreach (Alert alert in executor.ExecutionDataSnapshot.AlertsPending) { Position pos = alert.PositionAffected; if (pos == null) { continue; } if (pos.Prototype == null) { continue; } if (pos.Prototype.IsIdenticalTo(proto)) { return(true); } } return(false); }
public void PlaceOnce(PositionPrototype proto) { if (proto.PriceEntry == 0) { string msg = "market orders can't be found in OrdersPending"; } if (this.checkPrototypeAlreadyPlaced(proto)) { return; } //this.checkThrowPlacingProtoMakesSense(proto); proto.checkTPOffsetThrowBeforeAbsorbing(proto.TakeProfitPositiveOffset); proto.checkSLOffsetsThrowBeforeAbsorbing(proto.StopLossNegativeOffset, proto.StopLossActivationNegativeOffset); //bool a = this.executor.BacktesterFacade.IsBacktestingNow; Position posWithAlert = executor.BuyOrShortAlertCreateRegister( executor.Bars.BarStreaming, proto.PriceEntry, "protoEntry@" + proto.PriceEntry, MarketConverter.EntryDirectionFromLongShort(proto.LongShort), MarketConverter.EntryMarketLimitStopFromDirection( executor.Bars.BarStreamingCloneReadonly.Close, proto.PriceEntry, proto.LongShort) ); if (posWithAlert == null) { string msg = "man I don't understand this null; out-of-bar limit should still leave a pending Alert.PositionAffected"; throw new Exception(msg); } if (posWithAlert.Prototype != null) { string msg = "CLEANUP: I was trying to catch MoveStopLoss::if(proto.StopLossAlertForAnnihilation==null)" + " so I thought there is a new prototype assigned to a position," + " since we never put null directly proto.StopLossAlertForAnnihilation"; throw new Exception(msg); } posWithAlert.Prototype = proto; }
public void MoveTakeProfitOrderProcessorInvoker(PositionPrototype proto, double newTakeProfitPositiveOffset) { // broker providers might put some additional order processing, // but they must call OrderProcessor.MoveStopLoss() or imitate similar mechanism this.OrderProcessor.MoveTakeProfit(proto, newTakeProfitPositiveOffset); }
public void MoveTakeProfitOrderProcessorInvoker(PositionPrototype proto, double newTakeProfitPositiveOffset) { // broker providers might put some additional order processing, // but they must call OrderProcessor.MoveStopLoss() or imitate similar mechanism this.OrderProcessor.MoveTakeProfit(proto, newTakeProfitPositiveOffset); }
public virtual void MoveStopLossOrderProcessorInvoker(PositionPrototype proto, double newActivationOffset, double newStopLossNegativeOffset) { // broker providers might put some additional order processing, // but they must call OrderProcessor.MoveStopLoss() or imitate similar mechanism this.OrderProcessor.MoveStopLoss(proto, newActivationOffset, newStopLossNegativeOffset); }
public void MoveTakeProfit(PositionPrototype proto, double newTakeProfitPositiveOffset) { if (proto.TakeProfitAlertForAnnihilation == null) { string msg = "I refuse to move TakeProfit order because proto.TakeProfitAlertForAnnihilation=null"; throw new Exception(msg); } if (proto.TakeProfitAlertForAnnihilation.OrderFollowed == null) { string msg = "I refuse to move TakeProfit order because proto.TakeProfitAlertForAnnihilation.OrderFollowed=null"; throw new Exception(msg); } Order order2killAndReplace = proto.TakeProfitAlertForAnnihilation.OrderFollowed; OrderState stateBeforeActiveAssummingSubmitting = order2killAndReplace.State; OrderState stateBeforeKilledAssumingActive = OrderState.Unknown; string msig = "MoveTakeProfit(" + proto.TakeProfitPositiveOffset + "=>" + newTakeProfitPositiveOffset + "): "; // 1. hook onKilled=>submitNew OrderPostProcessorStateHook takeProfitGotKilledHook = new OrderPostProcessorStateHook("TakeProfitGotKilledHook", order2killAndReplace, OrderState.Killed, delegate(Order takeProfitKilled, ReporterPokeUnit pokeUnit) { string msg = msig + "takeProfitGotKilledHook(): invoking OnTakeProfitKilledCreateNewTakeProfitAndAddToPokeUnit() " + " [" + stateBeforeKilledAssumingActive + "] => " + "[" + takeProfitKilled.State + "]"; takeProfitKilled.AppendMessage(msg); this.OnTakeProfitKilledCreateNewTakeProfitAndAddToPokeUnit(takeProfitKilled, newTakeProfitPositiveOffset, pokeUnit); } ); // 2. hook onActive=>kill OrderPostProcessorStateHook takeProfitReceivedActiveCallback = new OrderPostProcessorStateHook("TakeProfitReceivedActiveCallback", order2killAndReplace, OrderState.Active, delegate(Order takeProfitToBeKilled, ReporterPokeUnit pokeUnit) { string msg = msig + "takeProfitReceivedActiveCallback(): invoking KillOrderUsingKillerOrder() " + " [" + stateBeforeActiveAssummingSubmitting + "] => " + "[" + takeProfitToBeKilled.State + "]"; takeProfitToBeKilled.AppendMessage(msg); stateBeforeKilledAssumingActive = takeProfitToBeKilled.State; this.KillOrderUsingKillerOrder(order2killAndReplace); } ); this.OPPstatusCallbacks.AddStateChangedHook(takeProfitReceivedActiveCallback); this.OPPstatusCallbacks.AddStateChangedHook(takeProfitGotKilledHook); this.AppendOrderMessageAndPropagateCheckThrowOrderNull(proto.TakeProfitAlertForAnnihilation.OrderFollowed, msig + ": hooked takeProfitReceivedActiveCallback() and takeProfitGotKilledHook()"); }
public string ReasonWhyNewStopLossOffsetDoesntMakeSense(Position position, double newStopLossNegativeOffset, bool internalCallee = false) { PositionPrototype proto = position.Prototype; if (position.Symbol != proto.Symbol) { string msg1 = "NotYetImplemented: your script changes StopLossOffset for a proto.Symbol[" + proto.Symbol + "]!=position.Symbol[" + position.Symbol + "]"; throw new Exception(msg1); } Direction dir = MarketConverter.EntryDirectionFromLongShort(proto.LongShort); if (position.EntryAlert.Direction != dir) { string msg1 = "NotYetImplemented: Crazy check here"; throw new Exception(msg1); } string msg = ""; double priceBestBidAsk = executor.DataSource.StreamingProvider.StreamingDataSnapshot.BidOrAskFor(proto.Symbol, proto.LongShort); double newStopLossPrice = proto.OffsetToPrice(newStopLossNegativeOffset); switch (proto.StopLossAlertForAnnihilation.MarketLimitStop) { #region StopLimits are considered NYI; mess v1 implementation case MarketLimitStop.StopLimit: double newActivationOffset = proto.CalcActivationOffsetForNewClosing(newStopLossNegativeOffset); //double lastPrice = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetPriceForMarketOrder(proto.Symbol); //Quote quote = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetForSymbol(proto.Symbol); double newActivationPrice = proto.OffsetToPrice(newActivationOffset); bool willBeExecutedImmediately = false; string ident = "StopLoss{old[" + proto.PriceStopLoss + "]:new[" + newStopLossPrice + "]}" + " Activation{old[" + proto.PriceStopLossActivation + "]:new[" + newActivationPrice + "]}"; switch (dir) { case Direction.Buy: if (newActivationPrice > priceBestBidAsk) { willBeExecutedImmediately = true; msg = "newActivationPrice[" + newActivationPrice + "] > Bid[" + priceBestBidAsk + "] " + ident + " your SLactivation goes above current price so the StopLoss will be activated/filled immediately..." + " //position[" + position + "]"; } break; case Direction.Short: if (newActivationPrice < priceBestBidAsk) { willBeExecutedImmediately = true; msg = "newActivationPrice[" + newActivationPrice + "] < Ask[" + priceBestBidAsk + "] " + ident + " your SLactivation goes below current price so the StopLoss will be activated/filled immediately..." + " //position[" + position + "]"; } break; default: msg = "I refuse to change StopLoss when position.EntryAlert.Direction=[" + position.EntryAlert.Direction + "] - must be Buy or Short only!!!"; break; } break; #endregion case MarketLimitStop.Stop: string ident2 = "PureStopLoss{old[" + proto.PriceStopLoss + "]:new[" + newStopLossPrice + "]}"; switch (proto.StopLossAlertForAnnihilation.Direction) { case Direction.Sell: double ask = executor.DataSource.StreamingProvider.StreamingDataSnapshot.BestAskGetForMarketOrder(proto.Symbol); if (newStopLossPrice > ask) { msg = "NEW_STOP_PRICE_BELOW_ASK_WILL_BE_REJECTED_BY_MARKET" + " newStopLossPrice[" + newStopLossPrice + "] < Ask[" + ask + "] " + ident2 + " //position[" + position + "]"; } break; case Direction.Cover: double bid = executor.DataSource.StreamingProvider.StreamingDataSnapshot.BestBidGetForMarketOrder(proto.Symbol); if (newStopLossPrice > bid) { msg = "NEW_STOP_PRICE_ABOVE_BID_WILL_BE_REJECTED_BY_MARKET" + " newStopLossPrice[" + newStopLossPrice + "] > Bid[" + bid + "] " + ident2 + " //position[" + position + "]"; } break; default: msg = "PROTOTYPE_BASED_STOP_LOSS_MODIFICATION_REFUSED_MUSTBE_SELL_OR_COVER" + "; position.ExitA.Direction=[" + position.ExitAlert.Direction + "]"; break; } break; default: msg = "STOP_LOSS_ALERT_TYPE_NOT_SUPPORTED [" + proto.StopLossAlertForAnnihilation.MarketLimitStop + "]"; throw new Exception(msg); } if (internalCallee == true) { msg += " (Script is strongly recommented to check SL price first so we don't pass unexpected position closures to the Market)"; } return(msg); }
public string ReasonWhyPlacingProtoDoesntMakeSense(PositionPrototype proto, bool internalCallee = false) { double lastPrice = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetPriceForMarketOrder(proto.Symbol); Quote quote = executor.DataSource.StreamingProvider.StreamingDataSnapshot.LastQuoteGetForSymbol(proto.Symbol); double priceBestBidAsk = executor.DataSource.StreamingProvider.StreamingDataSnapshot.BidOrAskFor(proto.Symbol, proto.LongShort); bool willBeExecutedImmediately = false; MarketLimitStop planningEntryUsing = MarketConverter.EntryMarketLimitStopFromDirection( executor.Bars.BarStreamingCloneReadonly.Close, proto.PriceEntry, proto.LongShort); string msg = ""; Direction dir = MarketConverter.EntryDirectionFromLongShort(proto.LongShort); switch (dir) { case Direction.Buy: if (proto.PriceEntry > priceBestBidAsk) { willBeExecutedImmediately = true; msg = "proto.PriceEntry[" + proto.PriceEntry + "] > Bid[" + priceBestBidAsk + "]" + " your Alert.EntryPrice goes above current price" + " so the planningEntryUsing[" + planningEntryUsing + "] will be activated/filled immediately..." + " //proto[" + proto + "]"; } break; case Direction.Short: if (proto.PriceEntry < priceBestBidAsk) { willBeExecutedImmediately = true; msg = "proto.PriceEntry[" + proto.PriceEntry + "] < Ask[" + priceBestBidAsk + "]" + " your Alert.EntryPrice goes below current price" + " so the planningEntryUsing[" + planningEntryUsing + "] will be activated/filled immediately..." + " //proto[" + proto + "]"; } break; default: msg = "I refuse to PlaceOnce(proto) for.Direction=[" + dir + "] - must be Buy or Sell only!!!"; break; } if (internalCallee == true) { msg += " (Script is strongly recommented to check proto.EntryPrice first so we don't pass unexpected position entries to the Market)"; } return msg; }
void checkThrowPlacingProtoMakesSense(PositionPrototype proto) { string msg = this.ReasonWhyPlacingProtoDoesntMakeSense(proto); if (String.IsNullOrEmpty(msg) == false) throw new Exception(msg); }
public List<Alert> PositionPrototypeKillWhateverIsPending(PositionPrototype proto, string signalName) { List<Alert> alertsSubmittedToKill = new List<Alert>(); if (proto.StopLossAlertForAnnihilation != null) { this.AlertKillPending(proto.StopLossAlertForAnnihilation); alertsSubmittedToKill.Add(proto.StopLossAlertForAnnihilation); } if (proto.TakeProfitAlertForAnnihilation != null) { this.AlertKillPending(proto.TakeProfitAlertForAnnihilation); alertsSubmittedToKill.Add(proto.TakeProfitAlertForAnnihilation); } return alertsSubmittedToKill; }
public virtual void MoveStopLossOrderProcessorInvoker(PositionPrototype proto, double newActivationOffset, double newStopLossNegativeOffset) { // broker providers might put some additional order processing, // but they must call OrderProcessor.MoveStopLoss() or imitate similar mechanism this.OrderProcessor.MoveStopLoss(proto, newActivationOffset, newStopLossNegativeOffset); }