@@ -61,7 +61,7 @@ public virtual BaseSeries Sample(BaseSeries series, DateTime start, DateTime sto
61
61
if ( dataDiff >= Step )
62
62
{
63
63
// we don't want to subsample this case, directly return what we are given as long as is within the range
64
- return GetIdentitySeries ( series . Clone ( empty : true ) , series , start , stop , truncateValues : false ) ;
64
+ return GetIdentitySeries ( series . Clone ( empty : true ) , series , start , stop , truncateValues : false , roundTime : series . SeriesType == SeriesType . StackedArea ) ;
65
65
}
66
66
}
67
67
@@ -125,13 +125,13 @@ private Series SampleSeries(Series series, DateTime start, DateTime stop, bool t
125
125
{
126
126
var sampled = ( Series ) series . Clone ( empty : true ) ;
127
127
128
- var nextSampleTime = start ;
128
+ var nextSampleTime = start . RoundUp ( Step ) ;
129
129
130
130
// we can't sample a single point and it doesn't make sense to sample scatter plots
131
131
// in this case just copy the raw data
132
132
if ( series . Values . Count < 2 || series . SeriesType == SeriesType . Scatter )
133
133
{
134
- return GetIdentitySeries ( sampled , series , start , stop , truncateValues ) ;
134
+ return GetIdentitySeries ( sampled , series , start , stop , truncateValues , series . SeriesType == SeriesType . StackedArea ) ;
135
135
}
136
136
137
137
var enumerator = series . Values . Cast < ChartPoint > ( ) . GetEnumerator ( ) ;
@@ -143,9 +143,9 @@ private Series SampleSeries(Series series, DateTime start, DateTime stop, bool t
143
143
var current = enumerator . Current ;
144
144
145
145
// make sure we don't start sampling before the data begins
146
- if ( nextSampleTime < previous . Time )
146
+ while ( nextSampleTime < previous . Time )
147
147
{
148
- nextSampleTime = previous . Time ;
148
+ nextSampleTime += Step ;
149
149
}
150
150
151
151
// make sure to advance into the requested time frame before sampling
@@ -168,7 +168,7 @@ private Series SampleSeries(Series series, DateTime start, DateTime stop, bool t
168
168
}
169
169
else
170
170
{
171
- sampledPoint = TruncateValue ( Interpolate ( previous , current , nextSampleTime , ( decimal ) Step . TotalSeconds ) , truncateValues , clone : false ) ;
171
+ sampledPoint = TruncateValue ( Interpolate ( previous , current , nextSampleTime , ( decimal ) Step . TotalSeconds ) , truncateValues , clone : false , roundTime : false ) ;
172
172
}
173
173
174
174
nextSampleTime += Step ;
@@ -224,7 +224,7 @@ private CandlestickSeries SampleCandlestickSeries(CandlestickSeries series, Date
224
224
// we can't sample a single point, so just copy the raw data
225
225
if ( seriesSize < 2 )
226
226
{
227
- return GetIdentitySeries ( sampledSeries , series , start , stop , truncateValues ) ;
227
+ return GetIdentitySeries ( sampledSeries , series , start , stop , truncateValues , roundTime : false ) ;
228
228
}
229
229
230
230
// Make sure we don't start sampling before the data begins.
@@ -240,7 +240,7 @@ private CandlestickSeries SampleCandlestickSeries(CandlestickSeries series, Date
240
240
if ( startIndex < 0 )
241
241
{
242
242
// there's not value before the start, just return identity
243
- return GetIdentitySeries ( sampledSeries , series , start , stop , truncateValues ) ;
243
+ return GetIdentitySeries ( sampledSeries , series , start , stop , truncateValues , roundTime : false ) ;
244
244
}
245
245
if ( candlesticks [ startIndex ] . Time == nextSampleTime && nextSampleTime <= stop )
246
246
{
@@ -333,7 +333,7 @@ private CandlestickSeries SampleCandlestickSeries(CandlestickSeries series, Date
333
333
/// Aggregates the candlesticks in the given range into a single candlestick,
334
334
/// keeping the first open and last close and calculating highest high and lowest low
335
335
/// </summary>
336
- private static Candlestick AggregateCandlesticks ( List < ISeriesPoint > candlesticks , int start , int end , DateTime time , bool truncateValues )
336
+ private Candlestick AggregateCandlesticks ( List < ISeriesPoint > candlesticks , int start , int end , DateTime time , bool truncateValues )
337
337
{
338
338
var aggregatedCandlestick = new Candlestick
339
339
{
@@ -349,7 +349,7 @@ private static Candlestick AggregateCandlesticks(List<ISeriesPoint> candlesticks
349
349
aggregatedCandlestick . Update ( current . Close ) ;
350
350
}
351
351
352
- return ( Candlestick ) TruncateValue ( aggregatedCandlestick , truncateValues , clone : false ) ;
352
+ return ( Candlestick ) TruncateValue ( aggregatedCandlestick , truncateValues , clone : false , roundTime : false ) ;
353
353
}
354
354
355
355
/// <summary>
@@ -424,15 +424,18 @@ private static Candlestick Interpolate(Candlestick template, Candlestick first,
424
424
/// Truncates the value/values of the point after cloning it to avoid mutating the original point
425
425
/// </summary>
426
426
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
427
- private static ISeriesPoint TruncateValue ( ISeriesPoint point , bool truncate , bool clone = false )
427
+ private ISeriesPoint TruncateValue ( ISeriesPoint point , bool truncate , bool clone = false , bool roundTime = false )
428
428
{
429
+ var truncatedPoint = clone ? point . Clone ( ) : point ;
430
+ if ( roundTime )
431
+ {
432
+ truncatedPoint . Time = truncatedPoint . Time . RoundUp ( Step ) ;
433
+ }
429
434
if ( ! truncate )
430
435
{
431
- return point ;
436
+ return truncatedPoint ;
432
437
}
433
438
434
- var truncatedPoint = clone ? point . Clone ( ) : point ;
435
-
436
439
if ( truncatedPoint is ChartPoint chartPoint )
437
440
{
438
441
chartPoint . y = SafeTruncate ( chartPoint . y ) ;
@@ -451,15 +454,15 @@ private static ISeriesPoint TruncateValue(ISeriesPoint point, bool truncate, boo
451
454
/// <summary>
452
455
/// Gets the identity series, this is the series with no sampling applied.
453
456
/// </summary>
454
- protected static T GetIdentitySeries < T > ( T sampled , T series , DateTime start , DateTime stop , bool truncateValues )
457
+ protected T GetIdentitySeries < T > ( T sampled , T series , DateTime start , DateTime stop , bool truncateValues , bool roundTime )
455
458
where T : BaseSeries
456
459
{
457
460
// we can minimally verify we're within the start/stop interval
458
461
foreach ( var point in series . Values )
459
462
{
460
463
if ( point . Time >= start && point . Time <= stop )
461
464
{
462
- sampled . Values . Add ( TruncateValue ( point , truncateValues , clone : true ) ) ;
465
+ sampled . Values . Add ( TruncateValue ( point , truncateValues , clone : true , roundTime ) ) ;
463
466
}
464
467
}
465
468
return sampled ;
0 commit comments