www.pudn.com > TeeChart_Pro_v7_0_VCL_CLX_for_Delphi_BCB_Kylix_Ful > CandleCh.pas
{**********************************************}
{ TCandleSeries (derived from OHLCSeries) }
{ TVolumeSeries (derived from TCustomSeries) }
{ TRSIFunction (Resistance Strength Index) }
{ TADXFunction }
{ }
{ Copyright (c) 1995-2004 by David Berneda }
{**********************************************}
unit CandleCh;
{$I TeeDefs.inc}
interface
{
Financial TCandleSeries derives from TOHLCSeries (Open, High, Low & Close).
See OHLChart.pas unit for TOHLCSeries source code.
TCandleSeries overrides the TChartSeries.DrawValue method to paint its
points in several financial styles (CandleStick, Bars, OpenClose, etc).
TVolumeSeries overrides the TChartSeries.DrawValue method to paint
points as thin vertical bars.
TADXFunction is a commonly used financial indicator. It requires an
OHLC (financial) series as the datasource.
TRSIFunction (Resistence Strength Index) is a commonly used financial
indicator. It requires an OHLC (financial) series as the datasource.
}
Uses {$IFNDEF LINUX}
Windows,
{$ENDIF}
Classes,
{$IFDEF CLX}
QGraphics, Types,
{$ELSE}
Graphics,
{$ENDIF}
Chart, Series, OHLChart, TeEngine, TeCanvas;
Const DefCandleWidth = 4; { 2 + 1 + 2 Default width for Candle points }
type
TCandleStyle=(csCandleStick,csCandleBar,csOpenClose,csLine);
TCandleItem=packed record
yOpen : Integer;
yClose : Integer;
yHigh : Integer;
yLow : Integer;
tmpX : Integer;
tmpLeftWidth : Integer;
tmpRightWidth : Integer;
end;
TCandleSeries=class(TOHLCSeries)
private
FCandleStyle : TCandleStyle;
FCandleWidth : Integer;
FDownCloseColor : TColor;
FHighLowPen : TChartPen;
FShowCloseTick : Boolean;
FShowOpenTick : Boolean;
FUpCloseColor : TColor;
OldP : TPoint;
procedure CalcItem(ValueIndex:Integer; var AItem:TCandleItem);
Function GetDark3D:Boolean;
Function GetDraw3D:Boolean;
Function GetPen:TChartPen;
procedure SetCandlePen(Value:TChartPen);
Procedure SetCandleStyle(Value:TCandleStyle);
Procedure SetCandleWidth(Value:Integer);
procedure SetDark3D(Value:Boolean);
Procedure SetDownColor(Value:TColor);
procedure SetDraw3D(Value:Boolean);
Procedure SetShowCloseTick(Value:Boolean);
Procedure SetShowOpenTick(Value:Boolean);
Procedure SetUpColor(Value:TColor);
procedure SetHighLowPen(const Value: TChartPen);
protected
Function CalculateColor(ValueIndex:Integer):TColor;
class Procedure CreateSubGallery(AddSubChart:TChartSubGalleryProc); override;
procedure DrawValue(ValueIndex:Integer); override;
class Function GetEditorClass:String; override;
Procedure PrepareForGallery(IsEnabled:Boolean); override;
class Procedure SetSubGallery(ASeries:TChartSeries; Index:Integer); override;
public
Constructor Create(AOwner: TComponent); override;
Destructor Destroy; override;
Procedure Assign(Source:TPersistent); override;
Function AddCandle( Const ADate:TDateTime;
Const AOpen,AHigh,ALow,AClose:Double):Integer;
Function Clicked(x,y:Integer):Integer; override;
function ClickedCandle(ValueIndex:Integer; const P:TPoint):Boolean;
Function LegendItemColor(LegendIndex:Integer):TColor; override;
Function MaxYValue:Double; override;
Function MinYValue:Double; override;
published
property Active;
property ColorEachPoint;
property ColorSource;
property Cursor;
property Depth;
property HorizAxis;
property Marks;
property ParentChart;
property DataSource;
property PercentFormat;
property SeriesColor;
property ShowInLegend;
property Title;
property ValueFormat;
property VertAxis;
property XLabelsSource;
{ events }
property AfterDrawValues;
property BeforeDrawValues;
property OnAfterAdd;
property OnBeforeAdd;
property OnClearValues;
property OnClick;
property OnDblClick;
property OnGetMarkText;
property OnMouseEnter;
property OnMouseLeave;
property CandleStyle:TCandleStyle read FCandleStyle write SetCandleStyle
default csCandleStick;
property CandleWidth:Integer read FCandleWidth write SetCandleWidth
default DefCandleWidth;
property Draw3D:Boolean read GetDraw3D write SetDraw3D default False;
property Dark3D:Boolean read GetDark3D write SetDark3D default True;
property DownCloseColor:TColor read FDownCloseColor write SetDownColor
default clRed;
property HighLowPen:TChartPen read FHighLowPen write SetHighLowPen;
property ShowCloseTick:Boolean read FShowCloseTick write SetShowCloseTick
default True;
property ShowOpenTick:Boolean read FShowOpenTick write SetShowOpenTick
default True;
property UpCloseColor:TColor read FUpCloseColor write SetUpColor
default clWhite;
property Pen:TChartPen read GetPen write SetCandlePen;
end;
{ Used in financial charts for Volume quantities (or OpenInterest) }
{ Overrides FillSampleValues to create random POSITIVE values }
{ Overrides DrawValue to paint a thin vertical bar }
{ Declares VolumeValues (same like YValues) }
TVolumeSeries=class(TCustomSeries)
private
FUseYOrigin: Boolean;
FOrigin: Double;
IColor : TColor;
Function GetVolumeValues:TChartValueList;
Procedure PrepareCanvas(Forced:Boolean; AColor:TColor);
procedure SetOrigin(const Value: Double);
procedure SetUseOrigin(const Value: Boolean);
Procedure SetVolumeValues(Value:TChartValueList);
protected
Procedure AddSampleValues(NumValues:Integer; OnlyMandatory:Boolean=False); override;
class Procedure CreateSubGallery(AddSubChart:TChartSubGalleryProc); override;
Procedure DrawLegendShape(ValueIndex:Integer; Const Rect:TRect); override;
procedure DrawValue(ValueIndex:Integer); override;
class Function GetEditorClass:String; override;
Procedure PrepareForGallery(IsEnabled:Boolean); override;
Procedure PrepareLegendCanvas( ValueIndex:Integer; Var BackColor:TColor;
Var BrushStyle:TBrushStyle); override;
Procedure SetSeriesColor(AColor:TColor); override;
class Procedure SetSubGallery(ASeries:TChartSeries; Index:Integer); override;
public
Constructor Create(AOwner: TComponent); override;
Procedure Assign(Source:TPersistent); override;
Function NumSampleValues:Integer; override;
published
property Active;
property ColorEachPoint;
property ColorSource;
property Cursor;
property HorizAxis;
property Marks;
property ParentChart;
property DataSource;
property PercentFormat;
property SeriesColor;
property ShowInLegend;
property Title;
property ValueFormat;
property VertAxis;
property XLabelsSource;
{ events }
property AfterDrawValues;
property BeforeDrawValues;
property OnAfterAdd;
property OnBeforeAdd;
property OnClearValues;
property OnClick;
property OnDblClick;
property OnGetMarkText;
property OnMouseEnter;
property OnMouseLeave;
property LinePen;
property UseYOrigin:Boolean read FUseYOrigin write SetUseOrigin default False;
property VolumeValues:TChartValueList read GetVolumeValues write SetVolumeValues;
property XValues;
property YOrigin:Double read FOrigin write SetOrigin;
end;
{ Financial A.D.X function }
TADXFunction=class(TTeeFunction)
private
IDMDown : TFastLineSeries;
IDMUp : TFastLineSeries;
function GetDownPen: TChartPen;
function GetUpPen: TChartPen;
procedure SetDownPen(const Value: TChartPen);
procedure SetUpPen(const Value: TChartPen);
protected
class Function GetEditorClass:String; override;
Function IsValidSource(Value:TChartSeries):Boolean; override;
public
Constructor Create(AOwner:TComponent); override;
Destructor Destroy; override; { 5.01 }
procedure AddPoints(Source:TChartSeries); override;
property DMDown:TFastLineSeries read IDMDown;
property DMUp:TFastLineSeries read IDMUp;
published
property DownLinePen:TChartPen read GetDownPen write SetDownPen;
property UpLinePen:TChartPen read GetUpPen write SetUpPen;
end;
{ RSI, Relative Strentgh Index }
TRSIStyle=(rsiOpenClose,rsiClose);
TRSIFunction = class(TTeeMovingFunction)
private
FStyle : TRSIStyle;
ISeries : TChartSeries;
Opens : TChartValueList;
Closes : TChartValueList;
procedure SetStyle(Const Value:TRSIStyle);
protected
Function IsValidSource(Value:TChartSeries):Boolean; override;
public
Constructor Create(AOwner:TComponent); override;
Function Calculate( Series:TChartSeries;
FirstIndex,LastIndex:Integer):Double; override;
published
property Style:TRSIStyle read FStyle write SetStyle default rsiOpenClose;
end;
implementation
Uses {$IFDEF CLR}
{$ELSE}
Math, SysUtils,
{$ENDIF}
TeeProcs, TeeProCo, TeeConst;
{ TCandleSeries }
Constructor TCandleSeries.Create(AOwner: TComponent);
Begin
inherited;
FUpCloseColor :=clWhite;
FDownCloseColor:=clRed;
FCandleWidth :=DefCandleWidth;
FCandleStyle :=csCandleStick;
FShowOpenTick :=True;
FShowCloseTick :=True;
Pointer.Draw3D :=False;
FHighLowPen:=TChartPen.Create(CanvasChanged); // 7.0
FHighLowPen.Color:=clTeeColor;
end;
Procedure TCandleSeries.SetShowOpenTick(Value:Boolean);
Begin
SetBooleanProperty(FShowOpenTick,Value);
End;
Procedure TCandleSeries.SetShowCloseTick(Value:Boolean);
Begin
SetBooleanProperty(FShowCloseTick,Value);
End;
Function TCandleSeries.CalculateColor(ValueIndex:Integer):TColor;
Begin
result:=ValueColor[ValueIndex];
if result=SeriesColor then
begin
if OpenValues.Value[ValueIndex]>CloseValues.Value[ValueIndex] then { 5.01 }
result:=FDownCloseColor
else
if OpenValues.Value[ValueIndex]CloseValues.Value[ValueIndex] then
result:=FDownCloseColor
else
if CloseValues.Value[ValueIndex-1]tmpBottom then SwapInteger(tmpTop,tmpBottom);
{ Draw Candle Vertical Line from bottom to Low }
if FCandleStyle=csCandleStick then
VertLine3D(tmpX,tmpBottom,yLow,MiddleZ);
{ Draw 3D Candle }
Brush.Color:=CalculateColor(ValueIndex);
if Self.Pen.Visible then
if yOpen=yClose then AssignVisiblePenColor(Self.Pen,CalculateColor(ValueIndex))
else AssignVisiblePen(Self.Pen)
else
Pen.Style:=psClear; // 7.0
Cube( tmpX-tmpLeftWidth,tmpX+tmpRightWidth,tmpTop,tmpBottom,
StartZ,EndZ,Pointer.Dark3D);
CheckHighLowPen;
{ Draw Candle Vertical Line from Top to High }
if FCandleStyle=csCandleStick then
VertLine3D(tmpX,tmpTop,yHigh,MiddleZ);
end
else
begin
{ Draw Candle Vertical Line from High to Low }
if FCandleStyle=csCandleStick then
if View3D then
VertLine3D(tmpX,yLow,yHigh,MiddleZ)
else
DoVertLine(tmpX,yLow,yHigh);
{ remember that Y coordinates are inverted }
{ prevent zero height rectangles 5.02 }
{ in previous releases, an horizontal line was displayed instead
of the small candle rectangle }
if yOpen=yClose then Dec(yClose);
{ draw the candle }
Brush.Color:=CalculateColor(ValueIndex);
if Self.Pen.Visible then
if yOpen=yClose then AssignVisiblePenColor(Self.Pen,CalculateColor(ValueIndex))
else AssignVisiblePen(Self.Pen)
else
Pen.Style:=psClear; // 7.0
if View3D then
RectangleWithZ(TeeRect(tmpX-tmpLeftWidth,yOpen,tmpX+tmpRightWidth,yClose),
MiddleZ)
else
begin
if not Self.Pen.Visible then
if yOpentmpFirst) and (not IsNull(ValueIndex)) then
begin
AssignVisiblePenColor(Self.Pen,CalculateColor(ValueIndex));
BackMode:=cbmTransparent;
if View3D then LineWithZ(OldP,P,MiddleZ)
else Line(OldP,P);
end;
OldP:=P;
end
else
begin // Draw Candle bar
AssignVisiblePenColor(Self.Pen,CalculateColor(ValueIndex));
BackMode:=cbmTransparent;
// Draw Candle Vertical Line from High to Low
if View3D then
begin
VertLine3D(tmpX,yLow,yHigh,MiddleZ);
if ShowOpenTick then HorizLine3D(tmpX,tmpX-tmpLeftWidth-1,yOpen,MiddleZ);
if ShowCloseTick then HorizLine3D(tmpX,tmpX+tmpRightWidth+1,yClose,MiddleZ);
end
else
begin // 5.02
DoVertLine(tmpX,yLow,yHigh);
if ShowOpenTick then DoHorizLine(tmpX,tmpX-tmpLeftWidth-1,yOpen);
if ShowCloseTick then DoHorizLine(tmpX,tmpX+tmpRightWidth+1,yClose);
end;
end;
end;
end;
Procedure TCandleSeries.SetUpColor(Value:TColor);
Begin
SetColorProperty(FUpCloseColor,Value);
end;
Procedure TCandleSeries.SetDownColor(Value:TColor);
Begin
SetColorProperty(FDownCloseColor,Value);
end;
Procedure TCandleSeries.SetCandleWidth(Value:Integer);
Begin
SetIntegerProperty(FCandleWidth,Value);
end;
Procedure TCandleSeries.SetCandleStyle(Value:TCandleStyle);
Begin
if FCandleStyle<>Value then
begin
FCandleStyle:=Value;
Pointer.Visible:=CandleStyle<>csLine;
Repaint;
end;
end;
class Function TCandleSeries.GetEditorClass:String;
Begin
result:='TCandleEditor'; { <-- do not translate }
End;
Procedure TCandleSeries.PrepareForGallery(IsEnabled:Boolean);
Begin
inherited;
FillSampleValues(4);
ColorEachPoint:=IsEnabled;
if IsEnabled then
UpCloseColor:=clBlue
else
begin
UpCloseColor:=clSilver;
DownCloseColor:=clDkGray;
Pointer.Pen.Color:=clGray;
end;
Pointer.Pen.Width:=2;
CandleWidth:=12;
end;
Procedure TCandleSeries.Assign(Source:TPersistent);
begin
if Source is TCandleSeries then
With TCandleSeries(Source) do
begin
Self.FCandleWidth :=FCandleWidth;
Self.FCandleStyle :=FCandleStyle;
Self.FUpCloseColor :=FUpCloseColor;
Self.FDownCloseColor:=FDownCloseColor;
Self.HighLowPen :=FHighLowPen;
Self.FShowOpenTick :=FShowOpenTick;
Self.FShowCloseTick :=FShowCloseTick;
end;
inherited;
end;
Function TCandleSeries.GetDraw3D:Boolean;
begin
result:=Pointer.Draw3D;
end;
procedure TCandleSeries.SetDraw3D(Value:Boolean);
begin
Pointer.Draw3D:=Value;
end;
Function TCandleSeries.GetDark3D:Boolean;
begin
result:=Pointer.Dark3D;
end;
procedure TCandleSeries.SetDark3D(Value:Boolean);
begin
Pointer.Dark3D:=Value;
end;
Function TCandleSeries.GetPen:TChartPen;
begin
result:=Pointer.Pen;
end;
procedure TCandleSeries.SetCandlePen(Value:TChartPen);
begin
Pointer.Pen.Assign(Value);
end;
Function TCandleSeries.AddCandle( Const ADate:TDateTime;
Const AOpen,AHigh,ALow,AClose:Double):Integer;
begin
result:=AddOHLC(ADate,AOpen,AHigh,ALow,AClose);
end;
class procedure TCandleSeries.CreateSubGallery(
AddSubChart: TChartSubGalleryProc);
begin
inherited;
AddSubChart(TeeMsg_CandleBar);
AddSubChart(TeeMsg_CandleNoOpen);
AddSubChart(TeeMsg_CandleNoClose);
AddSubChart(TeeMsg_NoBorder);
AddSubChart(TeeMsg_Line);
end;
class procedure TCandleSeries.SetSubGallery(ASeries: TChartSeries;
Index: Integer);
begin
With TCandleSeries(ASeries) do
Case Index of
1: CandleStyle:=csCandleBar;
2: begin Pen.Show; CandleStyle:=csCandleBar; ShowOpenTick:=False; end;
3: begin Pen.Show; CandleStyle:=csCandleBar; ShowCloseTick:=False; end;
4: begin CandleStyle:=csCandleStick; Pen.Hide; end;
5: begin CandleStyle:=csLine; end;
else inherited;
end;
end;
function TCandleSeries.ClickedCandle(ValueIndex:Integer; const P:TPoint):Boolean;
var tmpItem : TCandleItem;
tmpTop : Integer;
tmpBottom : Integer;
tmpFirst : Integer;
tmpTo : TPoint;
begin
result:=False;
CalcItem(ValueIndex,tmpItem);
With tmpItem do
Begin
if (FCandleStyle=csCandleStick) or (FCandleStyle=csOpenClose) then
begin
if ParentChart.View3D and Pointer.Draw3D then
begin
tmpTop:=yClose;
tmpBottom:=yOpen;
if tmpTop>tmpBottom then SwapInteger(tmpTop,tmpBottom);
if (FCandleStyle=csCandleStick) and
(
PointInLine(P,tmpX,tmpBottom,tmpX,yLow) or
PointInLine(P,tmpX,tmpTop,tmpX,yHigh)
) then
begin
result:=True;
exit;
end;
if PointInRect(TeeRect(tmpX-tmpLeftWidth,tmpTop,tmpX+tmpRightWidth,tmpBottom),P.X,P.Y) then
result:=True;
end
else
begin
if (FCandleStyle=csCandleStick) and
PointInLine(P,tmpX,yLow,tmpX,yHigh) then
begin
result:=True;
exit;
end;
if yOpen=yClose then Dec(yClose);
if ParentChart.View3D then
begin
if PointInRect(TeeRect(tmpX-tmpLeftWidth,yOpen,tmpX+tmpRightWidth,yClose),P.X,P.Y) then
result:=True;
end
else
begin
if not Self.Pen.Visible then
if yOpentmpFirst then result:=PointInLine(P,OldP,tmpTo);
OldP:=tmpTo;
end
else
if PointInLine(P,tmpX,yLow,tmpX,yHigh) or
(ShowOpenTick and PointInLine(P,tmpX,yOpen,tmpX-tmpLeftWidth-1,yOpen)) or
(ShowCloseTick and PointInLine(P,tmpX,yClose,tmpX+tmpRightWidth+1,yClose)) then
result:=True;
end;
end;
function TCandleSeries.Clicked(x, y: Integer): Integer;
var t : Integer;
P : TPoint;
begin
result:=TeeNoPointClicked;
if (FirstValueIndex>-1) and (LastValueIndex>-1) then
begin
if Assigned(ParentChart) then
ParentChart.Canvas.Calculate2DPosition(X,Y,StartZ);
P:=TeePoint(x,y);
for t:=FirstValueIndex to LastValueIndex do
if ClickedCandle(t,P) then
begin
result:=t;
break;
end;
end;
end;
function TCandleSeries.LegendItemColor(LegendIndex: Integer): TColor;
begin
result:=CalculateColor(LegendIndex);
end;
function TCandleSeries.MaxYValue: Double;
begin
if CandleStyle=csLine then result:=CloseValues.MaxValue
else result:=inherited MaxYValue;
end;
function TCandleSeries.MinYValue: Double;
begin
if CandleStyle=csLine then result:=CloseValues.MinValue
else result:=inherited MinYValue;
end;
procedure TCandleSeries.SetHighLowPen(const Value: TChartPen);
begin
FHighLowPen.Assign(Value);
end;
destructor TCandleSeries.Destroy;
begin
FHighLowPen.Free;
inherited;
end;
{ TVolumeSeries }
Constructor TVolumeSeries.Create(AOwner: TComponent);
begin
inherited;
DrawArea:=False;
DrawBetweenPoints:=False;
ClickableLine:=False;
Pointer.Hide;
FUseYOrigin:=False;
end;
Function TVolumeSeries.GetVolumeValues:TChartValueList;
Begin
result:=YValues;
end;
Procedure TVolumeSeries.SetSeriesColor(AColor:TColor);
begin
inherited;
LinePen.Color:=AColor;
end;
Procedure TVolumeSeries.SetVolumeValues(Value:TChartValueList);
Begin
SetYValues(Value);
end;
Procedure TVolumeSeries.PrepareCanvas(Forced:Boolean; AColor:TColor);
begin
if Forced or (AColor<>IColor) then
begin
ParentChart.Canvas.AssignVisiblePenColor(LinePen,AColor);
ParentChart.Canvas.BackMode:=cbmTransparent;
IColor:=AColor;
end;
end;
procedure TVolumeSeries.DrawValue(ValueIndex:Integer);
var tmpY : Integer;
Begin
PrepareCanvas(ValueIndex=FirstDisplayedIndex, ValueColor[ValueIndex]);
{ moves to x,y coordinates and draws a vertical bar to top or bottom,
depending on the vertical Axis.Inverted property }
if UseYOrigin then
tmpY:=CalcYPosValue(YOrigin) { 5.02 }
else
With GetVertAxis do
if Inverted then tmpY:=IStartPos else tmpY:=IEndPos;
with ParentChart,Canvas do
if View3D then
VertLine3D(CalcXPos(ValueIndex),CalcYPos(ValueIndex),tmpY,MiddleZ)
else
DoVertLine(CalcXPos(ValueIndex),tmpY,CalcYPos(ValueIndex)); { 5.02 }
end;
Function TVolumeSeries.NumSampleValues:Integer;
Begin
result:=40;
end;
Procedure TVolumeSeries.AddSampleValues(NumValues:Integer; OnlyMandatory:Boolean=False);
Var t : Integer;
s : TSeriesRandomBounds;
begin
s:=RandomBounds(NumValues);
with s do
for t:=1 to NumValues do
Begin
AddXY(tmpX,RandomValue(Round(DifY) div 15));
tmpX:=tmpX+StepX;
end;
end;
Procedure TVolumeSeries.PrepareForGallery(IsEnabled:Boolean);
begin
inherited;
FillSampleValues(26);
Pointer.InflateMargins:=True;
end;
class Function TVolumeSeries.GetEditorClass:String;
Begin
result:='TVolumeSeriesEditor';
End;
class procedure TVolumeSeries.CreateSubGallery(
AddSubChart: TChartSubGalleryProc);
begin
inherited;
AddSubChart(TeeMsg_Dotted);
AddSubChart(TeeMsg_Colors);
AddSubChart(TeeMsg_Origin); { 5.02 }
end;
class procedure TVolumeSeries.SetSubGallery(ASeries: TChartSeries;
Index: Integer);
begin
With TVolumeSeries(ASeries) do
Case Index of
1: Pen.SmallDots:=True;
2: ColorEachPoint:=True;
3: UseYOrigin:=True;
else inherited
end;
end;
procedure TVolumeSeries.DrawLegendShape(ValueIndex: Integer; { 5.01 }
const Rect: TRect);
begin
With Rect do ParentChart.Canvas.DoHorizLine(Left,Right,(Top+Bottom) div 2);
end;
procedure TVolumeSeries.Assign(Source: TPersistent);
begin
if Source is TVolumeSeries then
with TVolumeSeries(Source) do
begin
Self.FUseYOrigin:= UseYOrigin;
Self.FOrigin := YOrigin;
end;
inherited;
end;
procedure TVolumeSeries.SetOrigin(const Value: Double);
begin
SetDoubleProperty(FOrigin,Value);
end;
procedure TVolumeSeries.SetUseOrigin(const Value: Boolean);
begin
SetBooleanProperty(FUseYOrigin,Value);
end;
procedure TVolumeSeries.PrepareLegendCanvas(ValueIndex: Integer;
var BackColor: TColor; var BrushStyle: TBrushStyle);
begin
PrepareCanvas(True,SeriesColor);
end;
{ TADXFunction }
type TChartSeriesAccess=class(TChartSeries);
Constructor TADXFunction.Create(AOwner: TComponent);
Procedure HideSeries(ASeries:TChartSeries);
begin
ASeries.ShowInLegend:=False;
TChartSeriesAccess(ASeries).InternalUse:=True;
end;
begin
inherited;
InternalSetPeriod(14);
SingleSource:=True;
HideSourceList:=True;
IDMDown:=TFastLineSeries.Create(Self);
HideSeries(IDMDown);
IDMDown.SeriesColor:=clRed;
IDMUp:=TFastLineSeries.Create(Self);
HideSeries(IDMUp);
IDMUp.SeriesColor:=clGreen;
end;
procedure TADXFunction.AddPoints(Source: TChartSeries);
Procedure PrepareSeries(ASeries:TChartSeries);
begin
With ASeries do
begin
ParentChart:=ParentSeries.ParentChart;
CustomVertAxis:=ParentSeries.CustomVertAxis;
VertAxis:=ParentSeries.VertAxis;
XValues.DateTime:=ParentSeries.XValues.DateTime;
AfterDrawValues:=ParentSeries.AfterDrawValues;
BeforeDrawValues:=ParentSeries.BeforeDrawValues;
end;
end;
Function CalcADX(Index:Integer):Double;
begin
Index:=Index-Round(Period);
result:=(100*Abs(IDMUp.YValues.Value[Index]-IDMDown.YValues.Value[Index])/
(IDMUp.YValues.Value[Index]+IDMDown.YValues.Value[Index]));
end;
var tmpTR,
tmpDMUp,
tmpDMDown : Array of Double;
t : Integer;
tt : Integer;
tmpClose : Double;
Closes,
Highs,
Lows : TChartValueList;
tmpTR2,
tmpUp2,
tmpDown2 : Double;
tmpX : Double;
tmp : Integer;
tmpADX : Double;
begin
if Period<2 then Exit; // 5.03
ParentSeries.Clear;
IDMUp.Clear;
IDMDown.Clear;
PrepareSeries(IDMUp);
PrepareSeries(IDMDown);
if Source.Count>=(2*Period) then
begin
With TOHLCSeries(Source) do
begin
Closes:=CloseValues;
Highs:=HighValues;
Lows:=LowValues;
end;
SetLength(tmpTR, Source.Count);
SetLength(tmpDMUp, Source.Count);
SetLength(tmpDMDown, Source.Count);
for t:=1 to Source.Count-1 do
begin
tmpClose:=Closes.Value[t-1];
tmpTR[t]:=Highs.Value[t]-Lows.Value[t];
tmpTR[t]:=Math.Max(tmpTR[t],Abs(Highs.Value[t]-tmpClose));
tmpTR[t]:=Math.Max(tmpTR[t],Abs(Lows.Value[t]-tmpClose));
if (Highs.Value[t]-Highs.Value[t-1])>(Lows.Value[t-1]-Lows.Value[t]) then
tmpDMUp[t]:=Math.Max(0,Highs.Value[t]-Highs.Value[t-1])
else
tmpDMUp[t]:=0;
if (Lows.Value[t-1]-Lows.Value[t])>(Highs.Value[t]-Highs.Value[t-1]) then
tmpDMDown[t]:=Math.Max(0,Lows.Value[t-1]-Lows.Value[t])
else
tmpDMDown[t]:=0;
end;
tmpTR2:=0;
tmpUp2:=0;
tmpDown2:=0;
tmp:=Round(Period);
for t:=tmp to Source.Count-1 do
begin
if t=tmp then
begin
for tt:=1 to Round(Period) do
begin
tmpTR2 :=tmpTR2+tmpTR[tt];
tmpUp2 :=tmpUp2+tmpDMUp[tt];
tmpDown2:=tmpDown2+tmpDMDown[tt];
end;
end
else
begin
tmpTR2:=tmpTR2-(tmpTR2/Period)+tmpTR[t];
tmpUp2:=tmpUp2-(tmpUp2/Period)+tmpDMUp[t];
tmpDown2:=tmpDown2-(tmpDown2/Period)+tmpDMDown[t];
end;
tmpX:=Source.XValues[t];
IDMUp.AddXY( tmpX, 100*(tmpUp2/tmpTR2));
IDMDown.AddXY( tmpX, 100*(tmpDown2/tmpTR2));
end;
tmpTR:=nil;
tmpDMUp:=nil;
tmpDMDown:=nil;
tmpADX:=0;
tmp:=Round((2*Period)-2);
for t:=tmp to Source.Count-1 do
begin
if t=tmp then
begin
tmpADX:=0;
for tt:=Round(Period) to tmp do tmpADX:=tmpADX+CalcADX(tt);
tmpADX:=tmpADX/(Period-1);
end
else
begin
tmpADX:=((tmpADX*(Period-1))+(CalcADX(t)))/Period;
end;
ParentSeries.AddXY(Source.XValues[t],tmpADX);
end;
end;
end;
Destructor TADXFunction.Destroy; { 5.01 }
begin
DMDown.Free;
DMUp.Free;
inherited;
end;
class function TADXFunction.GetEditorClass: String;
begin
result:='TADXFuncEditor';
end;
function TADXFunction.IsValidSource(Value: TChartSeries): Boolean;
begin
result:=Value is TOHLCSeries;
end;
function TADXFunction.GetDownPen: TChartPen;
begin
result:=DMDown.Pen;
end;
function TADXFunction.GetUpPen: TChartPen;
begin
result:=DMUp.Pen;
end;
procedure TADXFunction.SetDownPen(const Value: TChartPen);
begin
DMDown.Pen:=Value;
end;
procedure TADXFunction.SetUpPen(const Value: TChartPen);
begin
DMUp.Pen:=Value;
end;
{ R.S.I. }
Constructor TRSIFunction.Create(AOwner: TComponent);
begin
inherited;
FStyle:=rsiOpenClose;
SingleSource:=True;
HideSourceList:=True;
end;
Function TRSIFunction.Calculate( Series:TChartSeries;
FirstIndex,LastIndex:Integer):Double;
var NumPoints : Integer;
t : Integer;
tmpClose : Double;
Ups : Double;
Downs : Double;
Begin
if ISeries<>Series then
begin // Cache lists during calculation
Closes:=Series.GetYValueList('CLOSE');
Opens :=Series.GetYValueList('OPEN');
ISeries:=Series;
end;
Ups:=0;
Downs:=0;
With Series do
Begin
if Self.Style=rsiOpenClose then
begin // use today Close and Open prices (do not use "yesterday" close)
for t:=FirstIndex to LastIndex do
Begin
tmpClose:=Closes.Value[t];
if Opens.Value[t]>tmpClose then Downs:=Downs+tmpClose
else Ups :=Ups +tmpClose;
end;
end
else
begin // Use Close prices (today - yesterday)
for t:=FirstIndex+1 to LastIndex do
Begin
tmpClose:=Closes.Value[t]-Closes.Value[t-1];
if tmpClose<0 then Downs:=Downs-tmpClose
else Ups :=Ups +tmpClose;
end;
end;
end;
{ Calculate RSI }
NumPoints:=(LastIndex-FirstIndex)+1;
Downs:=Downs/NumPoints;
Ups :=Ups /NumPoints;
if Downs<>0 then
Begin
result:=100.0 - ( 100.0 / ( 1.0+Abs(Ups/Downs) ) );
if result<0 then result:=0 else
if result>100 then result:=100;
end
else result:=100; // Special case, to avoid divide by zero
end;
// R.S.I. function needs an OHLC series values to calculate.
function TRSIFunction.IsValidSource(Value: TChartSeries): Boolean;
begin
result:=Value is TOHLCSeries;
end;
procedure TRSIFunction.SetStyle(const Value: TRSIStyle);
begin
if Style<>Value then
begin
FStyle:=Value;
ReCalculate;
end;
end;
initialization
RegisterTeeSeries( TCandleSeries, {$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryCandle,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryFinancial, 1);
RegisterTeeSeries( TVolumeSeries, {$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryVolume,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryFinancial, 1);
RegisterTeeFunction( TADXFunction, {$IFNDEF CLR}@{$ENDIF}TeeMsg_FunctionADX,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryFinancial );
RegisterTeeFunction( TRSIFunction, {$IFNDEF CLR}@{$ENDIF}TeeMsg_FunctionRSI,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryFinancial );
finalization
UnRegisterTeeSeries([TCandleSeries,TVolumeSeries]);
UnRegisterTeeFunctions([ TADXFunction,TRSIFunction ]);
end.