Get the visible points
Get the visible points
I insert 1000 values to my candle series, X-axis is DateTime
1. i want to get the number of currently displaying points when i zoom in so i can scale candles widths, problem is when i use VisibleCount of series it will return 1000 which is all my data, but after i zoomed in i have like only 5 points visible so that value is incorrect.
2. when i zoom with mouse wheel it will keep zooming, how may i limit the zoom to for example not zoomin more than 2 days gap in x-axis and not zoomout when all points are displaying and with left and right of chart.
3. how can i force x-axis to only display the dates i have inserted and not any data in between? for example i add data with 5 days in gap but when i zoomin it will expand data range to all dates in between (see img)
1. i want to get the number of currently displaying points when i zoom in so i can scale candles widths, problem is when i use VisibleCount of series it will return 1000 which is all my data, but after i zoomed in i have like only 5 points visible so that value is incorrect.
2. when i zoom with mouse wheel it will keep zooming, how may i limit the zoom to for example not zoomin more than 2 days gap in x-axis and not zoomout when all points are displaying and with left and right of chart.
3. how can i force x-axis to only display the dates i have inserted and not any data in between? for example i add data with 5 days in gap but when i zoomin it will expand data range to all dates in between (see img)
- Attachments
-
- cap1.PNG (4.1 KiB) Viewed 23228 times
Re: Get the visible points
Hello,
This is the basic application I've started with to test this (note I've tried this with VCL but it shouldn't be different in FMX):n2n wrote:I insert 1000 values to my candle series, X-axis is DateTime
Code: Select all
uses CandleCh;
procedure TForm1.FormCreate(Sender: TObject);
begin
Chart1.View3D:=false;
Chart1.Legend.Visible:=false;
with Chart1.AddSeries(TCandleSeries) as TCandleSeries do
begin
XValues.DateTime:=true;
FillSampleValues(1000);
end;
end;
Try forcing a chart repaint at OnZoom event before retrieving the VisibleCount. Ie:n2n wrote:1. i want to get the number of currently displaying points when i zoom in so i can scale candles widths, problem is when i use VisibleCount of series it will return 1000 which is all my data, but after i zoomed in i have like only 5 points visible so that value is incorrect.
Code: Select all
procedure TForm1.Chart1Zoom(Sender: TObject);
begin
Chart1.Draw;
Caption:=IntToStr(Chart1[0].VisibleCount);
end;
You can also force the axis scale (minimum, maximum or both) at OnZoom event. Ie:n2n wrote:2. when i zoom with mouse wheel it will keep zooming, how may i limit the zoom to for example not zoomin more than 2 days gap in x-axis and not zoomout when all points are displaying and with left and right of chart.
Code: Select all
procedure TForm1.Chart1Zoom(Sender: TObject);
begin
if (Chart1.Axes.Bottom.Maximum-Chart1.Axes.Bottom.Minimum
< DateTimeStep[dtOneDay]*2) then
begin
Chart1.Axes.Bottom.Maximum:=Chart1.Axes.Bottom.Minimum+DateTimeStep[dtOneDay]*2;
end;
Chart1.Draw;
Caption:=IntToStr(Chart1[0].VisibleCount);
end;
Adding this at OnCreate seems to do what you describe:n2n wrote:3. how can i force x-axis to only display the dates i have inserted and not any data in between? for example i add data with 5 days in gap but when i zoomin it will expand data range to all dates in between (see img)
Code: Select all
Chart1.Axes.Bottom.LabelStyle:=talPointValue;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Get the visible points
Thanks for the reply,
Last problem solved, however how may i delete the space between missing dates? for example i have value for 1st dec and 5th dec and 3 days in between with no data, currently it will create empty space for them, how can i remove them?
Last problem solved, however how may i delete the space between missing dates? for example i have value for 1st dec and 5th dec and 3 days in between with no data, currently it will create empty space for them, how can i remove them?
Re: Get the visible points
Hello,
I'd suggest you to convert your datetimes to strings (to use as labels) and add the values in consecutive XValues but with label. Ie:
This usually indicates the points are being added with an XValue - in your case a TDateTime.n2n wrote:how may i delete the space between missing dates? for example i have value for 1st dec and 5th dec and 3 days in between with no data, currently it will create empty space for them, how can i remove them?
I'd suggest you to convert your datetimes to strings (to use as labels) and add the values in consecutive XValues but with label. Ie:
Code: Select all
uses CandleCh, DateUtils;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
tmpDate: TDateTime;
begin
Chart1.View3D:=false;
Chart1.Legend.Visible:=false;
with Chart1.AddSeries(TCandleSeries) as TCandleSeries do
begin
XValues.DateTime:=true;
FillSampleValues(10);
tmpDate:=XValue[0];
for i:=1 to Count-1 do
begin
tmpDate:=IncDay(tmpDate,1+Round(random*4));
XValue[i]:=tmpDate;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var tmpDate: TDateTime;
tmpS: string;
i: Integer;
begin
with Chart1[0] as TCandleSeries do
begin
tmpDate:=XValue[0];
for i:=0 to Count-1 do
begin
tmpS:=FormatDateTime(Chart1.Axes.Bottom.DateTimeFormat, XValue[i]);
Labels[i]:=tmpS;
XValue[i]:=tmpDate;
tmpDate:=IncDay(tmpDate);
end;
end;
end;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Get the visible points
Hi,
Changing my Xvalues to string will cause me alot of problems, i do actually use the xvalue double data for some calculations, would there be any other workaround to overcome this with maintaining Xvalue with double data and not using Labels? also im currently using OnGetAxisLabel, to convert TDateTime to string due to some conditions when i zoom in i require to use different FormatDateTime.
Changing my Xvalues to string will cause me alot of problems, i do actually use the xvalue double data for some calculations, would there be any other workaround to overcome this with maintaining Xvalue with double data and not using Labels? also im currently using OnGetAxisLabel, to convert TDateTime to string due to some conditions when i zoom in i require to use different FormatDateTime.
Re: Get the visible points
Hello,
The XValue is the array of doubles TeeChart takes to calculate the x pixel position to draw each value in the series. That's why the easiest way to change the later is by changing the first.
An alternative to keep your DateTimes next to each value would be overriding TCandleSeries adding a new array of to it. Then, your values could be drawn using XValue as always (0, 1, 2,...) and you can make the axis to show the values in the array of DateTimes in the series.
Here it is a simple example doing it:
The XValue is the array of doubles TeeChart takes to calculate the x pixel position to draw each value in the series. That's why the easiest way to change the later is by changing the first.
An alternative to keep your DateTimes next to each value would be overriding TCandleSeries adding a new array of to it. Then, your values could be drawn using XValue as always (0, 1, 2,...) and you can make the axis to show the values in the array of DateTimes in the series.
Here it is a simple example doing it:
Code: Select all
uses CandleCh, DateUtils, TeeProCo, TeeConst;
type
TMyCandleSeries = class(TCandleSeries)
private
FDate : TChartValueList;
procedure SetDateValues(const Value:TChartValueList);
protected
//Changes the axis from showing the values in XValues to show the values in FDate
function ValueListOfAxis(const Axis:TChartAxis):TChartValueList; override;
//Use custom AddDateCandle function instead of AddOHLC fucntion
procedure AddSampleValues(NumValues:Integer; OnlyMandatory:Boolean=False); override;
public
property DateValues:TChartValueList read FDate write SetDateValues;
constructor Create(AOwner: TComponent); override;
//Adds a candle without XValue, so consecutive
function AddDateCandle(const ADate:TDateTime;
const AOpen,AHigh,ALow,AClose:Double;
const ALabel:String='';
AColor:TColor=clTeeColor ):Integer;
end;
TValueListAccess=class(TChartValueList);
Constructor TMyCandleSeries.Create(AOwner: TComponent);
begin
inherited;
TValueListAccess(XValues).InitDateTime(False);
XValues.Name:=TeeMsg_ValuesX;
FDate:=TChartValueList.Create(Self,TeeMsg_ValuesDate);
TValueListAccess(DateValues).InitDateTime(True);
NotMandatoryValueList:=FDate;
end;
Procedure TMyCandleSeries.SetDateValues(const Value:TChartValueList);
Begin
SetChartValueList(FDate,Value);
end;
function TMyCandleSeries.ValueListOfAxis(const Axis:TChartAxis):TChartValueList;
begin
if AssociatedToAxis(Axis) then
if Axis.Horizontal then result:=FDate
else result:=YValues
else
result:=nil;
end;
Function TMyCandleSeries.AddDateCandle(const ADate:TDateTime;
const AOpen,AHigh,ALow,AClose:Double;
const ALabel:String='';
AColor:TColor=clTeeColor ):Integer;
begin
HighValues.TempValue:=AHigh;
LowValues.TempValue:=ALow;
OpenValues.TempValue:=AOpen;
DateValues.TempValue:=ADate;
result:=AddY(AClose,ALabel,AColor);
end;
Procedure TMyCandleSeries.AddSampleValues(NumValues:Integer; OnlyMandatory:Boolean=False);
Var AOpen : Double;
AHigh : Double;
ALow : Double;
AClose : Double;
t : Integer;
s : TSeriesRandomBounds;
Begin
s:=RandomBounds(NumValues);
with s do
begin
tmpX:=Date;
AOpen:=MinY+RandomValue(Round(DifY)); { starting open price }
t:=1;
while t<=NumValues do
Begin
// Generate random figures
GetRandomOHLC(AOpen,AClose,AHigh,ALow,DifY);
AddDateCandle(tmpX,AOpen,AHigh,ALow,AClose);
Inc(t);
tmpX:=tmpX+StepX; { <-- next point X value }
// Tomorrow, the market will open at today's close plus/minus something }
AOpen:=AClose+RandomValue(10)-5;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
tmpDate: TDateTime;
begin
Chart1.View3D:=false;
Chart1.Legend.Visible:=false;
with Chart1.AddSeries(TMyCandleSeries) as TMyCandleSeries do
begin
FillSampleValues(10);
//Modifying the DateValues array that only affects the labels, not the x positions of the candles
tmpDate:=DateValues[0];
for i:=1 to Count-1 do
begin
tmpDate:=IncDay(tmpDate,1+Round(random*4));
DateValues[i]:=tmpDate;
end;
end;
Chart1.Axes.Bottom.LabelStyle:=talPointValue;
end;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Get the visible points
Hi,
I just realized after using:
To limit labels with only the ones with value, it will significantly reduce the performance when we have 1000 over points on our BottomAxis, and even though only few of the labels are showing actually but it will trigger the OnGetAxisLabel for every single point and this will even will trigger on every occasion even on mouse move. is it possible to improve performance on this issue?
I just realized after using:
Code: Select all
LabelStyle := talPointValue;
Re: Get the visible points
Hello,
If you are using OnGetAxisLabel only to format the bottom axis labels depending on the axis scale after zooming:n2n wrote:I just realized after using:To limit labels with only the ones with value, it will significantly reduce the performance when we have 1000 over points on our BottomAxis, and even though only few of the labels are showing actually but it will trigger the OnGetAxisLabel for every single point and this will even will trigger on every occasion even on mouse move. is it possible to improve performance on this issue?Code: Select all
LabelStyle := talPointValue;
You could try changing the bottom axis FormatDateTime at OnZoom/OnUndoZoom:n2n wrote:also im currently using OnGetAxisLabel, to convert TDateTime to string due to some conditions when i zoom in i require to use different FormatDateTime.
Code: Select all
procedure TForm1.Chart1Zoom(Sender: TObject);
var i: Integer;
tmpFirstIndex, tmpLastIndex: Integer;
visibleRange: double;
begin
Chart1.Draw;
tmpFirstIndex:=-1;
tmpLastIndex:=-1;
if Chart1[0] is TMyCandleSeries then
with TMyCandleSeries(Chart1[0]) do
begin
for i:=0 to Count-1 do
begin
if (XValue[i]>=Chart1.Axes.Bottom.Minimum) and
(XValue[i]<=Chart1.Axes.Bottom.Maximum) then
begin
tmpFirstIndex:=i;
break;
end;
end;
for i:=Count-1 downto 0 do
begin
if (XValue[i]>=Chart1.Axes.Bottom.Minimum) and
(XValue[i]<=Chart1.Axes.Bottom.Maximum) then
begin
tmpLastIndex:=i;
break;
end;
end;
if (tmpFirstIndex>-1) and (tmpLastIndex>-1) then
begin
visibleRange:=DateValues[tmpLastIndex]-DateValues[tmpFirstIndex];
if visibleRange < DateTimeStep[dtOneMonth] then
begin
Chart1.Title.Text.Text:=FormatDateTime('MMM yyyy', DateValues[LastDisplayedIndex]);
Chart1.Axes.Bottom.DateTimeFormat:='dd';
end
else
if visibleRange < DateTimeStep[dtOneYear] then
begin
Chart1.Title.Text.Text:=FormatDateTime('yyyy', DateValues[LastDisplayedIndex]);
Chart1.Axes.Bottom.DateTimeFormat:='dd/MM';
end;
end;
end;
end;
procedure TForm1.Chart1UndoZoom(Sender: TObject);
begin
Chart1.Title.Text.Text:='TeeChart';
Chart1.Axes.Bottom.DateTimeFormat:='dd/MM/yyyy';
end;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Get the visible points
Hi,
This will certainly do the trick for dateformat, however i still need
To only show xvalues that i have added. would it be possible to calculate this manually aswell?
This will certainly do the trick for dateformat, however i still need
Code: Select all
LabelStyle := talPointValue;
Re: Get the visible points
Hello,
However, if you know the value to get the label for, you can just call the axis LabelValue:
If you are using the customized TMyCandleSeries I suggested above, you would use this instead:
Just note the chart needs to be drawn at least once to use those functions.
I'm not sure to understand what do you mean here, or where do you need to get the labels.n2n wrote:would it be possible to calculate this manually aswell?
However, if you know the value to get the label for, you can just call the axis LabelValue:
Code: Select all
mystring:=Chart1.Axes.Bottom.LabelValue(Chart1[0].XValue[10]);
Code: Select all
mystring:=Chart1.Axes.Bottom.LabelValue(Chart1[0].DateValues[10]);
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |