Summary:
The Klinger Volume Oscillator indicator uses volume to measures the accumulation or distribution of shares in order to determine the long-term trends of money flow while
remaining sensitive to short-term fluctuations.

Developer:
Stephen J. Klinger

Interpretation:
1. When the Klinger Volume Oscillator indicator crosses above zero the underlying symbol price is likely to increase.
2. When the Klinger Volume Oscillator indicator crosses below zero the underlying symbol price is likely to decrease.
3. When the Klinger Volume Oscillator indicator starts increasing but the underlying symbol is decreasing, the underlying symbol price is likely to start increasing. (Positive Divergence).
4. When the Klinger Volume Oscillator indicator starts decreasing but the underlying symbol is increasing, the underlying symbol price is likely to start decreasing. (Negative Divergence).

                    
#region Namespaces using System; #endregion namespace ScriptCode { /// <summary> /// Indicator scripts are used for calculating a series of numerical values. /// /// This script can be used in several ways: /// (1) It can be used on a chart. /// (2) It can be used from another script. /// (3) It can be used as a script column in a watchlist. /// </summary> public partial class MyIndicator : IndicatorScriptBase // NEVER CHANGE THE CLASS NAME { #region Variables // Use for the underlying symbol index on which to calculate the indicator. private int _symbolIndex; // Use for the long EMA. private const int LONG_EMA = 0; // Use for the short EMA. private const int SHORT_EMA = 1; // Use for the long smooth factor. private double _longSmoothFactor; // Use for the short smooth factor. private double _shortSmoothFactor; #endregion #region OnInitialize /// <summary> /// This function accepts the user parameters for the script and is called when a new indicator instance is created. /// One of the parameters accepted by it must be that of a symbol or another script that is /// based on a symbol (drawing, indicator, pattern or signal). This symbol will be used as the underlying symbol for the indicator. /// /// The parameter values can be specified from the user interface (UI) or from another script, depending on usage. /// </summary> /// -------------------------------------------------------------------------------------------------- /// PLEASE USE THE SCRIPT WIZARD (CTRL+W) TO ADD, EDIT AND REMOVE THE SCRIPT PARAMETERS /// -------------------------------------------------------------------------------------------------- /// YOU MUST SET A PARAM TAG FOR EACH PARAMETER ACCEPTED BY THIS FUNCTION. /// ALL PARAM TAGS SHOULD BE SET IN THE 'OnInitialize' REGION, RIGHT ABOVE THE 'OnInitialize' FUNCTION. /// THE ORDER OF THE TAGS MUST MATCH THE ORDER OF THE ACTUAL PARAMETERS. /// REQUIRED ATTRIBUTES: /// (1) name: The exact parameter name. /// (2) type: The type of data to collect from the user: /// Set to "Integer" when the data type is 'int' /// Set to "IntegerArray" when the data type is 'int[]' /// Set to "DateTime" when the data type is 'long' /// Set to "DateTimeArray" when the data type is 'long[]' /// Set to "Boolean" when the data type is 'bool' /// Set to "BooleanArray" when the data type is 'bool[]' /// Set to "Double" when the data type is 'double' /// Set to "DoubleArray" when the data type is 'double[]' /// Set to "String" when the data type is 'string' /// Set to "StringArray" when the data type is 'string[]' /// Set to "Indicator" when the data type is 'Indicator' /// Set to "Pattern" when the data type is 'Pattern' /// Set to "Signal" when the data type is 'Signal' /// Set to "Drawing" when the data type is 'Drawing' /// Set to "Symbol" when the data type is 'int' representing a symbol index. /// OPTIONAL ATTRIBUTES: /// (3) default: The default parameter value is only valid when the type is Integer, Boolean, Double or String. /// (4) min: The minimum parameter value is only valid when the type is Integer or Double. /// (5) max: The maximum parameter value is only valid when the type is Integer or Double. /// EXAMPLE: <param name="" type="" default="" min="" max="">Enter the parameter description here.</param> /// -------------------------------------------------------------------------------------------------- /// <param name="symbolIndex" type="Symbol" default="">Use for the underlying symbol index on which to calculate the indicator.</param> public void OnInitialize(int symbolIndex) { _symbolIndex = symbolIndex; // Set the long smooth factor. _longSmoothFactor = 2 / (double)(55 + 1); // Set the short smooth factor. _shortSmoothFactor = 2 / (double)(34 + 1); // Create the internal series. IndicatorCreateSeries(2); } #endregion #region OnBarUpdate /// <summary> /// This function is used for calculating the indicator value for the latest bar (see the Indicator functions). /// </summary> /// <returns>The indicator value for the latest bar.</returns> public override double OnBarUpdate() { // Check whether the number of indicator values is lower than the number of values needed. if (IndicatorValueCount() == 0) return 0; // Use for todays typical price. double todayTypicalPrice = BarTypicalPrice(_symbolIndex, 0); // Use for yesterdays typical price. double yesterdayTypicalPrice = BarTypicalPrice(_symbolIndex, 1); // Use for today's volume. double todayVolume = 0; // Check whether todays typical price is higher than yesterday's. if (todayTypicalPrice >= yesterdayTypicalPrice) // Set the volume. todayVolume = BarVolume(_symbolIndex, 0); // Check whether yesterdays typical price is higher than today's. if (todayTypicalPrice < yesterdayTypicalPrice) // Set the volume. todayVolume = - 1 * BarVolume(_symbolIndex, 0); // Check whether the EMA's have not yet been initialized. if (IndicatorGetSeriesValue(LONG_EMA, 1) == 0) { IndicatorSetSeriesValue(LONG_EMA, 0, todayVolume); IndicatorSetSeriesValue(SHORT_EMA, 0, todayVolume); } else { // Calculate the long EMA. IndicatorSetSeriesValue(LONG_EMA, 0, (1 - _longSmoothFactor) * IndicatorGetSeriesValue(LONG_EMA, 1) + _longSmoothFactor * todayVolume); // Calculate the short EMA. IndicatorSetSeriesValue(SHORT_EMA, 0, (1 - _shortSmoothFactor) * IndicatorGetSeriesValue(SHORT_EMA, 1) + _shortSmoothFactor * todayVolume); } // Calculate the KVO return IndicatorGetSeriesValue(SHORT_EMA, 0) - IndicatorGetSeriesValue(LONG_EMA, 0); } #endregion #region OnChartSetup /// <summary> /// This function is used for setting up the indicator on the chart and registering its pens (see the IndicatorRegisterPen function). /// </summary> public override void OnChartSetup() { // Register a pen. IndicatorRegisterPen(0, "Positive Pen", new byte[] { 25, 200, 25, 255 }, IQ_DashStyle.SOLID, 2); // Register a pen. IndicatorRegisterPen(1, "Negative Pen", new byte[] { 175, 25, 25, 255 }, IQ_DashStyle.SOLID, 2); // Set the indicator in a new panel. IndicatorChartSetNewPanel(true); // Set a default plot style. IndicatorChartSetPlotStyle(IQ_PlotStyle.BOX_ZERO); } #endregion #region OnSelectPen /// <summary> /// This function is used for selecting a registered indicator pen with which to color the latest indicator value. /// Call the IndicatorRegisterPen function from the OnChartSetup function in order to register an indicator pen. /// </summary> /// <returns>The indicator pen index to use for coloring the latest indicator value.</returns> public override byte OnSelectPen() { // Check whether the indicator is going up. if (this[0] > 0) // Return the positive pen index 0 return 0; // The indicator is going down so return the negative pen index 1. else return 1; } #endregion } }

The Algorithmic Trading Software for Hedge Funds and Quants