#include "sierrachart.h"
SCDLLName("Spreadsheet Formula Position Size")
/*==================================================================================*/
SCSFExport scsf_SpreadsheetFormulaModified(SCStudyInterfaceRef sc)
{
	auto& in_Enable			= sc.Input[0];
	auto& in_Formula		= sc.Input[1];
	auto& in_Bars			= sc.Input[2];
	auto& in_MinPosition	= sc.Input[3];
	auto& in_MaxPosition	= sc.Input[4];
	auto& in_UpdateMode		= sc.Input[5];

	auto& sg_CalcPosition	= sc.Subgraph[0];
	auto& sg_MinPosition	= sc.Subgraph[1];
	auto& sg_MaxPosition	= sc.Subgraph[2];

	if (sc.SetDefaults)
	{
		sc.GraphName = "Spreadsheet Formula Position Size";
		sc.GraphRegion = 1;
		sc.AutoLoop = 0;
		sc.ValueFormat = VALUEFORMAT_WHOLE_NUMBER;
		sc.ScaleRangeType = SCALE_AUTO;
		sc.DisplayStudyInputValues = 0;
		sc.GlobalDisplayStudySubgraphsNameAndValue = 0;
		sc.CalculationPrecedence = VERY_LOW_PREC_LEVEL;

		in_Enable.Name = "Enable";
		in_Enable.SetYesNo(1);

		in_Formula.Name = "Formula";
		in_Formula.SetString("");

		in_Bars.Name = "Number of Bars to Calculate";
		in_Bars.SetInt(2000);
		in_Bars.SetIntLimits(1, INT_MAX);

		in_MinPosition.Name = "Min. Position Size";
		in_MinPosition.SetInt(1);
		in_MinPosition.SetIntLimits(1, INT_MAX);

		in_MaxPosition.Name = "Max. Position Size";
		in_MaxPosition.SetInt(10);
		in_MaxPosition.SetIntLimits(1, INT_MAX);

		in_UpdateMode.Name = "Update Mode";
		in_UpdateMode.SetCustomInputStrings("Always;On Bar Close;On Bar Open");
		in_UpdateMode.SetCustomInputIndex(0);

		sg_CalcPosition.Name = "Calculated Position Size";
		sg_CalcPosition.DrawStyle = DRAWSTYLE_LINE;
		sg_CalcPosition.LineStyle = LINESTYLE_SOLID;
		sg_CalcPosition.LineWidth = 1;
		sg_CalcPosition.DrawZeros = 0;
		sg_CalcPosition.PrimaryColor = COLOR_LIME;
		sg_CalcPosition.LineLabel |= LL_DISPLAY_VALUE;

		sg_MinPosition.Name = "Min. Position Size";
		sg_MinPosition.DrawStyle = DRAWSTYLE_LINE;
		sg_MinPosition.LineStyle = LINESTYLE_SOLID;
		sg_MinPosition.LineWidth = 1;
		sg_MinPosition.DrawZeros = 0;
		sg_MinPosition.PrimaryColor = COLOR_RED;
		sg_MinPosition.LineLabel |= LL_DISPLAY_VALUE;

		sg_MaxPosition.Name = "Max. Position Size";
		sg_MaxPosition.DrawStyle = DRAWSTYLE_LINE;
		sg_MaxPosition.LineStyle = LINESTYLE_SOLID;
		sg_MaxPosition.LineWidth = 1;
		sg_MaxPosition.DrawZeros = 0;
		sg_MaxPosition.PrimaryColor = COLOR_RED;
		sg_MaxPosition.LineLabel |= LL_DISPLAY_VALUE;

		return;
	}

	auto& r_StartIndex = sc.GetPersistentIntFast(0);

	if (sc.UpdateStartIndex == 0
		&& sc.IsFullRecalculation)
		r_StartIndex = max(0, sc.ArraySize - 1 - in_Bars.GetInt());

	if (!in_Enable.GetYesNo())
		return;

	for (auto index = sc.UpdateStartIndex; index < sc.ArraySize; ++index)
	{
		sg_MinPosition[index] = static_cast<float>(in_MinPosition.GetInt());
		sg_MaxPosition[index] = static_cast<float>(in_MaxPosition.GetInt());
		
		if (index < r_StartIndex)
			continue;
		
		auto update{ false };

		switch (in_UpdateMode.GetIndex())
		{
		case 1: // On Bar Close
			update = sc.GetBarHasClosedStatus(index) == BHCS_BAR_HAS_CLOSED;
			break;
		case 2: // On Bar Open
			update = sc.IsFullRecalculation || sc.IsNewBar(index);
			break;
		default: // Always
			update = true;
			break;
		}

		if (!update)
			continue;

		auto formulaResult{ 0ll };

		if (index == r_StartIndex)
			formulaResult = sc.Round64(sc.EvaluateGivenAlertConditionFormulaAsDouble(index, 1, in_Formula.GetString()));
		else
			formulaResult = sc.Round64(sc.EvaluateGivenAlertConditionFormulaAsDouble(index, 0, ""));

		sg_CalcPosition[index] = static_cast<float>(formulaResult);

		const auto positionSize = max(in_MinPosition.GetInt(), min(in_MaxPosition.GetInt(), formulaResult));

		sc.TradeWindowOrderQuantity = static_cast<double>(positionSize);
	}
}

/*==================================================================================*/