/// <summary>Called when new data is received</summary> public override void Step() { base.Step(); if (Instrument.NewCandle) { Debugging.LogInstrument(); Debugging.BreakOnPointOfInterest(); } // Run the position manager if (PosMgr != null) { PosMgr.Step(); } // If there is a pending order, wait for it to trigger or expire var pending = PendingOrders.FirstOrDefault(); if (pending != null) { // If the price is more than the SL/TP distance from the EP then give up on the order var dist = Math.Abs(Instrument.LatestPrice.Mid - pending.TargetPrice); if (dist > Math.Abs(pending.TakeProfitRel()) || dist > Math.Abs(pending.StopLossRel())) { Broker.CancelPendingOrder(pending); } else { return; } } // Look for an existing trade for this strategy. var position = Positions.FirstOrDefault(); if (position == null) { // Look for indicators to say "enter" and which direction. QuoteCurrency?ep, tp; var tt = Instrument.FindTradeEntry(out ep, out tp); if (tt == null) { return; } // Create a trade in the suggested direction var trade = new Trade(Instrument, tt.Value, Label, ep: ep, tp: tp); trade.Expiration = (Bot.UtcNow + Instrument.TimeFrame.ToTimeSpan(10)).DateTime; if (trade.RtR < 0.2) { return; } // Create a pending order Broker.CreatePendingOrder(trade); //Broker.CreateOrder(trade); } }
/// <summary>Called when new data is received</summary> public override void Step() { base.Step(); // Find the position associated with this strategy Position = FindLivePosition(Position); switch (State) { case EState.FindEntryTrigger: #region { // In this state we're waiting for an entry trigger. Debug.Assert(Position == null); // Do nothing unless the conditions are right if (SuitabilityScore < 0.5) { return; } if (Instrument.NewCandle) { Dump(); } // Always trade with the trend var sign = Math.Sign(Trend); var tt = sign > 0 ? TradeType.Buy : TradeType.Sell; // Look for a candle pattern that indicates entry int forecast_direction; QuoteCurrency target_entry; if (!Instrument.IsCandlePattern(0, out forecast_direction, out target_entry) || forecast_direction != sign) { return; } // Switch to the 'EnterOnPullBack' state State = EState.EnterOnPullBack; TargetEntry = new TargetEntryData(target_entry, tt); Dump(); break; } #endregion case EState.EnterOnPullBack: #region { if (Instrument.NewCandle) { Dump(); } // In this state we're waiting for the price to pull back // to the target entry. Check this on every tick. var tt = TargetEntry.TT; var cp = Instrument.CurrentPrice(tt.Sign()); if (Misc.Sign(cp - TargetEntry.Price) != tt.Sign()) { var trade = new Trade(Bot, Instrument, tt, Label); Position = Bot.Broker.CreateOrder(trade); Dump(); } break; } #endregion case EState.ManagePosition: #region { if (Instrument.NewCandle) { Dump(); } // Manage a trade position PositionManager.Step(); break; } #endregion } }