Features

Indicators

Indicators

A technical indicator is a set of derived data that is calculated by applying one or more formulas to the original set of data.

Features

Chart Types
Interaction
Analytics

Settings

Description

A technical indicator is a set of derived data that is calculated by applying one or more formulas to the original set of data. Technical indicators are generally used to forecast the asset's market direction and generally plotted separately from the original data since the Y-axis scales differ.

using FinancialChartExplorer.Models;
using System.Collections.Generic;
using System.Web.Mvc;

namespace FinancialChartExplorer.Controllers
{
    public partial class HomeController : Controller
    {
        //
        // GET: /Indicators/

        public ActionResult Indicators()
        {
            var model = BoxData.GetDataFromJson();
            return View(model);
        }
    }
}
@using FinancialChartExplorer.Models

@model List<FinanceData>
@{
    ViewBag.DemoSettings = true;
    var indicators = new List<AnalysisType> { 
        new AnalysisType{Name = "Average True Range", Abbreviation = "atr"},
        new AnalysisType{Name = "Relative Strength Index", Abbreviation = "rsi" },
        new AnalysisType{Name = "Commodity Channel Index", Abbreviation = "cci" },
        new AnalysisType{Name = "Williams %R", Abbreviation = "williamsR" },
        new AnalysisType{Name = "MACD", Abbreviation = "macd" },
        new AnalysisType{Name = "Stochastic", Abbreviation = "stoch" }
    };
}

<script type="text/javascript">
    var indicatorAbbs = [@Html.Raw(string.Join(",", indicators.Select(idi => "'" + idi.Abbreviation + "'")))];

    function showOption(indicator) {
        for (var i = 0; i < indicatorAbbs.length; i++) {
            toggleGroup(indicatorAbbs[i], indicatorAbbs[i] == indicator);
        }
    }

    function toggleGroup(indicator, shown) {
        var optGroup = wijmo.getElement('#' + indicator);
        if (optGroup) {
            if (shown) {
                optGroup.style.display = '';
            } else {
                optGroup.style.display = 'none';
            }
        }
    }

    function updateIndicatorType(combox) {
        var indicator = combox.selectedValue, index = combox.selectedIndex,
            indexes = [];

        if (index == 4) {
            indexes = [index, index + 1];
        } else if (index == 5) {
            indexes.push(index + 1);
        } else {
            indexes.push(index);
        }

        showSeries(indexes);
        showOption(indicator);
    }

    function showSeries(indexes) {
        var chart = wijmo.Control.getControl('#indicator');

        if (indexes == null || !indexes.length || !chart) {
            return;
        }

        for (var i = 0; i < chart.series.length; i++) {
            chart.series[i].visibility = (indexes.indexOf(i) != -1) ? wijmo.chart.SeriesVisibility.Visible : wijmo.chart.SeriesVisibility.Hidden;
        }
    }

    function updateATRPeriod(atrPDNumber) {
        var chart = wijmo.Control.getControl('#indicator');
        if (!checkValue(atrPDNumber)) {
            return;
        }
        if (chart) {
            chart.series[0].period = atrPDNumber.value;
        }
    }

    function updateRSIPeriod(rsiPDNumber) {
        var chart = wijmo.Control.getControl('#indicator');
        if (!checkValue(rsiPDNumber)) {
            return;
        }
        if (chart) {
            chart.series[1].period = rsiPDNumber.value;
        }
    }

    function updateCCIPeriod(cciPDNumber) {
        var chart = wijmo.Control.getControl('#indicator');
        if (!checkValue(cciPDNumber)) {
            return;
        }
        if (chart) {
            chart.series[2].period = cciPDNumber.value;
        }
    }

    function updateWilliamsRPeriod(wrPDNumber) {
        var chart = wijmo.Control.getControl('#indicator');
        if (!checkValue(wrPDNumber)) {
            return;
        }
        if (chart) {
            chart.series[3].period = wrPDNumber.value;
        }
    }

    function getDataLength(){
        return @(Model.Count);
    }

    function isValidSmoothingPeriod(newValue) {
        var dataLength = getDataLength(),
            chart = wijmo.Control.getControl('#indicator'),
            max;
        if (dataLength <= 0 || !chart) {
            return false;
        }

        max = Math.max(chart.series[4].fastPeriod, chart.series[4].slowPeriod);
        return newValue >= 2 && newValue <= Math.abs(dataLength - max);
    }

    function isValidPeriod(newValue) {
        var dataLength = getDataLength(),
            chart = wijmo.Control.getControl('#indicator'),
            smoothing;
        if (dataLength <= 0 || !chart) {
            return false;
        }

        smoothing = chart.series[4].smoothingPeriod;
        return newValue >= 2 && newValue <= Math.abs(dataLength - smoothing);
    }

    function updateFastPeriod(macdFPNumber) {
        var chart = wijmo.Control.getControl('#indicator'),
            validPeriod = macdFPNumber.value;
        if (!isValidPeriod(validPeriod)) {
            return;
        }
        if (chart) {
            chart.series[4].fastPeriod = validPeriod;
            chart.series[5].fastPeriod = validPeriod;
            macdFPNumber.value = validPeriod;
        }
    }

    function updateSlowPeriod(macdSPNumber) {
        var chart = wijmo.Control.getControl('#indicator'),
            validPeriod = macdSPNumber.value;
        if (!isValidPeriod(validPeriod)) {
            return;
        }
        if (chart) {
            chart.series[4].slowPeriod = validPeriod;
            chart.series[5].slowPeriod = validPeriod;
            macdSPNumber.value = validPeriod;
        }
    }

    function updateSmoothingPeriod(macdSPNumber) {
        var chart = wijmo.Control.getControl('#indicator'),
            validPeriod = macdSPNumber.value;
        if (!isValidSmoothingPeriod(validPeriod)) {
            return;
        }
        if (chart) {
            chart.series[4].smoothingPeriod = validPeriod;
            chart.series[5].smoothingPeriod = validPeriod;
            macdSPNumber.value = validPeriod;
        }
    }

    function isValidKPeriod(newValue) {
        var dataLength = getDataLength(),
            chart = wijmo.Control.getControl('#indicator'),
            kMax, smoothingPeriod;
        if (dataLength <= 0 || !chart) {
            return false;
        }

        kMax = Math.abs(dataLength - chart.series[6].dPeriod);
        smoothingPeriod = chart.series[6].smoothingPeriod;
        if (smoothingPeriod > 1) {
            kMax -= smoothingPeriod;
        }

        return newValue >= 2 && newValue <= kMax;
    }

    function isValidDPeriod(newValue) {
        var dataLength = getDataLength(),
            chart = wijmo.Control.getControl('#indicator'),
            dMax, smoothingPeriod;

        if (dataLength <= 0 || !chart) {
            return false;
        }

        dMax = Math.abs(dataLength - chart.series[6].kPeriod);
        smoothingPeriod = chart.series[6].smoothingPeriod;
        if (smoothingPeriod > 1) {
            dMax -= smoothingPeriod;
        }

        return newValue >= 2 && newValue <= dMax;
    }

    function isValidStochSmoothingPeriod(newValue) {
        var dataLength = getDataLength(),
            chart = wijmo.Control.getControl('#indicator'),
            sMax;

        if (dataLength <= 0 || newValue <= 1) {
            return false;
        }

        sMax = Math.abs(dataLength - chart.series[6].kPeriod - chart.series[6].dPeriod);
        sMax = sMax || 1;
        return newValue >= 1 && newValue <= sMax;
    }

    function updateKPeriod(stochKPNumber) {
        var chart = wijmo.Control.getControl('#indicator'),
            validPeriod = stochKPNumber.value;
        if (!isValidKPeriod(validPeriod)) {
            return;
        }
        if (chart) {
            chart.series[6].kPeriod = validPeriod;
            stochKPNumber.value = validPeriod;
        }
    }

    function updateDPeriod(stochDPNumber) {
        var chart = wijmo.Control.getControl('#indicator'),
            validPeriod = stochDPNumber.value;
        if (!isValidDPeriod(validPeriod)) {
            return;
        }
        if (chart) {
            chart.series[6].dPeriod = validPeriod;
            stochDPNumber.value = validPeriod;
        }
    }

    function updateStochSmoothingPeriod(stochSPNumber) {
        var chart = wijmo.Control.getControl('#indicator'),
            validPeriod = stochSPNumber.value;
        if (!isValidStochSmoothingPeriod(validPeriod)) {
            return;
        }
        if (chart) {
            chart.series[6].smoothingPeriod = validPeriod;
            stochSPNumber.value = validPeriod;
        }
    }

    function checkValue(number) {
        return number.value >= number.min && number.value <= number.max;
    }

    c1.documentReady(function () {
        var combox = wijmo.Control.getControl('#indicatorSel');
        if (combox) {
            combox.selectedIndex = 0;
            updateIndicatorType(combox);
        }
    });

    function chartRendered(sender, args) {
        // set min/max for indicator chart to match main chart
        var indicatorChart = wijmo.Control.getControl('#indicator'),
            chart = wijmo.Control.getControl('#financeChart');

        if (chart && indicatorChart) {
            indicatorChart.axisX.min = chart.axisX.actualMin;
            indicatorChart.axisX.max = chart.axisX.actualMax;
        }
    };
</script>

@(Html.C1().FinancialChart()
.Id("financeChart")
.Bind(Model)
.BindingX("X")
.Series(sers =>
{
    sers.Add().Binding("Close").Name("BOX");
})
.Tooltip(t => t.Content("tooltip"))
.Legend(C1.Web.Mvc.Chart.Position.Top)
.OnClientRendered("chartRendered"))

@(Html.C1().FinancialChart().Height(200)
.Id("indicator")
.Bind(Model)
.BindingX("X")
.Series(sers =>
{
    sers.AddATR().Binding("High,Low,Open,Close").Period(14).Name("ATR");
    sers.AddRSI().Binding("Close").Period(14).Name("RSI");
    sers.AddCCI().Binding("High,Low,Open,Close").Period(20).Name("CCI");
    sers.AddWilliamsR().Binding("High,Low,Open,Close").Period(14).Name("Williams %R");
    sers.AddMacd().Binding("Close").FastPeriod(12).SlowPeriod(26).SmoothingPeriod(9).SetMacdLineStyle("#bfa554").SetSignalLineStyle("#bf8c54").Name("MACD,Signal");
    sers.AddMacdHistogram().Binding("Close").FastPeriod(12).SlowPeriod(26).SmoothingPeriod(9).Name("MACD Histogram");
    sers.AddStochastic().Binding("High,Low,Open,Close").KPeriod(14).DPeriod(3).SmoothingPeriod(1).SetKLineStyle("#eddd46").SetDLineStyle("#edb747").Name("%K,%D");
})
.Tooltip(t => t.Content("tooltip"))
.Legend(C1.Web.Mvc.Chart.Position.Bottom)
.OnClientRendered("chartRendered"))

@section Settings{
<div class="panel-body">
    <!-- Indicator Selector -->
    <ul class="list-inline">
        <li>
            <label>Indicator Type</label>
            @(Html.C1().ComboBox().Id("indicatorSel").Bind(indicators).SelectedValuePath("Abbreviation").DisplayMemberPath("Name").OnClientSelectedIndexChanged("updateIndicatorType").IsEditable(false))
        </li>
    </ul>

    <!-- ATR Properties -->
    <ul class="list-inline" id="atr">
        <li>
            <label>Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(14).OnClientValueChanged("updateATRPeriod"))
        </li>
    </ul>

    <!-- RSI Properties -->
    <ul class="list-inline" id="rsi">
        <li>
            <label>Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(14).OnClientValueChanged("updateRSIPeriod"))
        </li>
    </ul>

    <!-- CCI Properties -->
    <ul class="list-inline" id="cci">
        <li>
            <label>Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(20).OnClientValueChanged("updateCCIPeriod"))
        </li>
    </ul>

    <!-- Williams %R Properties -->
    <ul class="list-inline" id="williamsR">
        <li>
            <label>Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(14).OnClientValueChanged("updateWilliamsRPeriod"))
        </li>
    </ul>

    <!-- MACD & MACD Histogram Properties -->
    <ul class="list-inline" id="macd">
        <li>
            <label>Fast Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(12).OnClientValueChanged("updateFastPeriod"))
        </li>
        <li>
            <label>Slow Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(26).OnClientValueChanged("updateSlowPeriod"))
        </li>
        <li>
            <label>Signal Smoothing Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(9).OnClientValueChanged("updateSmoothingPeriod"))
        </li>
    </ul>

    <!-- Fast Stochastic Properties -->
    <ul class="list-inline" id="stoch">
        <li>
            <label>K Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(14).OnClientValueChanged("updateKPeriod"))
        </li>
        <li>
            <label>D Period</label>
            @(Html.C1().InputNumber().Min(2).Step(1).Format("n0").Max(Model.Count - 1).Value(3).OnClientValueChanged("updateDPeriod"))
        </li>
        <li>
            <label>Smoothing Period</label>
            @(Html.C1().InputNumber().Min(1).Step(1).Format("n0").Max(Model.Count - 1).Value(1).OnClientValueChanged("updateStochSmoothingPeriod"))
        </li>
    </ul>
</div>
}

@section Description{
    <p>
        A technical indicator is a set of derived data that is calculated by applying one or more formulas to the original set of data. Technical indicators are generally used to forecast the asset's market direction and generally plotted separately from the original data since the Y-axis scales differ.
    </p>
}
@section Summary{
    <p>
        A technical indicator is a set of derived data that is calculated by applying one or more formulas to the original set of data.
    </p>
}