extranet/includes/phpchartdir/FinanceChart.php

2180 lines
96 KiB
PHP
Raw Normal View History

2009-06-23 06:53:04 +00:00
<?php
require_once("../lib/phpchartdir.php");
#/////////////////////////////////////////////////////////////////////////////////////////////////
# Copyright 2006 Advanced Software Engineering Limited
#
# ChartDirector FinanceChart class library
# - Requires ChartDirector Ver 4.1 or above
#
# You may use and modify the code in this file in your application, provided the code and
# its modifications are used only in conjunction with ChartDirector. Usage of this software
# is subjected to the terms and condition of the ChartDirector license.
#/////////////////////////////////////////////////////////////////////////////////////////////////
#/ <summary>
#/ Represents a Financial Chart
#/ </summary>
class FinanceChart extends MultiChart
{
var $m_totalWidth = 0;
var $m_totalHeight = 0;
var $m_antiAlias = true;
var $m_logScale = false;
var $m_axisOnRight = true;
var $m_leftMargin = 40;
var $m_rightMargin = 40;
var $m_topMargin = 30;
var $m_bottomMargin = 35;
var $m_plotAreaBgColor = 0xfffff0;
var $m_majorHGridColor = 0xdddddd;
var $m_minorHGridColor = 0xdddddd;
var $m_majorVGridColor = 0xdddddd;
var $m_minorVGridColor = 0xdddddd;
var $m_legendFont = "normal";
var $m_legendFontSize = 8;
var $m_legendFontColor = TextColor;
var $m_legendBgColor = 0x80ccccff;
var $m_yAxisFont = "normal";
var $m_yAxisFontSize = 8;
var $m_yAxisFontColor = TextColor;
var $m_yAxisMargin = 13;
var $m_xAxisFont = "normal";
var $m_xAxisFontSize = 8;
var $m_xAxisFontColor = TextColor;
var $m_xAxisFontAngle = 0;
var $m_timeStamps = null;
var $m_highData = null;
var $m_lowData = null;
var $m_openData = null;
var $m_closeData = null;
var $m_volData = null;
var $m_volUnit = "";
var $m_extraPoints = 0;
var $m_yearFormat = "{value|yyyy}";
var $m_firstMonthFormat = "<*font=bold*>{value|mmm yy}";
var $m_otherMonthFormat = "{value|mmm}";
var $m_firstDayFormat = "<*font=bold*>{value|d mmm}";
var $m_otherDayFormat = "{value|d}";
var $m_firstHourFormat = "<*font=bold*>{value|d mmm\nh:nna}";
var $m_otherHourFormat = "{value|h:nna}";
var $m_timeLabelSpacing = 50;
var $m_generalFormat = "G";
var $m_toolTipMonthFormat = "[{xLabel|mmm yyyy}]";
var $m_toolTipDayFormat = "[{xLabel|mmm d, yyyy}]";
var $m_toolTipHourFormat = "[{xLabel|mmm d, yyyy hh:nn:ss}]";
var $m_mainChart = null;
var $m_currentChart = null;
#/ <summary>
#/ Create a FinanceChart with a given width. The height will be automatically determined
#/ as the chart is built.
#/ </summary>
#/ <param name="width">Width of the chart in pixels</param>
function FinanceChart($width) {
$this->MultiChart($width, 1);
$this->m_totalWidth = $width;
}
#/ <summary>
#/ Enable/Disable anti-alias. Enabling anti-alias makes the line smoother. Disabling
#/ anti-alias make the chart file size smaller, and so can be downloaded faster
#/ through the Internet. The default is to enable anti-alias.
#/ </summary>
#/ <param name="antiAlias">True to enable anti-alias. False to disable anti-alias.</param>
function enableAntiAlias($antiAlias) {
$this->m_antiAlias = $antiAlias;
}
#/ <summary>
#/ Set the margins around the plot area.
#/ </summary>
#/ <param name="m_leftMargin">The distance between the plot area and the chart left edge.</param>
#/ <param name="m_topMargin">The distance between the plot area and the chart top edge.</param>
#/ <param name="m_rightMargin">The distance between the plot area and the chart right edge.</param>
#/ <param name="m_bottomMargin">The distance between the plot area and the chart bottom edge.</param>
function setMargins($leftMargin, $topMargin, $rightMargin, $bottomMargin) {
$this->m_leftMargin = $leftMargin;
$this->m_rightMargin = $rightMargin;
$this->m_topMargin = $topMargin;
$this->m_bottomMargin = $bottomMargin;
}
#/ <summary>
#/ Add a text title above the plot area. You may add multiple title above the plot area by
#/ calling this method multiple times.
#/ </summary>
#/ <param name="alignment">The alignment with respect to the region that is on top of the
#/ plot area.</param>
#/ <param name="text">The text to add.</param>
#/ <returns>The TextBox object representing the text box above the plot area.</returns>
function addPlotAreaTitle($alignment, $text) {
$ret = $this->addText($this->m_leftMargin, 0, $text, "bold", 10, TextColor, $alignment);
$ret->setSize($this->m_totalWidth - $this->m_leftMargin - $this->m_rightMargin + 1,
$this->m_topMargin - 1);
$ret->setMargin(0);
return $ret;
}
#/ <summary>
#/ Set the plot area style. The default is to use pale yellow 0xfffff0 as the background,
#/ and light grey 0xdddddd as the grid lines.
#/ </summary>
#/ <param name="bgColor">The plot area background color.</param>
#/ <param name="majorHGridColor">Major horizontal grid color.</param>
#/ <param name="majorVGridColor">Major vertical grid color.</param>
#/ <param name="minorHGridColor">Minor horizontal grid color. In current version, minor
#/ horizontal grid is not used.</param>
#/ <param name="minorVGridColor">Minor vertical grid color.</param>
function setPlotAreaStyle($bgColor, $majorHGridColor, $majorVGridColor, $minorHGridColor,
$minorVGridColor) {
$this->m_plotAreaBgColor = $bgColor;
$this->m_majorHGridColor = $majorHGridColor;
$this->m_majorVGridColor = $majorVGridColor;
$this->m_minorHGridColor = $minorHGridColor;
$this->m_minorVGridColor = $minorVGridColor;
}
#/ <summary>
#/ Set legend style. The default is Arial 8 pt black color, with light grey background.
#/ </summary>
#/ <param name="font">The font of the legend text.</param>
#/ <param name="fontSize">The font size of the legend text in points.</param>
#/ <param name="fontColor">The color of the legend text.</param>
#/ <param name="bgColor">The background color of the legend box.</param>
function setLegendStyle($font, $fontSize, $fontColor, $bgColor) {
$this->m_legendFont = $font;
$this->m_legendFontSize = $fontSize;
$this->m_legendFontColor = $fontColor;
$this->m_legendBgColor = $bgColor;
}
#/ <summary>
#/ Set x-axis label style. The default is Arial 8 pt black color no rotation.
#/ </summary>
#/ <param name="font">The font of the axis labels.</param>
#/ <param name="fontSize">The font size of the axis labels in points.</param>
#/ <param name="fontColor">The color of the axis labels.</param>
#/ <param name="fontAngle">The rotation of the axis labels.</param>
function setXAxisStyle($font, $fontSize, $fontColor, $fontAngle) {
$this->m_xAxisFont = $font;
$this->m_xAxisFontSize = $fontSize;
$this->m_xAxisFontColor = $fontColor;
$this->m_xAxisFontAngle = $fontAngle;
}
#/ <summary>
#/ Set y-axis label style. The default is Arial 8 pt black color, with 13 pixels margin.
#/ </summary>
#/ <param name="font">The font of the axis labels.</param>
#/ <param name="fontSize">The font size of the axis labels in points.</param>
#/ <param name="fontColor">The color of the axis labels.</param>
#/ <param name="axisMargin">The margin at the top of the y-axis in pixels (to leave
#/ space for the legend box).</param>
function setYAxisStyle($font, $fontSize, $fontColor, $axisMargin) {
$this->m_yAxisFont = $font;
$this->m_yAxisFontSize = $fontSize;
$this->m_yAxisFontColor = $fontColor;
$this->m_yAxisMargin = $axisMargin;
}
#/ <summary>
#/ Set whether the main y-axis is on right of left side of the plot area. The default is
#/ on right.
#/ </summary>
#/ <param name="b">True if the y-axis is on right. False if the y-axis is on left.</param>
function setAxisOnRight($b) {
$this->m_axisOnRight = $b;
}
#/ <summary>
#/ Determines if log scale should be used for the main chart. The default is linear scale.
#/ </summary>
#/ <param name="b">True for using log scale. False for using linear scale.</param>
function setLogScale($b) {
$this->m_logScale = $b;
if ($this->m_mainChart != null) {
if ($this->m_logScale) {
$this->m_mainChart->yAxis->setLogScale();
} else {
$this->m_mainChart->yAxis->setLinearScale();
}
}
}
#/ <summary>
#/ Set the date/time formats to use for the x-axis labels under various cases.
#/ </summary>
#/ <param name="yearFormat">The format for displaying labels on an axis with yearly ticks. The
#/ default is "yyyy".</param>
#/ <param name="firstMonthFormat">The format for displaying labels on an axis with monthly ticks.
#/ This parameter applies to the first available month of a year (usually January) only, so it can
#/ be formatted differently from the other labels.</param>
#/ <param name="otherMonthFormat">The format for displaying labels on an axis with monthly ticks.
#/ This parameter applies to months other than the first available month of a year.</param>
#/ <param name="firstDayFormat">The format for displaying labels on an axis with daily ticks.
#/ This parameter applies to the first available day of a month only, so it can be formatted
#/ differently from the other labels.</param>
#/ <param name="otherDayFormat">The format for displaying labels on an axis with daily ticks.
#/ This parameter applies to days other than the first available day of a month.</param>
#/ <param name="firstHourFormat">The format for displaying labels on an axis with hourly
#/ resolution. This parameter applies to the first tick of a day only, so it can be formatted
#/ differently from the other labels.</param>
#/ <param name="otherHourFormat">The format for displaying labels on an axis with hourly.
#/ resolution. This parameter applies to ticks at hourly boundaries, except the first tick
#/ of a day.</param>
function setDateLabelFormat($yearFormat, $firstMonthFormat, $otherMonthFormat, $firstDayFormat,
$otherDayFormat, $firstHourFormat, $otherHourFormat) {
if ($yearFormat != null) {
$this->m_yearFormat = $yearFormat;
}
if ($firstMonthFormat != null) {
$this->m_firstMonthFormat = $firstMonthFormat;
}
if ($otherMonthFormat != null) {
$this->m_otherMonthFormat = $otherMonthFormat;
}
if ($firstDayFormat != null) {
$this->m_firstDayFormat = $firstDayFormat;
}
if ($otherDayFormat != null) {
$this->m_otherDayFormat = $otherDayFormat;
}
if ($firstHourFormat != null) {
$this->m_firstHourFormat = $firstHourFormat;
}
if ($otherHourFormat != null) {
$this->m_otherHourFormat = $otherHourFormat;
}
}
#/ <summary>
#/ Set the minimum label spacing between two labels on the time axis
#/ </summary>
#/ <param name="labelSpacing">The minimum label spacing in pixels.</param>
function setDateLabelSpacing($labelSpacing) {
if ($labelSpacing > 0) {
$this->m_timeLabelSpacing = $labelSpacing;
} else {
$this->m_timeLabelSpacing = 0;
}
}
#/ <summary>
#/ Set the tool tip formats for display date/time
#/ </summary>
#/ <param name="monthFormat">The tool tip format to use if the data point spacing is one
#/ or more months (more than 30 days).</param>
#/ <param name="dayFormat">The tool tip format to use if the data point spacing is 1 day
#/ to less than 30 days.</param>
#/ <param name="hourFormat">The tool tip format to use if the data point spacing is less
#/ than 1 day.</param>
function setToolTipDateFormat($monthFormat, $dayFormat, $hourFormat) {
if ($monthFormat != null) {
$this->m_toolTipMonthFormat = $monthFormat;
}
if ($dayFormat != null) {
$this->m_toolTipDayFormat = $dayFormat;
}
if ($hourFormat != null) {
$this->m_toolTipHourFormat = $hourFormat;
}
}
#/ <summary>
#/ Get the tool tip format for display date/time
#/ </summary>
#/ <returns>The tool tip format string.</returns>
function getToolTipDateFormat() {
if ($this->m_timeStamps == null) {
return $this->m_toolTipHourFormat;
}
if (count($this->m_timeStamps) <= $this->m_extraPoints) {
return $this->m_toolTipHourFormat;
}
$resolution = ($this->m_timeStamps[count($this->m_timeStamps) - 1] - $this->m_timeStamps[0])
/ count($this->m_timeStamps);
if ($resolution >= 30 * 86400) {
return $this->m_toolTipMonthFormat;
} else if ($resolution >= 86400) {
return $this->m_toolTipDayFormat;
} else {
return $this->m_toolTipHourFormat;
}
}
#/ <summary>
#/ Set the number format for use in displaying values in legend keys and tool tips.
#/ </summary>
#/ <param name="formatString">The default number format.</param>
function setNumberLabelFormat($formatString) {
if ($formatString != null) {
$this->m_generalFormat = $formatString;
}
}
#/ <summary>
#/ A utility function to compute triangular moving averages
#/ </summary>
#/ <param name="data">An array of numbers as input.</param>
#/ <param name="period">The moving average period.</param>
#/ <returns>An array representing the triangular moving average of the input array.</returns>
function computeTriMovingAvg($data, $period) {
$p = $period / 2 + 1;
$tmpArrayMath1 = new ArrayMath($data);
$tmpArrayMath1->movAvg($p);
$tmpArrayMath1->movAvg($p);
return $tmpArrayMath1->result();
}
#/ <summary>
#/ A utility function to compute weighted moving averages
#/ </summary>
#/ <param name="data">An array of numbers as input.</param>
#/ <param name="period">The moving average period.</param>
#/ <returns>An array representing the weighted moving average of the input array.</returns>
function computeWeightedMovingAvg($data, $period) {
$acc = new ArrayMath($data);
for($i = 2; $i < $period + 1; ++$i) {
$tmpArrayMath1 = new ArrayMath($data);
$tmpArrayMath1->movAvg($i);
$tmpArrayMath1->mul($i);
$acc->add($tmpArrayMath1->result());
}
$divObj = $acc->div((1 + $period) * $period / 2);
return $divObj->result();
}
#/ <summary>
#/ A utility function to obtain the last valid position (that is, position not
#/ containing cd.NoValue) of a data series.
#/ </summary>
#/ <param name="data">An array of numbers as input.</param>
#/ <returns>The last valid position in the input array, or -1 if all positions
#/ are cd.NoValue.</returns>
function lastIndex($data) {
$i = count($data) - 1;
while ($i >= 0) {
if ($data[$i] != NoValue) {
break;
}
$i = $i - 1;
}
return $i;
}
#/ <summary>
#/ Set the data used in the chart. If some of the data are not available, some artifical
#/ values should be used. For example, if the high and low values are not available, you
#/ may use closeData as highData and lowData.
#/ </summary>
#/ <param name="timeStamps">An array of dates/times for the time intervals.</param>
#/ <param name="highData">The high values in the time intervals.</param>
#/ <param name="lowData">The low values in the time intervals.</param>
#/ <param name="openData">The open values in the time intervals.</param>
#/ <param name="closeData">The close values in the time intervals.</param>
#/ <param name="volData">The volume values in the time intervals.</param>
#/ <param name="extraPoints">The number of leading time intervals that are not
#/ displayed in the chart. These intervals are typically used for computing
#/ indicators that require extra leading data, such as moving averages.</param>
function setData($timeStamps, $highData, $lowData, $openData, $closeData, $volData, $extraPoints
) {
$this->m_timeStamps = $timeStamps;
$this->m_highData = $highData;
$this->m_lowData = $lowData;
$this->m_openData = $openData;
$this->m_closeData = $closeData;
if ($extraPoints > 0) {
$this->m_extraPoints = $extraPoints;
} else {
$this->m_extraPoints = 0;
}
#///////////////////////////////////////////////////////////////////////
# Auto-detect volume units
#///////////////////////////////////////////////////////////////////////
$tmpArrayMath1 = new ArrayMath($volData);
$maxVol = $tmpArrayMath1->max();
$units = array("", "K", "M", "B");
$unitIndex = count($units) - 1;
while (($unitIndex > 0) && ($maxVol < pow(1000, $unitIndex))) {
$unitIndex = $unitIndex - 1;
}
$tmpArrayMath1 = new ArrayMath($volData);
$tmpArrayMath1->div(pow(1000, $unitIndex));
$this->m_volData = $tmpArrayMath1->result();
$this->m_volUnit = $units[$unitIndex];
}
#////////////////////////////////////////////////////////////////////////////
# Format x-axis labels
#////////////////////////////////////////////////////////////////////////////
function setXLabels(&$a) {
$a->setLabels2($this->m_timeStamps);
if ($this->m_extraPoints < count($this->m_timeStamps)) {
$tickStep = (int)((count($this->m_timeStamps) - $this->m_extraPoints) *
$this->m_timeLabelSpacing / ($this->m_totalWidth - $this->m_leftMargin -
$this->m_rightMargin)) + 1;
$timeRangeInSeconds = $this->m_timeStamps[count($this->m_timeStamps) - 1] -
$this->m_timeStamps[$this->m_extraPoints];
$secondsBetweenTicks = $timeRangeInSeconds / ($this->m_totalWidth - $this->m_leftMargin
- $this->m_rightMargin) * $this->m_timeLabelSpacing;
if ($secondsBetweenTicks * (count($this->m_timeStamps) - $this->m_extraPoints) <=
$timeRangeInSeconds) {
$tickStep = 1;
if (count($this->m_timeStamps) > 1) {
$secondsBetweenTicks = $this->m_timeStamps[count($this->m_timeStamps) - 1] -
$this->m_timeStamps[count($this->m_timeStamps) - 2];
} else {
$secondsBetweenTicks = 86400;
}
}
if (($secondsBetweenTicks > 360 * 86400) || (($secondsBetweenTicks > 90 * 86400) && (
$timeRangeInSeconds >= 720 * 86400))) {
#yearly ticks
$a->setMultiFormat2(StartOfYearFilter(), $this->m_yearFormat, $tickStep);
} else if (($secondsBetweenTicks >= 30 * 86400) || (($secondsBetweenTicks > 7 * 86400)
&& ($timeRangeInSeconds >= 60 * 86400))) {
#monthly ticks
$monthBetweenTicks = (int)($secondsBetweenTicks / 31 / 86400) + 1;
$a->setMultiFormat(StartOfYearFilter(), $this->m_firstMonthFormat,
StartOfMonthFilter($monthBetweenTicks), $this->m_otherMonthFormat);
$a->setMultiFormat2(StartOfMonthFilter(), "-", 1, false);
} else if (($secondsBetweenTicks >= 86400) || (($secondsBetweenTicks > 6 * 3600) && (
$timeRangeInSeconds >= 86400))) {
#daily ticks
$a->setMultiFormat(StartOfMonthFilter(), $this->m_firstDayFormat, StartOfDayFilter(
1, 0.5), $this->m_otherDayFormat, $tickStep);
} else {
#hourly ticks
$a->setMultiFormat(StartOfDayFilter(1, 0.5), $this->m_firstHourFormat,
StartOfHourFilter(1, 0.5), $this->m_otherHourFormat, $tickStep);
}
}
}
#////////////////////////////////////////////////////////////////////////////
# Create tool tip format string for showing OHLC data
#////////////////////////////////////////////////////////////////////////////
function getHLOCToolTipFormat() {
return sprintf("title='%s Op:{open|%s}, Hi:{high|%s}, Lo:{low|%s}, Cl:{close|%s}'",
$this->getToolTipDateFormat(), $this->m_generalFormat, $this->m_generalFormat,
$this->m_generalFormat, $this->m_generalFormat);
}
#/ <summary>
#/ Add the main chart - the chart that shows the HLOC data.
#/ </summary>
#/ <param name="height">The height of the main chart in pixels.</param>
#/ <returns>An XYChart object representing the main chart created.</returns>
function addMainChart($height) {
$this->m_mainChart = $this->addIndicator($height);
$this->setMainChart($this->m_mainChart);
$this->m_mainChart->yAxis->setMargin(2 * $this->m_yAxisMargin);
if ($this->m_logScale) {
$this->m_mainChart->yAxis->setLogScale();
} else {
$this->m_mainChart->yAxis->setLinearScale();
}
return $this->m_mainChart;
}
#/ <summary>
#/ Add a candlestick layer to the main chart.
#/ </summary>
#/ <param name="upColor">The candle color for an up day.</param>
#/ <param name="downColor">The candle color for a down day.</param>
#/ <returns>The CandleStickLayer created.</returns>
function addCandleStick($upColor, $downColor) {
$this->addOHLCLabel($upColor, $downColor, true);
$ret = $this->m_mainChart->addCandleStickLayer($this->m_highData, $this->m_lowData,
$this->m_openData, $this->m_closeData, $upColor, $downColor);
$ret->setHTMLImageMap("", "", $this->getHLOCToolTipFormat());
if (count($this->m_highData) - $this->m_extraPoints > 60) {
$ret->setDataGap(0);
}
if (count($this->m_highData) > $this->m_extraPoints) {
$expectedWidth = ($this->m_totalWidth - $this->m_leftMargin - $this->m_rightMargin) / (
count($this->m_highData) - $this->m_extraPoints);
if ($expectedWidth <= 5) {
$ret->setDataWidth($expectedWidth + 1 - $expectedWidth % 2);
}
}
return $ret;
}
#/ <summary>
#/ Add a HLOC layer to the main chart.
#/ </summary>
#/ <param name="upColor">The color of the HLOC symbol for an up day.</param>
#/ <param name="downColor">The color of the HLOC symbol for a down day.</param>
#/ <returns>The HLOCLayer created.</returns>
function addHLOC($upColor, $downColor) {
$this->addOHLCLabel($upColor, $downColor, false);
$ret = $this->m_mainChart->addHLOCLayer($this->m_highData, $this->m_lowData,
$this->m_openData, $this->m_closeData);
$ret->setColorMethod(HLOCUpDown, $upColor, $downColor);
$ret->setHTMLImageMap("", "", $this->getHLOCToolTipFormat());
$ret->setDataGap(0);
return $ret;
}
function addOHLCLabel($upColor, $downColor, $candleStickMode) {
$i = $this->lastIndex($this->m_closeData);
if ($i >= 0) {
$openValue = NoValue;
$closeValue = NoValue;
$highValue = NoValue;
$lowValue = NoValue;
if ($i < count($this->m_openData)) {
$openValue = $this->m_openData[$i];
}
if ($i < count($this->m_closeData)) {
$closeValue = $this->m_closeData[$i];
}
if ($i < count($this->m_highData)) {
$highValue = $this->m_highData[$i];
}
if ($i < count($this->m_lowData)) {
$lowValue = $this->m_lowData[$i];
}
$openLabel = "";
$closeLabel = "";
$highLabel = "";
$lowLabel = "";
$delim = "";
if ($openValue != NoValue) {
$openLabel = sprintf("Op:%s", $this->formatValue($openValue, $this->m_generalFormat)
);
$delim = ", ";
}
if ($highValue != NoValue) {
$highLabel = sprintf("%sHi:%s", $delim, $this->formatValue($highValue,
$this->m_generalFormat));
$delim = ", ";
}
if ($lowValue != NoValue) {
$lowLabel = sprintf("%sLo:%s", $delim, $this->formatValue($lowValue,
$this->m_generalFormat));
$delim = ", ";
}
if ($closeValue != NoValue) {
$closeLabel = sprintf("%sCl:%s", $delim, $this->formatValue($closeValue,
$this->m_generalFormat));
$delim = ", ";
}
$label = "$openLabel$highLabel$lowLabel$closeLabel";
$useUpColor = ($closeValue >= $openValue);
if ($candleStickMode != true) {
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->delta();
$closeChanges = $tmpArrayMath1->result();
$lastChangeIndex = $this->lastIndex($closeChanges);
$useUpColor = ($lastChangeIndex < 0);
if ($useUpColor != true) {
$useUpColor = ($closeChanges[$lastChangeIndex] >= 0);
}
}
$udcolor = $downColor;
if ($useUpColor) {
$udcolor = $upColor;
}
$legendObj = $this->m_mainChart->getLegend();
$legendObj->addKey($label, $udcolor);
}
}
#/ <summary>
#/ Add a closing price line on the main chart.
#/ </summary>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addCloseLine($color) {
return $this->addLineIndicator2($this->m_mainChart, $this->m_closeData, $color,
"Closing Price");
}
#/ <summary>
#/ Add a weight close line on the main chart.
#/ </summary>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addWeightedClose($color) {
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->add($this->m_lowData);
$tmpArrayMath1->add($this->m_closeData);
$tmpArrayMath1->add($this->m_closeData);
$tmpArrayMath1->div(4);
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color,
"Weighted Close");
}
#/ <summary>
#/ Add a typical price line on the main chart.
#/ </summary>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addTypicalPrice($color) {
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->add($this->m_lowData);
$tmpArrayMath1->add($this->m_closeData);
$tmpArrayMath1->div(3);
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color,
"Typical Price");
}
#/ <summary>
#/ Add a median price line on the main chart.
#/ </summary>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addMedianPrice($color) {
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->add($this->m_lowData);
$tmpArrayMath1->div(2);
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color,
"Median Price");
}
#/ <summary>
#/ Add a simple moving average line on the main chart.
#/ </summary>
#/ <param name="period">The moving average period</param>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addSimpleMovingAvg($period, $color) {
$label = "SMA ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movAvg($period);
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color, $label
);
}
#/ <summary>
#/ Add an exponential moving average line on the main chart.
#/ </summary>
#/ <param name="period">The moving average period</param>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addExpMovingAvg($period, $color) {
$label = "EMA ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->expAvg(2.0 / ($period + 1));
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color, $label
);
}
#/ <summary>
#/ Add a triangular moving average line on the main chart.
#/ </summary>
#/ <param name="period">The moving average period</param>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addTriMovingAvg($period, $color) {
$label = "TMA ($period)";
$tmpArrayMath1 = new ArrayMath($this->computeTriMovingAvg($this->m_closeData, $period));
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color, $label
);
}
#/ <summary>
#/ Add a weighted moving average line on the main chart.
#/ </summary>
#/ <param name="period">The moving average period</param>
#/ <param name="color">The color of the line.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addWeightedMovingAvg($period, $color) {
$label = "WMA ($period)";
$tmpArrayMath1 = new ArrayMath($this->computeWeightedMovingAvg($this->m_closeData, $period))
;
return $this->addLineIndicator2($this->m_mainChart, $tmpArrayMath1->result(), $color, $label
);
}
#/ <summary>
#/ Add a generic band to the main finance chart. This method is used internally by other methods to add
#/ various bands (eg. Bollinger band, Donchian channels, etc).
#/ </summary>
#/ <param name="upperLine">The data series for the upper band line.</param>
#/ <param name="lowerLine">The data series for the lower band line.</param>
#/ <param name="lineColor">The color of the upper and lower band line.</param>
#/ <param name="fillColor">The color to fill the region between the upper and lower band lines.</param>
#/ <param name="name">The name of the band.</param>
#/ <returns>An InterLineLayer object representing the filled region.</returns>
function addBand($upperLine, $lowerLine, $lineColor, $fillColor, $name) {
$i = count($upperLine) - 1;
if ($i >= count($lowerLine)) {
$i = count($lowerLine) - 1;
}
while ($i >= 0) {
if (($upperLine[$i] != NoValue) && ($lowerLine[$i] != NoValue)) {
$name = sprintf("%s: %s - %s", $name, $this->formatValue($lowerLine[$i],
$this->m_generalFormat), $this->formatValue($upperLine[$i],
$this->m_generalFormat));
break;
}
$i = $i - 1;
}
$uLayer = $this->m_mainChart->addLineLayer($upperLine, $lineColor, $name);
$lLayer = $this->m_mainChart->addLineLayer($lowerLine, $lineColor);
return $this->m_mainChart->addInterLineLayer($uLayer->getLine(), $lLayer->getLine(),
$fillColor);
}
#/ <summary>
#/ Add a Bollinger band on the main chart.
#/ </summary>
#/ <param name="period">The period to compute the band.</param>
#/ <param name="bandWidth">The half-width of the band in terms multiples of standard deviation. Typically 2 is used.</param>
#/ <param name="lineColor">The color of the lines defining the upper and lower limits.</param>
#/ <param name="fillColor">The color to fill the regional within the band.</param>
#/ <returns>The InterLineLayer object representing the band created.</returns>
function addBollingerBand($period, $bandWidth, $lineColor, $fillColor) {
#Bollinger Band is moving avg +/- (width * moving std deviation)
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movStdDev($period);
$tmpArrayMath1->mul($bandWidth);
$stdDev = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movAvg($period);
$movAvg = $tmpArrayMath1->result();
$label = "Bollinger ($period, $bandWidth)";
$tmpArrayMath1 = new ArrayMath($movAvg);
$tmpArrayMath1->add($stdDev);
$tmpArrayMath2 = new ArrayMath($movAvg);
$tmpArrayMath2->sub($stdDev);
$tmpArrayMath2->selectGTZ(null, 0);
return $this->addBand($tmpArrayMath1->result(), $tmpArrayMath2->result(), $lineColor,
$fillColor, $label);
}
#/ <summary>
#/ Add a Donchian channel on the main chart.
#/ </summary>
#/ <param name="period">The period to compute the band.</param>
#/ <param name="lineColor">The color of the lines defining the upper and lower limits.</param>
#/ <param name="fillColor">The color to fill the regional within the band.</param>
#/ <returns>The InterLineLayer object representing the band created.</returns>
function addDonchianChannel($period, $lineColor, $fillColor) {
#Donchian Channel is the zone between the moving max and moving min
$label = "Donchian ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->movMax($period);
$tmpArrayMath2 = new ArrayMath($this->m_lowData);
$tmpArrayMath2->movMin($period);
return $this->addBand($tmpArrayMath1->result(), $tmpArrayMath2->result(), $lineColor,
$fillColor, $label);
}
#/ <summary>
#/ Add a price envelop on the main chart. The price envelop is a defined as a ratio around a
#/ moving average. For example, a ratio of 0.2 means 20% above and below the moving average.
#/ </summary>
#/ <param name="period">The period for the moving average.</param>
#/ <param name="range">The ratio above and below the moving average.</param>
#/ <param name="lineColor">The color of the lines defining the upper and lower limits.</param>
#/ <param name="fillColor">The color to fill the regional within the band.</param>
#/ <returns>The InterLineLayer object representing the band created.</returns>
function addEnvelop($period, $range, $lineColor, $fillColor) {
#Envelop is moving avg +/- percentage
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movAvg($period);
$movAvg = $tmpArrayMath1->result();
$label = sprintf("Envelop (SMA %s +/- %s%%)", $period, (int)($range * 100));
$tmpArrayMath1 = new ArrayMath($movAvg);
$tmpArrayMath1->mul(1 + $range);
$tmpArrayMath2 = new ArrayMath($movAvg);
$tmpArrayMath2->mul(1 - $range);
return $this->addBand($tmpArrayMath1->result(), $tmpArrayMath2->result(), $lineColor,
$fillColor, $label);
}
#/ <summary>
#/ Add a volume bar chart layer on the main chart.
#/ </summary>
#/ <param name="height">The height of the bar chart layer in pixels.</param>
#/ <param name="upColor">The color to used on an 'up' day. An 'up' day is a day where
#/ the closing price is higher than that of the previous day.</param>
#/ <param name="downColor">The color to used on a 'down' day. A 'down' day is a day
#/ where the closing price is lower than that of the previous day.</param>
#/ <param name="flatColor">The color to used on a 'flat' day. A 'flat' day is a day
#/ where the closing price is the same as that of the previous day.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addVolBars($height, $upColor, $downColor, $flatColor) {
return $this->addVolBars2($this->m_mainChart, $height, $upColor, $downColor, $flatColor);
}
function addVolBars2(&$c, $height, $upColor, $downColor, $flatColor) {
#Compute an array to represent the closing price changes
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->delta();
$closeChange = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->selectGTZ($closeChange);
$upLayer = $this->addBarIndicator2($c, $tmpArrayMath1->result(), $upColor, "");
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->selectLTZ($closeChange);
$dnLayer = $this->addBarIndicator2($c, $tmpArrayMath1->result(), $downColor, "");
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->selectEQZ($closeChange);
$flatLayer = $this->addBarIndicator2($c, $tmpArrayMath1->result(), $flatColor, "");
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$maxVol = $tmpArrayMath1->max();
if ($c == $this->m_mainChart) {
$res_yAxis2=$c->yAxis2();
$this->configureYAxis($res_yAxis2, $height);
$drawAreaObj = $c->getDrawArea();
$topMargin = $drawAreaObj->getHeight() - $this->m_topMargin - $this->m_bottomMargin -
$height + $this->m_yAxisMargin;
if ($topMargin < 0) {
$topMargin = 0;
}
$c->yAxis2->setTopMargin($topMargin);
$upLayer->setUseYAxis2();
$dnLayer->setUseYAxis2();
$flatLayer->setUseYAxis2();
}
$a = $c->yAxis2;
if ($c != $this->m_mainChart) {
$a = $c->yAxis;
}
$volFormat = "";
if ($maxVol < 10) {
$volFormat = sprintf("{value|1}%s", $this->m_volUnit);
} else {
$volFormat = sprintf("{value}%s", $this->m_volUnit);
}
$a->setLabelFormat($volFormat);
$i = $this->lastIndex($this->m_volData);
$label = "Vol";
if ($i >= 0) {
$label = sprintf("Vol: %s%s", $this->formatValue($this->m_volData[$i],
$this->m_generalFormat), $this->m_volUnit);
}
$selectedLayer = null;
if (($i < 0) || ($closeChange[$i] == 0) || ($closeChange[$i] == NoValue)) {
$selectedLayer = $flatLayer;
} else if ($closeChange[$i] > 0) {
$selectedLayer = $upLayer;
} else {
$selectedLayer = $dnLayer;
}
$dataSetObj = $selectedLayer->getDataSet(0);
$dataSetObj->setDataName($label);
return $selectedLayer;
}
#/ <summary>
#/ Add a blank indicator chart to the finance chart. Used internally to add other indicators.
#/ Override to change the default formatting (eg. axis fonts, etc.) of the various indicators.
#/ </summary>
#/ <param name="height">The height of the chart in pixels.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addIndicator($height) {
#create a new chart object
$ret = new XYChart($this->m_totalWidth, $height + $this->m_topMargin +
$this->m_bottomMargin, Transparent);
$ret->setTrimData($this->m_extraPoints);
if ($this->m_currentChart != null) {
#if there is a chart before the newly created chart, disable its x-axis, and copy
#its x-axis labels to the new chart
$this->m_currentChart->xAxis->setColors(LineColor, Transparent);
$ret->xAxis->copyAxis($this->m_currentChart->xAxis());
} else {
#no existing chart - create the x-axis labels from scratch
$res_xAxis=$ret->xAxis();
$this->setXLabels($res_xAxis);
}
#the newly created chart becomes the current chart
$this->m_currentChart = $ret;
#add chart to MultiChart and update the total height
$this->addChart(0, $this->m_totalHeight, $ret);
$this->m_totalHeight = $this->m_totalHeight + $height + 1;
$this->setSize($this->m_totalWidth, $this->m_totalHeight + $this->m_topMargin +
$this->m_bottomMargin);
#configure the plot area
$plotAreaObj = $ret->setPlotArea($this->m_leftMargin, $this->m_topMargin,
$this->m_totalWidth - $this->m_leftMargin - $this->m_rightMargin, $height,
$this->m_plotAreaBgColor);
$plotAreaObj->setGridColor($this->m_majorHGridColor, $this->m_majorVGridColor,
$this->m_minorHGridColor, $this->m_minorVGridColor);
$ret->setAntiAlias($this->m_antiAlias);
#configure legend box
$box = $ret->addLegend($this->m_leftMargin, $this->m_topMargin, false, $this->m_legendFont,
$this->m_legendFontSize);
$box->setBackground($this->m_legendBgColor);
$box->setMargin2(5, 0, 2, 0);
$box->setSize($this->m_totalWidth - $this->m_leftMargin - $this->m_rightMargin, 0);
#configure x-axis
$a = $ret->xAxis;
$a->setIndent(true);
$a->setTickLength(2, 0);
$a->setLabelStyle($this->m_xAxisFont, $this->m_xAxisFontSize, $this->m_xAxisFontColor,
$this->m_xAxisFontAngle);
#configure y-axis
$ret->setYAxisOnRight($this->m_axisOnRight);
$res_yAxis=$ret->yAxis();
$this->configureYAxis($res_yAxis, $height);
return $ret;
}
function configureYAxis(&$a, $height) {
$a->setAutoScale(0, 0.05, 0);
if ($height < 100) {
$a->setTickDensity(15);
}
$a->setMargin($this->m_yAxisMargin);
$a->setLabelStyle($this->m_yAxisFont, $this->m_yAxisFontSize, $this->m_yAxisFontColor, 0);
$a->setTickLength(-4, -2);
}
#/ <summary>
#/ Add a generic line indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="data">The data series of the indicator line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="name">The name of the indicator.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addLineIndicator($height, $data, $color, $name) {
$c = $this->addIndicator($height);
$this->addLineIndicator2($c, $data, $color, $name);
return $c;
}
#/ <summary>
#/ Add a line to an existing indicator chart.
#/ </summary>
#/ <param name="c">The indicator chart to add the line to.</param>
#/ <param name="data">The data series of the indicator line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="name">The name of the indicator.</param>
#/ <returns>The LineLayer object representing the line created.</returns>
function addLineIndicator2(&$c, $data, $color, $name) {
return $c->addLineLayer($data, $color, $this->formatIndicatorLabel($name, $data));
}
#/ <summary>
#/ Add a generic bar indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="data">The data series of the indicator bars.</param>
#/ <param name="color">The color of the indicator bars.</param>
#/ <param name="name">The name of the indicator.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addBarIndicator($height, $data, $color, $name) {
$c = $this->addIndicator($height);
$this->addBarIndicator2($c, $data, $color, $name);
return $c;
}
#/ <summary>
#/ Add a bar layer to an existing indicator chart.
#/ </summary>
#/ <param name="c">The indicator chart to add the bar layer to.</param>
#/ <param name="data">The data series of the indicator bars.</param>
#/ <param name="color">The color of the indicator bars.</param>
#/ <param name="name">The name of the indicator.</param>
#/ <returns>The BarLayer object representing the bar layer created.</returns>
function addBarIndicator2(&$c, $data, $color, $name) {
$layer = $c->addBarLayer($data, $color, $this->formatIndicatorLabel($name, $data));
$layer->setBorderColor(Transparent);
return $layer;
}
#/ <summary>
#/ Add an upper/lower threshold range to an existing indicator chart.
#/ </summary>
#/ <param name="c">The indicator chart to add the threshold range to.</param>
#/ <param name="layer">The line layer that the threshold range applies to.</param>
#/ <param name="topRange">The upper threshold.</param>
#/ <param name="topColor">The color to fill the region of the line that is above the
#/ upper threshold.</param>
#/ <param name="bottomRange">The lower threshold.</param>
#/ <param name="bottomColor">The color to fill the region of the line that is below
#/ the lower threshold.</param>
function addThreshold(&$c, &$layer, $topRange, $topColor, $bottomRange, $bottomColor) {
$topMark = $c->yAxis->addMark($topRange, $topColor, $this->formatValue($topRange,
$this->m_generalFormat));
$bottomMark = $c->yAxis->addMark($bottomRange, $bottomColor, $this->formatValue(
$bottomRange, $this->m_generalFormat));
$c->addInterLineLayer($layer->getLine(), $topMark->getLine(), $topColor, Transparent);
$c->addInterLineLayer($layer->getLine(), $bottomMark->getLine(), Transparent, $bottomColor);
}
function formatIndicatorLabel($name, $data) {
$i = $this->lastIndex($data);
if ($name == null) {
return $name;
}
if (($name == "") || ($i < 0)) {
return $name;
}
$ret = sprintf("%s: %s", $name, $this->formatValue($data[$i], $this->m_generalFormat));
return $ret;
}
#/ <summary>
#/ Add an Accumulation/Distribution indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addAccDist($height, $color) {
#Close Location Value = ((C - L) - (H - C)) / (H - L)
#Accumulation Distribution Line = Accumulation of CLV * volume
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$range = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->mul(2);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->sub($this->m_highData);
$tmpArrayMath1->mul($this->m_volData);
$tmpArrayMath1->financeDiv($range, 0);
$tmpArrayMath1->acc();
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color,
"Accumulation/Distribution");
}
function computeAroonUp($period) {
$aroonUp = array_pad(array(), count($this->m_highData), 0);
for($i = 0; $i < count($this->m_highData); ++$i) {
$highValue = $this->m_highData[$i];
if ($highValue == NoValue) {
$aroonUp[$i] = NoValue;
} else {
$currentIndex = $i;
$highCount = $period;
$count = $period;
while (($count > 0) && ($currentIndex >= $count)) {
$currentIndex = $currentIndex - 1;
$currentValue = $this->m_highData[$currentIndex];
if ($currentValue != NoValue) {
$count = $count - 1;
if ($currentValue > $highValue) {
$highValue = $currentValue;
$highCount = $count;
}
}
}
if ($count > 0) {
$aroonUp[$i] = NoValue;
} else {
$aroonUp[$i] = $highCount * 100.0 / $period;
}
}
}
return $aroonUp;
}
function computeAroonDn($period) {
$aroonDn = array_pad(array(), count($this->m_lowData), 0);
for($i = 0; $i < count($this->m_lowData); ++$i) {
$lowValue = $this->m_lowData[$i];
if ($lowValue == NoValue) {
$aroonDn[$i] = NoValue;
} else {
$currentIndex = $i;
$lowCount = $period;
$count = $period;
while (($count > 0) && ($currentIndex >= $count)) {
$currentIndex = $currentIndex - 1;
$currentValue = $this->m_lowData[$currentIndex];
if ($currentValue != NoValue) {
$count = $count - 1;
if ($currentValue < $lowValue) {
$lowValue = $currentValue;
$lowCount = $count;
}
}
}
if ($count > 0) {
$aroonDn[$i] = NoValue;
} else {
$aroonDn[$i] = $lowCount * 100.0 / $period;
}
}
}
return $aroonDn;
}
#/ <summary>
#/ Add an Aroon Up/Down indicators chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicators.</param>
#/ <param name="upColor">The color of the Aroon Up indicator line.</param>
#/ <param name="downColor">The color of the Aroon Down indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addAroon($height, $period, $upColor, $downColor) {
$c = $this->addIndicator($height);
$this->addLineIndicator2($c, $this->computeAroonUp($period), $upColor, "Aroon Up");
$this->addLineIndicator2($c, $this->computeAroonDn($period), $downColor, "Aroon Down");
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add an Aroon Oscillator indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addAroonOsc($height, $period, $color) {
$label = "Aroon Oscillator ($period)";
$tmpArrayMath1 = new ArrayMath($this->computeAroonUp($period));
$tmpArrayMath1->sub($this->computeAroonDn($period));
$c = $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
$c->yAxis->setLinearScale(-100, 100);
return $c;
}
function computeTrueRange() {
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->shift();
$previousClose = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$ret = $tmpArrayMath1->result();
$temp = 0;
for($i = 0; $i < count($this->m_highData); ++$i) {
if (($ret[$i] != NoValue) && ($previousClose[$i] != NoValue)) {
$temp = abs($this->m_highData[$i] - $previousClose[$i]);
if ($temp > $ret[$i]) {
$ret[$i] = $temp;
}
$temp = abs($previousClose[$i] - $this->m_lowData[$i]);
if ($temp > $ret[$i]) {
$ret[$i] = $temp;
}
}
}
return $ret;
}
#/ <summary>
#/ Add an Average Directional Index indicators chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="posColor">The color of the Positive Directional Index line.</param>
#/ <param name="negColor">The color of the Negatuve Directional Index line.</param>
#/ <param name="color">The color of the Average Directional Index line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addADX($height, $period, $posColor, $negColor, $color) {
#pos/neg directional movement
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->delta();
$pos = $tmpArrayMath1->selectGTZ();
$tmpArrayMath1 = new ArrayMath($this->m_lowData);
$tmpArrayMath1->delta();
$tmpArrayMath1->mul(-1);
$neg = $tmpArrayMath1->selectGTZ();
$tmpArrayMath1 = new ArrayMath($pos->result());
$tmpArrayMath1->sub($neg->result());
$delta = $tmpArrayMath1->result();
$pos->selectGTZ($delta);
$neg->selectLTZ($delta);
#pos/neg directional index
$tr = $this->computeTrueRange();
$financeDivObj = $pos->financeDiv($tr, 0.25);
$mulObj = $financeDivObj->mul(100);
$mulObj->expAvg(2.0 / ($period + 1));
$financeDivObj = $neg->financeDiv($tr, 0.25);
$mulObj = $financeDivObj->mul(100);
$mulObj->expAvg(2.0 / ($period + 1));
#directional movement index ??? what happen if division by zero???
$tmpArrayMath1 = new ArrayMath($pos->result());
$tmpArrayMath1->add($neg->result());
$totalDM = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($pos->result());
$tmpArrayMath1->sub($neg->result());
$tmpArrayMath1->abs();
$tmpArrayMath1->financeDiv($totalDM, 0);
$tmpArrayMath1->mul(100);
$dx = $tmpArrayMath1->expAvg(2.0 / ($period + 1));
$c = $this->addIndicator($height);
$label1 = "+DI ($period)";
$label2 = "-DI ($period)";
$label3 = "ADX ($period)";
$this->addLineIndicator2($c, $pos->result(), $posColor, $label1);
$this->addLineIndicator2($c, $neg->result(), $negColor, $label2);
$this->addLineIndicator2($c, $dx->result(), $color, $label3);
return $c;
}
#/ <summary>
#/ Add an Average True Range indicators chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color1">The color of the True Range line.</param>
#/ <param name="color2">The color of the Average True Range line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addATR($height, $period, $color1, $color2) {
$trueRange = $this->computeTrueRange();
$c = $this->addLineIndicator($height, $trueRange, $color1, "True Range");
$label = "Average True Range ($period)";
$tmpArrayMath1 = new ArrayMath($trueRange);
$tmpArrayMath1->expAvg(2.0 / ($period + 1));
$this->addLineIndicator2($c, $tmpArrayMath1->result(), $color2, $label);
return $c;
}
#/ <summary>
#/ Add a Bollinger Band Width indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="width">The band width to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addBollingerWidth($height, $period, $width, $color) {
$label = "Bollinger Width ($period, $width)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movStdDev($period);
$tmpArrayMath1->mul($width * 2);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Community Channel Index indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="range">The distance beween the middle line and the upper and lower threshold lines.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addCCI($height, $period, $color, $range, $upColor, $downColor) {
#typical price
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->add($this->m_lowData);
$tmpArrayMath1->add($this->m_closeData);
$tmpArrayMath1->div(3);
$tp = $tmpArrayMath1->result();
#simple moving average of typical price
$tmpArrayMath1 = new ArrayMath($tp);
$tmpArrayMath1->movAvg($period);
$smvtp = $tmpArrayMath1->result();
#compute mean deviation
$movMeanDev = array_pad(array(), count($smvtp), 0);
for($i = 0; $i < count($smvtp); ++$i) {
$avg = $smvtp[$i];
if ($avg == NoValue) {
$movMeanDev[$i] = NoValue;
} else {
$currentIndex = $i;
$count = $period - 1;
$acc = 0;
while (($count > 0) && ($currentIndex >= $count)) {
$currentIndex = $currentIndex - 1;
$currentValue = $tp[$currentIndex];
if ($currentValue != NoValue) {
$count = $count - 1;
$acc = $acc + abs($avg - $currentValue);
}
}
if ($count > 0) {
$movMeanDev[$i] = NoValue;
} else {
$movMeanDev[$i] = $acc / $period;
}
}
}
$c = $this->addIndicator($height);
$label = "CCI ($period)";
$tmpArrayMath1 = new ArrayMath($tp);
$tmpArrayMath1->sub($smvtp);
$tmpArrayMath1->financeDiv($movMeanDev, 0);
$tmpArrayMath1->div(0.015);
$layer = $this->addLineIndicator2($c, $tmpArrayMath1->result(), $color, $label);
$this->addThreshold($c, $layer, $range, $upColor, -$range, $downColor);
return $c;
}
#/ <summary>
#/ Add a Chaikin Money Flow indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addChaikinMoneyFlow($height, $period, $color) {
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$range = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->movAvg($period);
$volAvg = $tmpArrayMath1->result();
$label = "Chaikin Money Flow ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->mul(2);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->sub($this->m_highData);
$tmpArrayMath1->mul($this->m_volData);
$tmpArrayMath1->financeDiv($range, 0);
$tmpArrayMath1->movAvg($period);
$tmpArrayMath1->financeDiv($volAvg, 0);
return $this->addBarIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Chaikin Oscillator indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addChaikinOscillator($height, $color) {
#first compute acc/dist line
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$range = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->mul(2);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->sub($this->m_highData);
$tmpArrayMath1->mul($this->m_volData);
$tmpArrayMath1->financeDiv($range, 0);
$tmpArrayMath1->acc();
$accdist = $tmpArrayMath1->result();
#chaikin osc = exp3(accdist) - exp10(accdist)
$tmpArrayMath1 = new ArrayMath($accdist);
$tmpArrayMath1->expAvg(2.0 / (11));
$expAvg10 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($accdist);
$tmpArrayMath1->expAvg(2.0 / (4));
$tmpArrayMath1->sub($expAvg10);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color,
"Chaikin Oscillator");
}
#/ <summary>
#/ Add a Chaikin Volatility indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The period to smooth the range.</param>
#/ <param name="period2">The period to compute the rate of change of the smoothed range.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addChaikinVolatility($height, $period1, $period2, $color) {
$label = "Chaikin Volatility ($period1, $period2)";
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->expAvg(2.0 / ($period1 + 1));
$tmpArrayMath1->rate($period2);
$tmpArrayMath1->sub(1);
$tmpArrayMath1->mul(100);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Close Location Value indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addCLV($height, $color) {
#Close Location Value = ((C - L) - (H - C)) / (H - L)
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$range = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->mul(2);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->sub($this->m_highData);
$tmpArrayMath1->financeDiv($range, 0);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color,
"Close Location Value");
}
#/ <summary>
#/ Add a Detrended Price Oscillator indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addDPO($height, $period, $color) {
$label = "DPO ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movAvg($period);
$tmpArrayMath1->shift($period / 2 + 1);
$tmpArrayMath1->sub($this->m_closeData);
$tmpArrayMath1->mul(-1);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Donchian Channel Width indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addDonchianWidth($height, $period, $color) {
$label = "Donchian Width ($period)";
$tmpArrayMath2 = new ArrayMath($this->m_lowData);
$tmpArrayMath2->movMin($period);
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->movMax($period);
$tmpArrayMath1->sub($tmpArrayMath2->result());
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Ease of Movement indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to smooth the indicator.</param>
#/ <param name="color1">The color of the indicator line.</param>
#/ <param name="color2">The color of the smoothed indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addEaseOfMovement($height, $period, $color1, $color2) {
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->financeDiv($this->m_volData, 0);
$boxRatioInverted = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->add($this->m_lowData);
$tmpArrayMath1->div(2);
$tmpArrayMath1->delta();
$tmpArrayMath1->mul($boxRatioInverted);
$result = $tmpArrayMath1->result();
$c = $this->addLineIndicator($height, $result, $color1, "EMV");
$label = "EMV EMA ($period)";
$tmpArrayMath1 = new ArrayMath($result);
$tmpArrayMath1->movAvg($period);
$this->addLineIndicator2($c, $tmpArrayMath1->result(), $color2, $label);
return $c;
}
#/ <summary>
#/ Add a Fast Stochastic indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The period to compute the %K line.</param>
#/ <param name="period2">The period to compute the %D line.</param>
#/ <param name="color1">The color of the %K line.</param>
#/ <param name="color2">The color of the %D line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addFastStochastic($height, $period1, $period2, $color1, $color2) {
$tmpArrayMath1 = new ArrayMath($this->m_lowData);
$tmpArrayMath1->movMin($period1);
$movLow = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->movMax($period1);
$tmpArrayMath1->sub($movLow);
$movRange = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->sub($movLow);
$tmpArrayMath1->financeDiv($movRange, 0.5);
$tmpArrayMath1->mul(100);
$stochastic = $tmpArrayMath1->result();
$label1 = "Fast Stochastic %K ($period1)";
$c = $this->addLineIndicator($height, $stochastic, $color1, $label1);
$label2 = "%D ($period2)";
$tmpArrayMath1 = new ArrayMath($stochastic);
$tmpArrayMath1->movAvg($period2);
$this->addLineIndicator2($c, $tmpArrayMath1->result(), $color2, $label2);
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add a MACD indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The first moving average period to compute the indicator.</param>
#/ <param name="period2">The second moving average period to compute the indicator.</param>
#/ <param name="period3">The moving average period of the signal line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="signalColor">The color of the signal line.</param>
#/ <param name="divColor">The color of the divergent bars.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addMACD($height, $period1, $period2, $period3, $color, $signalColor, $divColor) {
$c = $this->addIndicator($height);
#MACD is defined as the difference between two exponential averages (typically 12/26 days)
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->expAvg(2.0 / ($period1 + 1));
$expAvg1 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->expAvg(2.0 / ($period2 + 1));
$tmpArrayMath1->sub($expAvg1);
$macd = $tmpArrayMath1->result();
#Add the MACD line
$label1 = "MACD ($period1, $period2)";
$this->addLineIndicator2($c, $macd, $color, $label1);
#MACD signal line
$tmpArrayMath1 = new ArrayMath($macd);
$tmpArrayMath1->expAvg(2.0 / ($period3 + 1));
$macdSignal = $tmpArrayMath1->result();
$label2 = "EXP ($period3)";
$this->addLineIndicator2($c, $macdSignal, $signalColor, $label2);
#Divergence
$tmpArrayMath1 = new ArrayMath($macd);
$tmpArrayMath1->sub($macdSignal);
$this->addBarIndicator2($c, $tmpArrayMath1->result(), $divColor, "Divergence");
return $c;
}
#/ <summary>
#/ Add a Mass Index indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addMassIndex($height, $color, $upColor, $downColor) {
#Mass Index
$f = 2.0 / (10);
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->sub($this->m_lowData);
$tmpArrayMath1->expAvg($f);
$exp9 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($exp9);
$tmpArrayMath1->expAvg($f);
$exp99 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($exp9);
$tmpArrayMath1->financeDiv($exp99, 1);
$tmpArrayMath1->movAvg(25);
$tmpArrayMath1->mul(25);
$c = $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, "Mass Index");
$c->yAxis->addMark(27, $upColor);
$c->yAxis->addMark(26.5, $downColor);
return $c;
}
#/ <summary>
#/ Add a Money Flow Index indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="range">The distance beween the middle line and the upper and lower threshold lines.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addMFI($height, $period, $color, $range, $upColor, $downColor) {
#Money Flow Index
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->add($this->m_lowData);
$tmpArrayMath1->add($this->m_closeData);
$tmpArrayMath1->div(3);
$typicalPrice = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($typicalPrice);
$tmpArrayMath1->mul($this->m_volData);
$moneyFlow = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($typicalPrice);
$tmpArrayMath1->delta();
$selector = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($moneyFlow);
$tmpArrayMath1->selectGTZ($selector);
$tmpArrayMath1->movAvg($period);
$posMoneyFlow = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($moneyFlow);
$tmpArrayMath1->selectLTZ($selector);
$tmpArrayMath1->movAvg($period);
$tmpArrayMath1->add($posMoneyFlow);
$posNegMoneyFlow = $tmpArrayMath1->result();
$c = $this->addIndicator($height);
$label = "Money Flow Index ($period)";
$tmpArrayMath1 = new ArrayMath($posMoneyFlow);
$tmpArrayMath1->financeDiv($posNegMoneyFlow, 0.5);
$tmpArrayMath1->mul(100);
$layer = $this->addLineIndicator2($c, $tmpArrayMath1->result(), $color, $label);
$this->addThreshold($c, $layer, 50 + $range, $upColor, 50 - $range, $downColor);
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add a Momentum indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addMomentum($height, $period, $color) {
$label = "Momentum ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->delta($period);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Negative Volume Index indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the signal line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="signalColor">The color of the signal line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addNVI($height, $period, $color, $signalColor) {
$nvi = array_pad(array(), count($this->m_volData), 0);
$previousNVI = 100;
$previousVol = NoValue;
$previousClose = NoValue;
for($i = 0; $i < count($this->m_volData); ++$i) {
if ($this->m_volData[$i] == NoValue) {
$nvi[$i] = NoValue;
} else {
if (($previousVol != NoValue) && ($this->m_volData[$i] < $previousVol) && (
$previousClose != NoValue) && ($this->m_closeData[$i] != NoValue)) {
$nvi[$i] = $previousNVI + $previousNVI * ($this->m_closeData[$i] -
$previousClose) / $previousClose;
} else {
$nvi[$i] = $previousNVI;
}
$previousNVI = $nvi[$i];
$previousVol = $this->m_volData[$i];
$previousClose = $this->m_closeData[$i];
}
}
$c = $this->addLineIndicator($height, $nvi, $color, "NVI");
if (count($nvi) > $period) {
$label = "NVI SMA ($period)";
$tmpArrayMath1 = new ArrayMath($nvi);
$tmpArrayMath1->movAvg($period);
$this->addLineIndicator2($c, $tmpArrayMath1->result(), $signalColor, $label);
}
return $c;
}
#/ <summary>
#/ Add an On Balance Volume indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addOBV($height, $color) {
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->delta();
$closeChange = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->selectGTZ($closeChange);
$upVolume = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->selectLTZ($closeChange);
$downVolume = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($upVolume);
$tmpArrayMath1->sub($downVolume);
$tmpArrayMath1->acc();
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, "OBV");
}
#/ <summary>
#/ Add a Performance indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addPerformance($height, $color) {
$firstCloseIndex = $this->m_extraPoints;
while ($firstCloseIndex < count($this->m_closeData)) {
if (($this->m_closeData[$firstCloseIndex] != NoValue) && ($this->m_closeData[
$firstCloseIndex] != 0)) {
break;
}
$firstCloseIndex = $firstCloseIndex + 1;
}
if ($firstCloseIndex < count($this->m_closeData)) {
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->div($this->m_closeData[$firstCloseIndex]);
$tmpArrayMath1->sub(1);
$tmpArrayMath1->mul(100);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, "Performance")
;
} else {
#chart is empty !!!
return $this->addIndicator($height);
}
}
#/ <summary>
#/ Add a Percentage Price Oscillator indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The first moving average period to compute the indicator.</param>
#/ <param name="period2">The second moving average period to compute the indicator.</param>
#/ <param name="period3">The moving average period of the signal line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="signalColor">The color of the signal line.</param>
#/ <param name="divColor">The color of the divergent bars.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addPPO($height, $period1, $period2, $period3, $color, $signalColor, $divColor) {
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->expAvg(2.0 / ($period1 + 1));
$expAvg1 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->expAvg(2.0 / ($period2 + 1));
$expAvg2 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($expAvg2);
$tmpArrayMath1->sub($expAvg1);
$tmpArrayMath1->financeDiv($expAvg2, 0);
$ppo = $tmpArrayMath1->mul(100);
$tmpArrayMath1 = new ArrayMath($ppo->result());
$tmpArrayMath1->expAvg(2.0 / ($period3 + 1));
$ppoSignal = $tmpArrayMath1->result();
$label1 = "PPO ($period1, $period2)";
$label2 = "EMA ($period3)";
$c = $this->addLineIndicator($height, $ppo->result(), $color, $label1);
$this->addLineIndicator2($c, $ppoSignal, $signalColor, $label2);
$subtractObj = $ppo->sub($ppoSignal);
$this->addBarIndicator2($c, $subtractObj->result(), $divColor, "Divergence");
return $c;
}
#/ <summary>
#/ Add a Positive Volume Index indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the signal line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="signalColor">The color of the signal line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addPVI($height, $period, $color, $signalColor) {
#Positive Volume Index
$pvi = array_pad(array(), count($this->m_volData), 0);
$previousPVI = 100;
$previousVol = NoValue;
$previousClose = NoValue;
for($i = 0; $i < count($this->m_volData); ++$i) {
if ($this->m_volData[$i] == NoValue) {
$pvi[$i] = NoValue;
} else {
if (($previousVol != NoValue) && ($this->m_volData[$i] > $previousVol) && (
$previousClose != NoValue) && ($this->m_closeData[$i] != NoValue)) {
$pvi[$i] = $previousPVI + $previousPVI * ($this->m_closeData[$i] -
$previousClose) / $previousClose;
} else {
$pvi[$i] = $previousPVI;
}
$previousPVI = $pvi[$i];
$previousVol = $this->m_volData[$i];
$previousClose = $this->m_closeData[$i];
}
}
$c = $this->addLineIndicator($height, $pvi, $color, "PVI");
if (count($pvi) > $period) {
$label = "PVI SMA ($period)";
$tmpArrayMath1 = new ArrayMath($pvi);
$tmpArrayMath1->movAvg($period);
$this->addLineIndicator2($c, $tmpArrayMath1->result(), $signalColor, $label);
}
return $c;
}
#/ <summary>
#/ Add a Percentage Volume Oscillator indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The first moving average period to compute the indicator.</param>
#/ <param name="period2">The second moving average period to compute the indicator.</param>
#/ <param name="period3">The moving average period of the signal line.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="signalColor">The color of the signal line.</param>
#/ <param name="divColor">The color of the divergent bars.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addPVO($height, $period1, $period2, $period3, $color, $signalColor, $divColor) {
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->expAvg(2.0 / ($period1 + 1));
$expAvg1 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_volData);
$tmpArrayMath1->expAvg(2.0 / ($period2 + 1));
$expAvg2 = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($expAvg2);
$tmpArrayMath1->sub($expAvg1);
$tmpArrayMath1->financeDiv($expAvg2, 0);
$pvo = $tmpArrayMath1->mul(100);
$tmpArrayMath1 = new ArrayMath($pvo->result());
$tmpArrayMath1->expAvg(2.0 / ($period3 + 1));
$pvoSignal = $tmpArrayMath1->result();
$label1 = "PVO ($period1, $period2)";
$label2 = "EMA ($period3)";
$c = $this->addLineIndicator($height, $pvo->result(), $color, $label1);
$this->addLineIndicator2($c, $pvoSignal, $signalColor, $label2);
$subtractObj = $pvo->sub($pvoSignal);
$this->addBarIndicator2($c, $subtractObj->result(), $divColor, "Divergence");
return $c;
}
#/ <summary>
#/ Add a Price Volumne Trend indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addPVT($height, $color) {
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->rate();
$tmpArrayMath1->sub(1);
$tmpArrayMath1->mul($this->m_volData);
$tmpArrayMath1->acc();
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, "PVT");
}
#/ <summary>
#/ Add a Rate of Change indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addROC($height, $period, $color) {
$label = "ROC ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->rate($period);
$tmpArrayMath1->sub(1);
$tmpArrayMath1->mul(100);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
function computeRSI($period) {
#RSI is defined as the average up changes for the last 14 days, divided by the
#average absolute changes for the last 14 days, expressed as a percentage.
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->delta();
$tmpArrayMath1->abs();
$tmpArrayMath1->movAvg($period);
$absChange = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->delta();
$tmpArrayMath1->selectGTZ();
$tmpArrayMath1->movAvg($period);
$tmpArrayMath1->financeDiv($absChange, 0.5);
$tmpArrayMath1->mul(100);
return $tmpArrayMath1->result();
}
#/ <summary>
#/ Add a Relative Strength Index indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="range">The distance beween the middle line and the upper and lower threshold lines.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addRSI($height, $period, $color, $range, $upColor, $downColor) {
$c = $this->addIndicator($height);
$label = "RSI ($period)";
$layer = $this->addLineIndicator2($c, $this->computeRSI($period), $color, $label);
#Add range if given
if (($range > 0) && ($range < 50)) {
$this->addThreshold($c, $layer, 50 + $range, $upColor, 50 - $range, $downColor);
}
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add a Slow Stochastic indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The period to compute the %K line.</param>
#/ <param name="period2">The period to compute the %D line.</param>
#/ <param name="color1">The color of the %K line.</param>
#/ <param name="color2">The color of the %D line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addSlowStochastic($height, $period1, $period2, $color1, $color2) {
$tmpArrayMath1 = new ArrayMath($this->m_lowData);
$tmpArrayMath1->movMin($period1);
$movLow = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->movMax($period1);
$tmpArrayMath1->sub($movLow);
$movRange = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->sub($movLow);
$tmpArrayMath1->financeDiv($movRange, 0.5);
$tmpArrayMath1->mul(100);
$stochastic = $tmpArrayMath1->movAvg(3);
$label1 = "Slow Stochastic %K ($period1)";
$label2 = "%D ($period2)";
$c = $this->addLineIndicator($height, $stochastic->result(), $color1, $label1);
$movAvgObj = $stochastic->movAvg($period2);
$this->addLineIndicator2($c, $movAvgObj->result(), $color2, $label2);
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add a Moving Standard Deviation indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addStdDev($height, $period, $color) {
$label = "Moving StdDev ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->movStdDev($period);
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
#/ <summary>
#/ Add a Stochastic RSI indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="range">The distance beween the middle line and the upper and lower threshold lines.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addStochRSI($height, $period, $color, $range, $upColor, $downColor) {
$rsi = $this->computeRSI($period);
$tmpArrayMath1 = new ArrayMath($rsi);
$tmpArrayMath1->movMin($period);
$movLow = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($rsi);
$tmpArrayMath1->movMax($period);
$tmpArrayMath1->sub($movLow);
$movRange = $tmpArrayMath1->result();
$c = $this->addIndicator($height);
$label = "StochRSI ($period)";
$tmpArrayMath1 = new ArrayMath($rsi);
$tmpArrayMath1->sub($movLow);
$tmpArrayMath1->financeDiv($movRange, 0.5);
$tmpArrayMath1->mul(100);
$layer = $this->addLineIndicator2($c, $tmpArrayMath1->result(), $color, $label);
#Add range if given
if (($range > 0) && ($range < 50)) {
$this->addThreshold($c, $layer, 50 + $range, $upColor, 50 - $range, $downColor);
}
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add a TRIX indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addTRIX($height, $period, $color) {
$f = 2.0 / ($period + 1);
$label = "TRIX ($period)";
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->expAvg($f);
$tmpArrayMath1->expAvg($f);
$tmpArrayMath1->expAvg($f);
$tmpArrayMath1->rate();
return $this->addLineIndicator($height, $tmpArrayMath1->result(), $color, $label);
}
function computeTrueLow() {
#the lower of today's low or yesterday's close.
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->shift();
$previousClose = $tmpArrayMath1->result();
$ret = array_pad(array(), count($this->m_lowData), 0);
for($i = 0; $i < count($this->m_lowData); ++$i) {
if (($this->m_lowData[$i] != NoValue) && ($previousClose[$i] != NoValue)) {
if ($this->m_lowData[$i] < $previousClose[$i]) {
$ret[$i] = $this->m_lowData[$i];
} else {
$ret[$i] = $previousClose[$i];
}
} else {
$ret[$i] = NoValue;
}
}
return $ret;
}
#/ <summary>
#/ Add an Ultimate Oscillator indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period1">The first moving average period to compute the indicator.</param>
#/ <param name="period2">The second moving average period to compute the indicator.</param>
#/ <param name="period3">The third moving average period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="range">The distance beween the middle line and the upper and lower threshold lines.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addUltimateOscillator($height, $period1, $period2, $period3, $color, $range, $upColor,
$downColor) {
$trueLow = $this->computeTrueLow();
$tmpArrayMath1 = new ArrayMath($this->m_closeData);
$tmpArrayMath1->sub($trueLow);
$buyingPressure = $tmpArrayMath1->result();
$trueRange = $this->computeTrueRange();
$tmpArrayMath2 = new ArrayMath($trueRange);
$tmpArrayMath2->movAvg($period1);
$tmpArrayMath1 = new ArrayMath($buyingPressure);
$tmpArrayMath1->movAvg($period1);
$tmpArrayMath1->financeDiv($tmpArrayMath2->result(), 0.5);
$tmpArrayMath1->mul(4);
$rawUO1 = $tmpArrayMath1->result();
$tmpArrayMath2 = new ArrayMath($trueRange);
$tmpArrayMath2->movAvg($period2);
$tmpArrayMath1 = new ArrayMath($buyingPressure);
$tmpArrayMath1->movAvg($period2);
$tmpArrayMath1->financeDiv($tmpArrayMath2->result(), 0.5);
$tmpArrayMath1->mul(2);
$rawUO2 = $tmpArrayMath1->result();
$tmpArrayMath2 = new ArrayMath($trueRange);
$tmpArrayMath2->movAvg($period3);
$tmpArrayMath1 = new ArrayMath($buyingPressure);
$tmpArrayMath1->movAvg($period3);
$tmpArrayMath1->financeDiv($tmpArrayMath2->result(), 0.5);
$tmpArrayMath1->mul(1);
$rawUO3 = $tmpArrayMath1->result();
$c = $this->addIndicator($height);
$label = "Ultimate Oscillator ($period1, $period2, $period3)";
$tmpArrayMath1 = new ArrayMath($rawUO1);
$tmpArrayMath1->add($rawUO2);
$tmpArrayMath1->add($rawUO3);
$tmpArrayMath1->mul(100.0 / 7);
$layer = $this->addLineIndicator2($c, $tmpArrayMath1->result(), $color, $label);
$this->addThreshold($c, $layer, 50 + $range, $upColor, 50 - $range, $downColor);
$c->yAxis->setLinearScale(0, 100);
return $c;
}
#/ <summary>
#/ Add a Volume indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="upColor">The color to used on an 'up' day. An 'up' day is a day where
#/ the closing price is higher than that of the previous day.</param>
#/ <param name="downColor">The color to used on a 'down' day. A 'down' day is a day
#/ where the closing price is lower than that of the previous day.</param>
#/ <param name="flatColor">The color to used on a 'flat' day. A 'flat' day is a day
#/ where the closing price is the same as that of the previous day.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addVolIndicator($height, $upColor, $downColor, $flatColor) {
$c = $this->addIndicator($height);
$this->addVolBars2($c, $height, $upColor, $downColor, $flatColor);
return $c;
}
#/ <summary>
#/ Add a William %R indicator chart.
#/ </summary>
#/ <param name="height">The height of the indicator chart in pixels.</param>
#/ <param name="period">The period to compute the indicator.</param>
#/ <param name="color">The color of the indicator line.</param>
#/ <param name="range">The distance beween the middle line and the upper and lower threshold lines.</param>
#/ <param name="upColor">The fill color when the indicator exceeds the upper threshold line.</param>
#/ <param name="downColor">The fill color when the indicator falls below the lower threshold line.</param>
#/ <returns>The XYChart object representing the chart created.</returns>
function addWilliamR($height, $period, $color, $range, $upColor, $downColor) {
$tmpArrayMath1 = new ArrayMath($this->m_lowData);
$tmpArrayMath1->movMin($period);
$movLow = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($this->m_highData);
$tmpArrayMath1->movMax($period);
$movHigh = $tmpArrayMath1->result();
$tmpArrayMath1 = new ArrayMath($movHigh);
$tmpArrayMath1->sub($movLow);
$movRange = $tmpArrayMath1->result();
$c = $this->addIndicator($height);
$tmpArrayMath1 = new ArrayMath($movHigh);
$tmpArrayMath1->sub($this->m_closeData);
$tmpArrayMath1->financeDiv($movRange, 0.5);
$tmpArrayMath1->mul(-100);
$layer = $this->addLineIndicator2($c, $tmpArrayMath1->result(), $color, "William %R");
$this->addThreshold($c, $layer, -50 + $range, $upColor, -50 - $range, $downColor);
$c->yAxis->setLinearScale(-100, 0);
return $c;
}
}