statchar.pas

来自「Delphi TeeChartPro.6.01的源代码」· PAS 代码 · 共 1,262 行 · 第 1/3 页

PAS
1,262
字号
  IMoving2.Period:=26;
  ISeries2:=TChartSeries.Create(nil);
  ISeries2.SetFunction(IMoving2);
  Period:=IMoving2.Period;

  IOther:=TFastLineSeries.Create(Self);
  HideSeries(IOther);
  IOther.SetFunction(TExpMovAveFunction.Create(nil));
  IOther.FunctionType.Period:=9;
  IOther.SeriesColor:=clGreen;

  IHisto:=TVolumeSeries.Create(Self);
  HideSeries(IHisto);
  IHisto.SeriesColor:=clRed;
  IHisto.UseYOrigin:=True;
  IHisto.YOrigin:=0;
end;

destructor TMACDFunction.Destroy;
begin
  ISeries1.Free;
  ISeries2.Free;
  inherited;
end;

class function TMACDFunction.GetEditorClass: String;
begin
  result:='TMACDFuncEditor';
end;

procedure TMACDFunction.AddPoints(Source: TChartSeries);

  Procedure PrepareSeries(ASeries:TChartSeries);
  begin { copy properties from "ParentSeries" to ASeries }
    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;

var t : Integer;
begin
  { calculate first line... }
  ParentSeries.Clear;
  With Source do
  if Count>1 then
  begin
    IMoving1.AddPoints(Source);
    IMoving2.Period:=Self.Period;
    IMoving2.AddPoints(Source);
    for t:=0 to Count-1 do
        ParentSeries.AddXY(XValues.Value[t],
                           ISeries1.YValues.Value[t]-ISeries2.YValues.Value[t]);
    ISeries1.Clear;
    ISeries2.Clear;
  end;

  // Calculate "MACDExp" second line, even if not visible.
  PrepareSeries(IOther);
  if ParentSeries.SeriesColor=clWhite then ParentSeries.SeriesColor:=clBlue;
  IOther.DataSource:=nil;
  IOther.DataSource:=ParentSeries;

  { calculate Histogram if Active... }
  if IHisto.Active then
  begin
    PrepareSeries(IHisto);
    IHisto.BeginUpdate;
    IHisto.Clear;
    With IOther do
    for t:=0 to Count-1 do
        IHisto.AddXY(IOther.XValues.Value[t],
                     ParentSeries.YValues.Value[t]-IOther.YValues.Value[t]);
    IHisto.EndUpdate;
  end;
end;

function TMACDFunction.GetPeriod2: Double;
begin
  result:=IMoving1.Period
end;

procedure TMACDFunction.SetPeriod2(const Value: Double);
begin
  if IMoving1.Period<>Value then
  begin
    IMoving1.Period:=Value;
    if IMoving1.Period<1 then IMoving1.Period:=1;
    Recalculate;
  end;
end;

function TMACDFunction.GetPeriod3: Integer;
begin
  result:=Round(IOther.FunctionType.Period);
end;

procedure TMACDFunction.SetPeriod3(const Value: Integer);
begin
  IOther.FunctionType.Period:=Value;
end;

function TMACDFunction.GetHistoPen: TChartPen;
begin
  result:=Histogram.Pen;
end;

function TMACDFunction.GetMACDExpPen: TChartPen;
begin
  result:=MACDExp.Pen;
end;

procedure TMACDFunction.SetHistoPen(const Value: TChartPen);
begin
  Histogram.Pen:=Value;
end;

procedure TMACDFunction.SetMACDExpPen(const Value: TChartPen);
begin
  MACDExp.Pen:=Value;
end;

function TMACDFunction.GetMACDPen: TChartPen;
begin
  result:=ParentSeries.Pen;
end;

procedure TMACDFunction.SetMACDPen(const Value: TChartPen);
begin
  ParentSeries.Pen:=Value;
end;

{ TExpMovAveFunction }
constructor TExpMovAveFunction.Create(AOwner: TComponent);
begin
  inherited;
  CanUsePeriod:=False;
  SingleSource:=True;
  InternalSetPeriod(10);
end;

procedure TExpMovAveFunction.AddPoints(Source: TChartSeries);
var tmpV : TChartValueList;
    Old  : Double;
    t    : Integer;
    tmp  : Double;
begin
  ParentSeries.Clear;
  if Period>0 then
  With Source do
  if Count>1 then
  begin
    tmpV:=ValueList(Source);
    tmp:=2/(Self.Period+1);
    Old:=tmpV.Value[0];
    ParentSeries.AddXY(NotMandatoryValueList.Value[0],Old);
    for t:=1 to Count-1 do
    begin
      Old:=(tmpV.Value[t]*tmp)+(Old*(1-tmp));
      ParentSeries.AddXY(NotMandatoryValueList.Value[t],Old);
    end;
  end;
end;

{ TBollingerFunction }
constructor TBollingerFunction.Create(AOwner: TComponent);
begin
  inherited;
  SingleSource:=True;
  Exponential:=True;
  Deviation:=2;
  IOther:=TFastLineSeries.Create(Self);
  IOther.ShowInLegend:=False;
  TChartSeriesAccess(IOther).InternalUse:=True;
  InternalSetPeriod(10);
end;

class function TBollingerFunction.GetEditorClass: String;
begin
  result:='TBollingerFuncEditor';
end;

procedure TBollingerFunction.AddPoints(Source:TChartSeries);
Var AList : TChartValueList;

  Function StdDev(First,Last:Integer):Double;
  var ISum  : Double;
      ISum2 : Double;
      tmp   : Double;
      t     : Integer;
  begin
    ISum:=0;
    ISum2:=0;
    for t:=First to Last do
    begin
      tmp:=AList.Value[t];
      ISum:=ISum+tmp;
      ISum2:=ISum2+Sqr(tmp);
    end;
    ISum:=((Period*ISum2) - Sqr(ISum)) / Sqr(Period);
    if ISum>0 then result:=Sqrt( ISum )
              else result:=0;  { 5.01  Negative square root not allowed }
  end;

  Procedure InternalAddPoints(ASeries:TChartSeries; const ADeviation:Double);
  var Mov       : TTeeFunction;
      tmp       : TChartSeries;
      tmpValue  : Double;
      tmpPeriod : Integer;
      t         : Integer;
      tmpSource : String;
  begin
    if Exponential then Mov:=TExpMovAveFunction.Create(nil)
                   else Mov:=TMovingAverageFunction.Create(nil);
    Mov.Period:=Period;

    tmp:=TChartSeries.Create(nil);
    try
      tmp.ParentChart:=Source.ParentChart;
      tmp.DataSource:=Source;
      tmpSource:=ParentSeries.MandatoryValueList.ValueSource;
      if tmpSource='' then tmpSource:=Source.MandatoryValueList.Name;
      tmp.MandatoryValueList.ValueSource:=tmpSource;
      tmp.SetFunction(Mov);

      ASeries.Clear;
      AList:=Source.GetYValueList(tmpSource);
      tmpPeriod:=Round(Period);
      for t:=tmpPeriod to Source.Count do
      begin
        tmpValue:=(ADeviation*StdDev(t-tmpPeriod,t-1));
        if Exponential then
           tmpValue:=tmp.YValues.Value[t-1]+tmpValue
        else
           tmpValue:=tmp.YValues.Value[t-tmpPeriod]+tmpValue;
        ASeries.AddXY(Source.XValues.Value[t-1],tmpValue);
      end;
      tmp.DataSource:=nil;
    finally
      tmp.Free;
    end;
  end;

begin
  With IOther do
  begin
    ParentChart:=ParentSeries.ParentChart;
    CustomVertAxis:=ParentSeries.CustomVertAxis;
    VertAxis:=ParentSeries.VertAxis;
    SeriesColor:=ParentSeries.SeriesColor;
    if ClassType=ParentSeries.ClassType then
       Pen.Assign(ParentSeries.Pen);
    XValues.DateTime:=ParentSeries.XValues.DateTime;
    AfterDrawValues:=ParentSeries.AfterDrawValues;
    BeforeDrawValues:=ParentSeries.BeforeDrawValues;
  end;

  if Period>0 then  // 5.03
  begin
    InternalAddPoints(ParentSeries,Deviation);
    InternalAddPoints(IOther,-Deviation);
  end;
end;

procedure TBollingerFunction.SetDeviation(const Value: Double);
begin
  if FDeviation<>Value then
  begin
    FDeviation:=Value;
    ReCalculate;
  end;
end;

procedure TBollingerFunction.SetExponential(const Value: Boolean);
begin
  if FExponential<>Value then
  begin
    FExponential:=Value;
    ReCalculate;
  end;
end;

destructor TBollingerFunction.Destroy;
begin
  IOther.Free;
  inherited;
end;

function TBollingerFunction.GetLowBandPen: TChartPen;
begin
  result:=LowBand.Pen;
end;

procedure TBollingerFunction.SetLowBandPen(const Value: TChartPen);
begin
  LowBand.Pen:=Value;
end;

function TBollingerFunction.GetUpperBandPen: TChartPen;
begin
  result:=ParentSeries.Pen;
end;

procedure TBollingerFunction.SetUpperBandPen(const Value: TChartPen);
begin
  ParentSeries.Pen:=Value;
end;

{ TCrossPointsFunction }
constructor TCrossPointsFunction.Create(AOwner: TComponent); // 6.0
begin
  inherited;
  CanUsePeriod:=False;
end;

procedure TCrossPointsFunction.AddPoints(Source: TChartSeries);
var tmp1   : TChartValueList;
    tmp2   : TChartValueList;
    tmpX1  : TChartValueList;
    tmpX2  : TChartValueList;

  Function LinesCross(index1,index2:Integer; var x,y:Double):Boolean;
  begin
    result:=CrossingLines(
                tmpX1.Value[index1],tmp1.Value[index1],
                tmpX1.Value[index1+1],tmp1.Value[index1+1],
                tmpX2.Value[index2],tmp2.Value[index2],
                tmpX2.Value[index2+1],tmp2.Value[index2+1],
                x,y
                );
  end;

var index1,
    index2 : Integer;
    x,
    y : Double;
begin
  if ParentSeries.DataSources.Count>1 then
  begin
    Source:=ParentSeries.DataSources[0];
    tmp1:=ValueList(Source);
    tmpX1:=Source.NotMandatoryValueList;
    tmp2:=ValueList(ParentSeries.DataSources[1]);
    tmpX2:=TChartSeries(ParentSeries.DataSources[1]).NotMandatoryValueList;

    ParentSeries.Clear;

    if (tmpX1.Count>1) and (tmpX2.Count>1) then
    begin
      index1:=0;
      index2:=0;

      repeat
        if LinesCross(index1,index2,x,y) then
           ParentSeries.AddXY(x,y);

        if tmpX2.Value[index2+1]<tmpX1.Value[index1+1] then
           Inc(Index2)
        else
           Inc(Index1);

      until (index1>=tmpX1.Count) or (index2>=tmpX2.Count);
    end;
  end;
end;

class function TCrossPointsFunction.GetEditorClass: String;
begin
  result:=''; // no options for this function
end;

{ TPerformanceFunction }
function TPerformanceFunction.Calculate(SourceSeries: TChartSeries;
  FirstIndex, LastIndex: Integer): Double;
begin
  if FirstIndex=TeeAllValues then LastIndex:=SourceSeries.Count-1;
  With ValueList(SourceSeries) do
  if Value[0]<>0 then
  begin
    result:=(Value[LastIndex]-Value[0])*100.0/Value[0];
  end
  else result:=0;
end;


initialization
  RegisterTeeFunction( TMovingAverageFunction, @TeeMsg_FunctionMovingAverage, @TeeMsg_GalleryFinancial );
  RegisterTeeFunction( TExpMovAveFunction,     @TeeMsg_FunctionExpMovAve, @TeeMsg_GalleryFinancial );
  RegisterTeeFunction( TExpAverageFunction,    @TeeMsg_FunctionExpAverage, @TeeMsg_GalleryExtended );
  RegisterTeeFunction( TMomentumFunction,      @TeeMsg_FunctionMomentum, @TeeMsg_GalleryFinancial  );
  RegisterTeeFunction( TMomentumDivFunction,   @TeeMsg_FunctionMomentumDiv, @TeeMsg_GalleryFinancial  );
  RegisterTeeFunction( TStdDeviationFunction,  @TeeMsg_FunctionStdDeviation, @TeeMsg_GalleryExtended  );
  RegisterTeeFunction( TRMSFunction,           @TeeMsg_FunctionRMS, @TeeMsg_GalleryExtended );
  RegisterTeeFunction( TMACDFunction,          @TeeMsg_FunctionMACD, @TeeMsg_GalleryFinancial  );
  RegisterTeeFunction( TStochasticFunction,    @TeeMsg_FunctionStochastic, @TeeMsg_GalleryFinancial  );
  RegisterTeeFunction( TBollingerFunction,     @TeeMsg_FunctionBollinger, @TeeMsg_GalleryFinancial );
  RegisterTeeFunction( TCrossPointsFunction,   @TeeMsg_FunctionCross, @TeeMsg_GalleryExtended );
  RegisterTeeFunction( TPerformanceFunction,   @TeeMsg_FunctionPerf, @TeeMsg_GalleryExtended );
  RegisterTeeSeries( THistogramSeries,@TeeMsg_GalleryHistogram,@TeeMsg_GalleryStats,1 );
finalization
  UnRegisterTeeFunctions([ TMovingAverageFunction,
                           TExpMovAveFunction,
                           TExpAverageFunction,
                           TMomentumFunction,
                           TMomentumDivFunction,
                           TStdDeviationFunction,
                           TRMSFunction,
                           TMACDFunction,
                           TStochasticFunction,
                           TBollingerFunction,
                           TCrossPointsFunction,
                           TPerformanceFunction ]);
  UnRegisterTeeSeries([THistogramSeries]);
end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?