Location: PHPKode > projects > Finasystem > fs_ta/dmi.php
<?php
/**
* Finasystem version 0.4 Lin Hai - Technical Analysis Library in PHP
 *Release: 14/10/2006
 *Copyright (C) 2006 Rudy Zuck
 *mailto:rudy[-at-]zuck.fr
 *web:http://sourceforge.net/projects/finasystem
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; if not, write to the Free Software
 *Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA  
 */

/**
 * Directionnal Movement Index Class (DMI)
 *
 *<p>The ATR is a Welles Wilder style moving average of the True Range. The ATR is a measure 
 *of volatility. High ATR values indicate high volatility, and low values indicate low volatility, 
 *often seen when the price is flat.</p>
 *
 *<p>The +DI is the percentage of the true range that is up. The -DI is the percentage of the true range 
 *that is down. A buy signal is generated when the +DI crosses up over the -DI. A sell signal is generated 
 *when the -DI crosses up over the +DI. You should wait to enter a trade until the extreme point is reached. 
 *That is, you should wait to enter a long trade until the price reaches the high of the bar on which the +DI 
 *crossed over the -DI, and wait to enter a short trade until the price reaches the low of the bar on which 
 *the -DI crossed over the +DI.</p>
 *
 *<p>The DX is usually smoothed with a moving average (i.e. the ADX). The values range from 0 to 100, but 
 *rarely get above 60. To interpret the DX, consider a high number to be a strong trend, and a low number, 
 *a weak trend.</p>
 *
 *<p>The ADX is a Welles Wilder style moving average of the Directional Movement Index (DX). The values range 
 *from 0 to 100, but rarely get above 60. To interpret the ADX, consider a high number to be a strong trend, 
 *and a low number, a weak trend.</p>
 *
 *<p>The ADXR is equal to the current ADX plus the ADX from n bars ago divided by 2. In effect, it is the 
 *average of the two ADX values. The ADXR smoothes the ADX, and is therefore less responsive, however, the 
 *ADXR filters out excessive tops and bottoms. To interpret the ADXR, consider a high number to be a strong 
 *trend, and a low number, a weak trend.</p>
 *
 *<p>The ADXR was developed by J. Welles Wilder and is described in his 1978 book 
 *New Concepts In Technical Trading Systems.</p>
 *
 *<p>Formula:</p>
 *
 * - The formula is slightly difficult. You can find a documentation of the DMI in the folder "Documentation"
 *
 * @author Rudy Zuck <rudy[-at-]zuck.fr>
 * @copyright Copyright, 2006, Rudy Zuck
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version 0.4
 * @package fs_ta
 */
class dmi{

	/**
	 * @var double[]
	 */	
	private $adxr;
	
	/**
	 * @var double[]
	 */	
	private $adx;
	/**
	 * @var double[]
	 */	
	private $dx;
	/**
	 * @var double[]
	 */	
	private $di_plus;
	/**
	 * @var double[]
	 */	
	private $di_minus;
	/**
	 * @var double[]
	 */	
	private $atr;
	/**
	 * @var double[]
	 */	
	private $dm_range_plus;
	/**
	 * @var double[]
	 */	
	private $dm_range_minus;
	/**
	 * @var double[]
	 */	
	private $tr;
	/**
	 * @var double[]
	 */	
	private $dm_plus;
	/**
	 * @var double[]
	 */	
	private $dm_minus;

	/**
     * @param double[] $high
	 * @param double[] $low
	 * @param double[] $close 
     * @param int $range
	 * @return void
     */
	function set($high,$low,$close,$range){
		
		//Computing the DM+ and DM-
		$size_data = count($close);
		
		for($i=1; $i<$size_data; $i++){
			if ($high[$i]>$high[$i-1]){
				$this->dm_plus[$i] = $high[$i]-$high[$i-1];
			}
			else {
				$this->dm_plus[$i] = 0;
			}
		
			if ($low[$i]<$low[$i-1]){
				$this->dm_minus[$i] = ($low[$i]-$low[$i-1]) * -1;
			}
			else {
				$this->dm_minus[$i] = 0;
			}
		
		}

		//Calculus of the TR
		for($i=1; $i<$size_data; $i++){
			$one = abs($high[$i] - $low[$i]);
			$two = abs($high[$i] - $close[$i-1]);
			$three = abs($low[$i] - $close[$i-1]);
			$this->tr[$i] = max($one, $two, $three);
		}
	
		//Calulus of DMrange+, DMrange-, TRrange
		$dm_temp_range_plus = 0;
		$dm_temp_range_minus = 0;
		$tr_temp_range = 0;

		for ($i=1; $i<$range; $i++){
			$dm_temp_range_plus += $this->dm_plus[$i]; 
			$dm_temp_range_minus += $this->dm_minus[$i];
			$tr_temp_range += $this->tr[$i]; 
		}

		$this->dm_range_plus[$range-1] = $dm_temp_range_plus;
		$this->dm_range_minus[$range-1] = $dm_temp_range_minus;
		$this->atr[$range-1] = $tr_temp_range;

		for ($i=0; $i<$size_data-$range; $i++){
			$this->dm_range_plus[$range+$i]=$this->dm_plus[$range+$i]+((($range-1)/$range)*$this->dm_range_plus[$range+$i-1]);
			$this->dm_range_minus[$range+$i]=$this->dm_minus[$range+$i]+((($range-1)/$range)*$this->dm_range_minus[$range+$i-1]); 
			$this->atr[$range+$i]=$this->tr[$range+$i]+((($range-1)/$range)*$this->atr[$range+$i-1]); 
		}

		//Calulus of DI+, DI-
		for ($i=0; $i<$size_data-$range+1; $i++){
			$this->di_plus[$range-1+$i] = $this->dm_range_plus[$range-1 + $i]*100 / $this->atr[$range-1 + $i]; 
			$this->di_minus[$range-1+$i] = $this->dm_range_minus[$range-1 + $i]*100 / $this->atr[$range-1 + $i];
		}

		//Calulus of DX
		for ($i=0; $i<$size_data-$range+1; $i++){
			$this->dx[$range-1+$i] = floor(((abs($this->di_plus[$range-1 + $i] - $this->di_minus[$range-1 + $i])) / 
												($this->di_plus[$range-1 + $i] + $this->di_minus[$range-1 + $i]))*100); 
		}

		//Calulus of ADX
		$adx_temp = 0;
		for ($i=$range-1; $i<2*$range-1; $i++){
			$adx_temp += $this->dx[$i]; 
		}
		$this->adx[2*$range-2] = $adx_temp/$range;

		for ($i=2*$range-1; $i<$size_data; $i++){
			$this->adx[] = (($range-1) * $this->adx[$i-1] + $this->dx[$i]) / $range; 
		}
		
		//Calulus of ADXR
		$i=0;
		while(true){
			if(isset($this->adx[$i])){break;}
			$i++;
		}
		for($j=$i+$range;$j<$size_data;$j++){
			$this->adxr[$j] = ($this->adx[$j] + $this->adx[$j-$range])/2; 
		}
	}
	
	/** 
    * @return double[]
    */
	function get_adx(){
			return $this->adx;
	}
	
	/** 
    * @return double[]
    */
	function get_dx(){
			return $this->dx;
	}

	/** 
    * @return double[]
    */
	function get_di_plus(){
			return $this->di_plus;
	}

	/** 
    * @return double[]
    */
	function get_di_minus(){
			return $this->di_minus;
	}
	
	/** 
    * @return double[]
    */
	function get_atr(){
			return $this->atr;
	}
	
	/** 
    * @return double[]
    */
	function get_dm_range_plus(){
			return $this->dm_range_plus;
	}
	
	/** 
    * @return double[]
    */
	function get_dm_range_minus(){
			return $this->dm_range_minus;
	}
}
?>
Return current item: Finasystem