
//
// Copyright (C) 2019, Order Flow Analytics Inc <www.orderflowanalytics.com>.
// OFA reserves the right to modify or overwrite this NinjaScript component with each release.
//
// By installing, using in whole or in part any sample code from Order Flow Analytics you agree to fully indemnify and hold harmless OrderFlowAnalytics, Inc 
// and its affiliates from and against any claims, losses, liabilities and expenses that may be incurred 
// as a result having downloaded and/or used any or all of the available code.
// Do thoroughly test any code & modifications for indicators and strategies in Replay Test mode

#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
using NinjaTrader.OFA;
#endregion

//This namespace holds Strategies in this folder and is required. Do not change it. 
namespace NinjaTrader.NinjaScript.Strategies
{
	public class OFASampleStrategyClusterCloseLogic : Strategy
	{
		private OFAIndicatorSTCORE OFAIndicatorSTCORE1;
		
		private bool breakevenset=false;

		protected override void OnStateChange()
		{
			if (State == State.SetDefaults)
			{
				Description									= @"Enter the description for your new custom Strategy here.";
				Name										= "OFASampleStrategyClusterCloseLogic";
				Calculate									= Calculate.OnBarClose;
				EntriesPerDirection							= 1;
				EntryHandling								= EntryHandling.AllEntries;
				IsExitOnSessionCloseStrategy				= true;
				ExitOnSessionCloseSeconds					= 30;
				IsFillLimitOnTouch							= false;
				MaximumBarsLookBack							= MaximumBarsLookBack.TwoHundredFiftySix;
				OrderFillResolution							= OrderFillResolution.Standard;
				Slippage									= 0;
				StartBehavior								= StartBehavior.WaitUntilFlat;
				TimeInForce									= TimeInForce.Gtc;
				TraceOrders									= false;
				RealtimeErrorHandling						= RealtimeErrorHandling.StopCancelClose;
				StopTargetHandling							= StopTargetHandling.PerEntryExecution;
				BarsRequiredToTrade							= 20;
				StopLossTicks				   = 10;
				ProfitTargetTicks			   = 20;
				StopBreakEvenTicks			   = 8;
				
				// Disable this property for performance gains in Strategy Analyzer optimizations
				// See the Help Guide for additional information
				IsInstantiatedOnEachOptimizationIteration	= true;
			}
			else if (State == State.Configure)
			{
				// Use here only if your stop loss price/offset is static
				// otherwise use in onbarupdate - to enable dynamically changing the stop loss price while in an open position
				// if using this in onbarupdate - make sure you reset the stop loss price/offset when the strategy is flat - important or the last price/offset will be used to generate
				// the stop loss order on your next open position
				
				SetStopLoss(CalculationMode.Ticks,StopLossTicks);
				SetProfitTarget(CalculationMode.Ticks,ProfitTargetTicks);
			}
			else if (State == State.DataLoaded)
			{				
				OFAIndicatorSTCORE1				= OFAIndicatorSTCORE(Close, 30, 70, OFAColorLogic.POC);
			}
		}

		protected override void OnBarUpdate()
		{
			if (BarsInProgress != 0) 
				return;

			// Ensure you have enough bars on the chart if you are referencing prior bars in your logic below !
			
			if (CurrentBars[0] < 5)
				return;		
			
			// Resets the stop loss to the original value when all positions are closed
			if (Position.MarketPosition == MarketPosition.Flat)
			{
				SetStopLoss(CalculationMode.Ticks, StopLossTicks);
				breakevenset=false;
			}
			
			// If a long position is open, allow for stop loss modification to breakeven
			else if (Position.MarketPosition == MarketPosition.Long)
			{
				
				// Once the price is greater than entry price+StopBreakEvenTicks set as a parameter, set stop loss to breakeven
				
				if ((Close[0] > Position.AveragePrice + StopBreakEvenTicks * TickSize) && (!breakevenset))
				{
					SetStopLoss(CalculationMode.Price, Position.AveragePrice);
					breakevenset = true;
					
				}
			}
			else if (Position.MarketPosition == MarketPosition.Short)
			{
				
				// Once the price is greater than entry price+StopBreakEvenTicks set as a parameter, set stop loss to breakeven
				
				if ((Close[0] < Position.AveragePrice - StopBreakEvenTicks * TickSize) && (!breakevenset))
				{
					SetStopLoss(CalculationMode.Price, Position.AveragePrice);
					breakevenset = true;
					
				}
			}
			
			// Wait for the classification cluster logic pattern of current bar to close before
			// testing if logic condition is true and submit order
			
			
			if ((OFAIndicatorSTCORE1.OFABarDirectionValue[0] == 1)
				
				 // Use the condition group feature in strategy builder to group your logic into meaningful chunks that are readable and thus easier to locate logic errors when testing TIP
				
				 // Condition group 1
				 && ((OFAIndicatorSTCORE1.OFABarClassification[0] == 2)
				 || (OFAIndicatorSTCORE1.OFABarClassification[0] == 1))
				
				 
				 // Condition group 2
				 // a line provided here if you want to include a 3rd bar lookback condition
				
				 && ((OFAIndicatorSTCORE1.OFABarDirectionValue[1] == -1)
				 || (OFAIndicatorSTCORE1.OFABarDirectionValue[1] == -1)
				 || (OFAIndicatorSTCORE1.OFABarDirectionValue[2] == -1))
				
				 // Can modify the next group for how many prior POCS to close above - adjust the strength of pivot looking for
				 // modify the 2nd close if > or >= compare in testing
				 // a line provided here if you want to include a 3rd bar lookback comparison condition - change one of the [2]'s to a [3]
				
				 && (OFAIndicatorSTCORE1.OFABarClose[0] > OFAIndicatorSTCORE1.OFAPocPrice[1])
				 && (OFAIndicatorSTCORE1.OFABarClose[0] >= OFAIndicatorSTCORE1.OFAPocPrice[2])
				 && (OFAIndicatorSTCORE1.OFABarClose[0] >= OFAIndicatorSTCORE1.OFAPocPrice[2])
				 )
			{
				
				Draw.Region(this, "tag1"+CurrentBar, 1, 0, High, Low, null, _UpBrush, 40);
				
				// Enter Long Limit at the POC price of the Bar just closed.
				
				EnterLongLimit(OFAIndicatorSTCORE1.OFAPocPrice[0]+(1*TickSize));
				
				
			}
			else if ((OFAIndicatorSTCORE1.OFABarDirectionValue[0] == -1)
				
				  // Condition group 1
				 && ((OFAIndicatorSTCORE1.OFABarClassification[0] == 2)
				 || (OFAIndicatorSTCORE1.OFABarClassification[0] == -1))
				
				
				 // Condition group 2
				 // a line provided here if you want to include a 3rd bar lookback condition
				
				 && ((OFAIndicatorSTCORE1.OFABarDirectionValue[1] == 1)
				 || (OFAIndicatorSTCORE1.OFABarDirectionValue[1] == 1)
				 || (OFAIndicatorSTCORE1.OFABarDirectionValue[2] == 1))
				
				// Can modify the next group for how many prior POCS to close below - adjust the strength of pivot looking for
				// modify the 2nd close if < or <= compare in testing
				
				// a line provided here if you want to include a 3rd bar lookback comparison condition - change one of the [2]'s to a [3]
				
				 && (OFAIndicatorSTCORE1.OFABarClose[0] < OFAIndicatorSTCORE1.OFAPocPrice[1])
				 && (OFAIndicatorSTCORE1.OFABarClose[0] <= OFAIndicatorSTCORE1.OFAPocPrice[2])
				 && (OFAIndicatorSTCORE1.OFABarClose[0] <= OFAIndicatorSTCORE1.OFAPocPrice[2])
				)
				
			{
				
				Draw.Region(this, "tag2"+CurrentBar, 1, 0, High, Low, null, _DnBrush, 40);
				
				// Enter Short Limit at the POC price of the Bar just closed.
				
				EnterShortLimit(OFAIndicatorSTCORE1.OFAPocPrice[0]-(1*TickSize));
				
			}
			
			
		}
		
		#region Properties
		[Range(1, int.MaxValue)]
		[NinjaScriptProperty]
		[Display(Name="StopLossTicks", Description="Numbers of ticks away from entry price for the Stop Loss order", Order=1, GroupName="Parameters")]
		public int StopLossTicks
		{ get; set; }

		[Range(1, int.MaxValue)]
		[NinjaScriptProperty]
		[Display(Name="ProfitTargetTicks", Description="Number of ticks away from entry price for the Profit Target order", Order=2, GroupName="Parameters")]
		public int ProfitTargetTicks
		{ get; set; }
		
		[Range(1, int.MaxValue)]
		[NinjaScriptProperty]
		[Display(Name="StopBreakEvenTicks", Description="Number of ticks profit to move stop to breakeven", Order=3, GroupName="Parameters")]
		public int StopBreakEvenTicks
		{ get; set; }
		
		// Up Color 
        private System.Windows.Media.Brush _UpBrush = Brushes.Lime;
        [XmlIgnore]
        [Display(Name = "Up Rule Color", GroupName = "Rule Parameters", Order = 5)]
        public System.Windows.Media.Brush UpRuleBrush
        {
            get { return _UpBrush; }
            set { _UpBrush = value; }
        }

        [Browsable(false)]
        public string UpBrushSerialize
        {
            get { return Serialize.BrushToString(_UpBrush); }
            set { _UpBrush = Serialize.StringToBrush(value); }
        }
		
		private System.Windows.Media.Brush _DnBrush = Brushes.Red;
        [XmlIgnore]
        [Display(Name = "Dn Rule Color", GroupName = "Rule Parameters", Order = 6)]
        public System.Windows.Media.Brush DnRuleBrush
        {
            get { return _DnBrush; }
            set { _DnBrush = value; }
        }

        [Browsable(false)]
        public string DnBrushSerialize
        {
            get { return Serialize.BrushToString(_DnBrush); }
            set { _DnBrush = Serialize.StringToBrush(value); }
        }
		#endregion
	}
}
