#include "sierrachart.h"
SCSFExport CustomChartBarBuildingFunction(SCCustomChartBarInterfaceRef ChartBarInterface)
{
ChartBarInterface.StartNewBarFlag = 0;
if (ChartBarInterface.IsDeterminingIfShouldStartNewBar)
{
if (ChartBarInterface.BarHasBeenCutAtStartOfSession)
{
}
SCInputRef VolumeInput = ChartBarInterface.GetInput(0);
const uint64_t CurrentBarVolume = static_cast<uint64_t>(ChartBarInterface.GetChartBarValue(SC_VOLUME, ChartBarInterface.CurrentBarIndex));
if (CurrentBarVolume >= VolumeInput.GetInt())
{
ChartBarInterface.StartNewBarFlag = 1;
return;
}
}
else if (ChartBarInterface.IsFinalProcessingAfterNewOrCurrentBar)
{
if (ChartBarInterface.IsFirstBarOfChart)
{
}
if (ChartBarInterface.IsNewChartBar)
{
if (ChartBarInterface.CurrentBarIndex >= 1)
{
ChartBarInterface.GetChartBarValue(SC_LAST, ChartBarInterface.CurrentBarIndex - 1) = ChartBarInterface.GetChartBarValue(SC_HIGH, ChartBarInterface.CurrentBarIndex - 1);
}
}
return;
}
else if (ChartBarInterface.IsInsertFileRecordsProcessing)
{
return;
}
}
SCSFExport scsf_CustomChartBarsExample(SCStudyInterfaceRef sc)
{
SCInputRef Input_VolumePerBar = sc.Input[0];
if (sc.SetDefaults)
{
sc.GraphRegion = 0;
sc.GraphName = "Custom Chart Bars Example";
sc.UsesCustomChartBarFunction = 1;
sc.fp_ACSCustomChartBarFunction = CustomChartBarBuildingFunction;
sc.AutoLoop = 0;
Input_VolumePerBar.Name = "Volume Per Bar";
Input_VolumePerBar.SetInt(1000);
Input_VolumePerBar.SetIntLimits(1, INT_MAX);
return;
}
int& r_ChartDataReloadedFlag = sc.GetPersistentInt(CUSTOM_CHART_BAR_RELOAD_FLAG_KEY);
if (r_ChartDataReloadedFlag == 0)
{
sc.FlagToReloadChartData = true;
r_ChartDataReloadedFlag = 1;
}
const int VolumePerBar = Input_VolumePerBar.GetInt();
int& r_PriorVolumePerBar = sc.GetPersistentInt(1);
if (r_PriorVolumePerBar != 0 && r_PriorVolumePerBar != VolumePerBar)
sc.FlagToReloadChartData = true;
r_PriorVolumePerBar = VolumePerBar;
if (sc.IsFullRecalculation)
sc.GraphName.Format("Custom Chart Bar Volume = %d", VolumePerBar);
}
int GetRangeBarDirection(SCCustomChartBarInterfaceRef ChartBarInterface, int BarIndex)
{
int LastIndex = BarIndex;
int NumIterations = 0;
while (NumIterations < 10)
{
float& BarOpen = ChartBarInterface.GetChartBarValue(SC_OPEN, LastIndex);
float& BarLast = ChartBarInterface.GetChartBarValue(SC_LAST, LastIndex);
if (BarLast < BarOpen)
{
return -1;
}
if (BarLast > BarOpen)
{
return 1;
}
if (LastIndex < 1)
break;
float& PriorBarLast = ChartBarInterface.GetChartBarValue(SC_LAST, LastIndex - 1);
if (BarLast < PriorBarLast)
{
return -1;
}
if (BarLast > PriorBarLast)
{
return 1;
}
--LastIndex;
++NumIterations;
}
return 1;
}
SCSFExport CustomRangeChartBarBuildingFunction(SCCustomChartBarInterfaceRef ChartBarInterface)
{
ChartBarInterface.StartNewBarFlag = 0;
SCInputRef RangeInput = ChartBarInterface.GetInput(0);
float NeededRangeAsFloat = RangeInput.GetInt() * ChartBarInterface.TickSize;
if (ChartBarInterface.IsDeterminingIfShouldStartNewBar)
{
if (ChartBarInterface.BarHasBeenCutAtStartOfSession)
{
}
int Direction = GetRangeBarDirection(ChartBarInterface, ChartBarInterface.CurrentBarIndex);
float BarHigh = ChartBarInterface.GetChartBarValue(SC_HIGH, ChartBarInterface.CurrentBarIndex);
float BarLow = ChartBarInterface.GetChartBarValue(SC_LOW, ChartBarInterface.CurrentBarIndex);
if (Direction == 1)
{
BarHigh = max(BarHigh, ChartBarInterface.NewFileRecord.GetHigh());
float Range = BarHigh - BarLow;
if (Range > NeededRangeAsFloat)
ChartBarInterface.StartNewBarFlag = 1;
}
else if (Direction == -1)
{
BarLow = min(BarLow, ChartBarInterface.NewFileRecord.GetLow());
float Range = BarHigh - BarLow;
if (Range > NeededRangeAsFloat)
ChartBarInterface.StartNewBarFlag = 1;
}
}
else if (ChartBarInterface.IsFinalProcessingAfterNewOrCurrentBar)
{
if (ChartBarInterface.IsNewChartBar && ChartBarInterface.CurrentBarIndex > 0)
{
int Direction = GetRangeBarDirection(ChartBarInterface, ChartBarInterface.CurrentBarIndex - 1);
if (Direction == 1)
{
float& r_BarHigh = ChartBarInterface.GetChartBarValue(SC_HIGH, ChartBarInterface.CurrentBarIndex - 1);
float& r_BarLast = ChartBarInterface.GetChartBarValue(SC_LAST, ChartBarInterface.CurrentBarIndex - 1);
r_BarLast = r_BarHigh;
}
else if (Direction == -1)
{
float& r_BarLow = ChartBarInterface.GetChartBarValue(SC_LOW, ChartBarInterface.CurrentBarIndex - 1);
float& r_BarLast = ChartBarInterface.GetChartBarValue(SC_LAST, ChartBarInterface.CurrentBarIndex - 1);
r_BarLast = r_BarLow;
}
}
}
else if (ChartBarInterface.IsInsertFileRecordsProcessing)
{
int Direction = GetRangeBarDirection(ChartBarInterface, ChartBarInterface.CurrentBarIndex);
float& r_BarHigh = ChartBarInterface.GetChartBarValue(SC_HIGH, ChartBarInterface.CurrentBarIndex);
float& r_BarLow = ChartBarInterface.GetChartBarValue(SC_LOW, ChartBarInterface.CurrentBarIndex);
float& r_BarOpen = ChartBarInterface.GetChartBarValue(SC_OPEN, ChartBarInterface.CurrentBarIndex);
float& r_BarLast = ChartBarInterface.GetChartBarValue(SC_LAST, ChartBarInterface.CurrentBarIndex);
float Range = r_BarHigh - r_BarLow;
if (Range <= NeededRangeAsFloat)
{
ChartBarInterface.InsertNewRecord = 0;
return;
}
ChartBarInterface.InsertNewRecord = 1;
if (Direction == 1)
{
ChartBarInterface.NewRecordToInsert.High = r_BarHigh;
ChartBarInterface.NewRecordToInsert.Close = r_BarLast;
float NewHigh = r_BarLow + NeededRangeAsFloat;
r_BarHigh = NewHigh;
if (r_BarLast > r_BarHigh)
{
r_BarLast = r_BarHigh;
}
if (r_BarOpen > r_BarHigh)
{
r_BarOpen = r_BarHigh;
}
ChartBarInterface.NewRecordToInsert.Low = r_BarHigh;
ChartBarInterface.NewRecordToInsert.Open = r_BarHigh + ChartBarInterface.TickSize;
if (ChartBarInterface.NewRecordToInsert.Close < ChartBarInterface.NewRecordToInsert.Low)
ChartBarInterface.NewRecordToInsert.Close = ChartBarInterface.NewRecordToInsert.Low;
}
else
{
ChartBarInterface.NewRecordToInsert.Low = r_BarLow;
ChartBarInterface.NewRecordToInsert.Close = r_BarLast;
float NewLow = r_BarHigh - NeededRangeAsFloat;
r_BarLow = NewLow;
if (r_BarLast < r_BarLow)
{
r_BarLast = r_BarLow;
}
if (r_BarOpen < r_BarLow)
{
r_BarOpen = r_BarLow;
}
ChartBarInterface.NewRecordToInsert.High = r_BarLow;
ChartBarInterface.NewRecordToInsert.Open = r_BarLow - ChartBarInterface.TickSize;
if (ChartBarInterface.NewRecordToInsert.Close > ChartBarInterface.NewRecordToInsert.High)
ChartBarInterface.NewRecordToInsert.Close = ChartBarInterface.NewRecordToInsert.High;
}
}
}
SCSFExport scsf_CustomRangeChartBarsExample(SCStudyInterfaceRef sc)
{
SCInputRef Input_RangePerBar = sc.Input[0];
if (sc.SetDefaults)
{
sc.GraphRegion = 0;
sc.GraphName = "Custom Range Chart Bars Example";
sc.UsesCustomChartBarFunction = 1;
sc.fp_ACSCustomChartBarFunction = CustomRangeChartBarBuildingFunction;
sc.AutoLoop = 0;
Input_RangePerBar.Name = "Range Per Bar in Ticks";
Input_RangePerBar.SetInt(10);
Input_RangePerBar.SetIntLimits(1, INT_MAX);
return;
}
int& r_ChartDataReloadedFlag = sc.GetPersistentInt(CUSTOM_CHART_BAR_RELOAD_FLAG_KEY);
if (r_ChartDataReloadedFlag == 0)
{
sc.FlagToReloadChartData = true;
r_ChartDataReloadedFlag = 1;
}
const int RangePerBar = Input_RangePerBar.GetInt();
int& r_PriorRangePerBar = sc.GetPersistentInt(1);
if (r_PriorRangePerBar != 0 && r_PriorRangePerBar != RangePerBar)
sc.FlagToReloadChartData = true;
r_PriorRangePerBar = RangePerBar;
if (sc.IsFullRecalculation)
sc.GraphName.Format("Custom Range Bar = %d", RangePerBar);
}