internal override void WorldTickPositions_FirstPass(
Point physicalMin,
Point physicalMax,
out ArrayList largeTickPositions,
out ArrayList smallTickPositions
)
{
if (LargeTickStep != TimeSpan.Zero || SparseWorldLength > 2.0 * (double)tradingTimeSpan_) // utilise base class
{
ArrayList largeTickPositions_FirstPass;
base.WorldTickPositions_FirstPass(physicalMin, physicalMax, out largeTickPositions_FirstPass, out smallTickPositions);
if (largeTickPositions_FirstPass.Count < 2)
{
// leave it alone, whatever that single tick may be (better something than nothing...)
largeTickPositions = largeTickPositions_FirstPass;
}
else if ((double)largeTickPositions_FirstPass[1] - (double)largeTickPositions_FirstPass[0] > 27.0 * (double)TimeSpan.TicksPerDay)
{
// For distances between ticks in months or longer, just accept all ticks
largeTickPositions = largeTickPositions_FirstPass;
}
else
{
// for daily ticks, ignore non-trading hours but obey (skip) non-trading days
largeTickPositions = new ArrayList();
foreach (object tick in largeTickPositions_FirstPass)
{
if (OnTradingDays((double)tick))
largeTickPositions.Add(tick);
}
}
}
else // intraday ticks, own algorithm
{
smallTickPositions = null;
largeTickPositions = new ArrayList();
TimeSpan timeLength = new TimeSpan((long)SparseWorldLength);
DateTime worldMinDate = new DateTime( (long)this.WorldMin );
DateTime worldMaxDate = new DateTime( (long)this.WorldMax );
DateTime currentTickDate;
long skip; // in time ticks
// The following if-else flow establishes currentTickDate to the beginning of series
// and skip to the optimal distance between ticks
// if less than 10 minutes, then large ticks on second spacings.
if ( timeLength < new TimeSpan(0,0,10,0,0) )
{
this.LargeTickLabelType_ = LargeTickLabelType.hourMinuteSeconds;
int secondsSkip;
if (timeLength < new TimeSpan( 0,0,0,10,0 ) )
secondsSkip = 1;
else if ( timeLength < new TimeSpan(0,0,0,20,0) )
secondsSkip = 2;
else if ( timeLength < new TimeSpan(0,0,0,50,0) )
secondsSkip = 5;
else if ( timeLength < new TimeSpan(0,0,2,30,0) )
secondsSkip = 15;
else
secondsSkip = 30;
int second = worldMinDate.Second;
second -= second % secondsSkip;
currentTickDate = new DateTime(
worldMinDate.Year,
worldMinDate.Month,
worldMinDate.Day,
worldMinDate.Hour,
worldMinDate.Minute,
second,0 );
skip = secondsSkip * TimeSpan.TicksPerSecond;
}
// Less than 2 hours, then large ticks on minute spacings.
else if ( timeLength < new TimeSpan(0,2,0,0,0) )
{
this.LargeTickLabelType_ = LargeTickLabelType.hourMinute;
int minuteSkip;
if ( timeLength < new TimeSpan(0,0,10,0,0) )
minuteSkip = 1;
else if ( timeLength < new TimeSpan(0,0,20,0,0) )
minuteSkip = 2;
else if ( timeLength < new TimeSpan(0,0,50,0,0) )
minuteSkip = 5;
else if ( timeLength < new TimeSpan(0,2,30,0,0) )
minuteSkip = 15;
else //( timeLength < new TimeSpan( 0,5,0,0,0) )
minuteSkip = 30;
int minute = worldMinDate.Minute;
minute -= minute % minuteSkip;
currentTickDate = new DateTime(
worldMinDate.Year,
worldMinDate.Month,
worldMinDate.Day,
worldMinDate.Hour,
minute,0,0 );
skip = minuteSkip * TimeSpan.TicksPerMinute;
}
// Else large ticks on hour spacings.
else
{
this.LargeTickLabelType_ = LargeTickLabelType.hourMinute;
int hourSkip;
if (timeLength < new TimeSpan(0, 10, 0, 0, 0))
hourSkip = 1;
else if (timeLength < new TimeSpan(0, 20, 0, 0, 0))
hourSkip = 2;
else
hourSkip = 6;
int hour = worldMinDate.Hour;
hour -= hour % hourSkip;
currentTickDate = new DateTime(
worldMinDate.Year,
worldMinDate.Month,
worldMinDate.Day,
hour, 0, 0, 0);
skip = hourSkip * TimeSpan.TicksPerHour;
}
// place ticks
while (currentTickDate < worldMaxDate)
{
double world = (double)currentTickDate.Ticks;
if (!WithinTradingHours(world))
{
// add gap boundary instead
world = ReverseSparseWorldRemap(SparseWorldRemap(world)); // moves forward
long gap = (long)world;
gap -= gap % skip;
currentTickDate = new DateTime(gap);
}
if (world >= this.WorldMin && world <= this.WorldMax)
{
largeTickPositions.Add(world);
}
currentTickDate = currentTickDate.AddTicks(skip);
}
}
}