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 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 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 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 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); }
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); }
public Market GetMarketInformation(long marketId) { GetMarketInformationRequest request = new GetMarketInformationRequest(); request.MarketIds = new long[] { marketId }; GetMarketInformationResponse response = _proxy.GetMarketInformation(request); if (response.ReturnStatus.Code != 0) { throw new Exception(response.ReturnStatus.Description); } // Since only receive one marketId as param then can assume will always be just one market returned. Market[] marketToReturn = MarketConverter.ConvertMarketTypeCollection(response.Markets); return(marketToReturn[0]); }
public Market GetPrices(long marketId) { GetPricesRequest request = new GetPricesRequest(); request.MarketIds = new long[] { marketId }; request.NumberAgainstPricesRequired = 3; request.NumberForPricesRequired = 3; GetPricesResponse response = _proxy.GetPrices(request); if (response.ReturnStatus.Code != 0) { throw new Exception(response.ReturnStatus.Description); } // Since only receive one marketId as param then can assume will always be just one market returned. Market[] marketToReturn = MarketConverter.ConvertMarketTypeWithPricesCollection(response.MarketPrices); return(marketToReturn[0]); }
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 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); }