File Name: HandS_Indicator.efs
Description:
Detecting Head & Shoulders Algorithmically, By Giorgos E. Siligardos
Formula Parameters:
HandS_Indicator.efs
Price Source Close
Max Pattern Length 200
Line Color red
Line Size 2
Notes:
The related article is copyrighted material. If you are not a subscriber
of Stocks & Commodities, please visit www.traders.com.
Download File:
HandS_Indicator.efs
HandS_Indicator.efs
EFS Code:
Description:
Detecting Head & Shoulders Algorithmically, By Giorgos E. Siligardos
Formula Parameters:
HandS_Indicator.efs
Price Source Close
Max Pattern Length 200
Line Color red
Line Size 2
Notes:
The related article is copyrighted material. If you are not a subscriber
of Stocks & Commodities, please visit www.traders.com.
Download File:
HandS_Indicator.efs
HandS_Indicator.efs
EFS Code:
PHP Code:
/*********************************
Provided By:
Interactive Data Corporation (Copyright В© 2013)
All rights reserved. This sample eSignal Formula Script (EFS)
is for educational purposes only. Interactive Data Corporation
reserves the right to modify and overwrite this EFS file with
each new release.
Description:
HandS Indicator
Version: 1.00 18/03/2013
Formula Parameters: Default:
Price Source Close
Max Pattern Length 200
Line Color red
Line Size 2
Notes:
The related article is copyrighted material. If you are not a subscriber
of Stocks & Commodities, please visit www.traders.com.
**********************************/
var fpArray = new Array();
function preMain()
{
setPriceStudy(true);
setStudyTitle("HandS Indicator");
setComputeOnClose();
var x = 0;
fpArray[x] = new FunctionParameter("fpPriceSource", FunctionParameter.STRING);
with(fpArray[x++])
{
setName("Price Source");
addOption("Open");
addOption("Close");
addOption("Low");
addOption("High");
addOption("HL/2");
addOption("HLC/3");
addOption("OHLC/4");
setDefault("Close");
}
fpArray[x] = new FunctionParameter("fpMaxLength", FunctionParameter.NUMBER);
with(fpArray[x++])
{
setName("Max Pattern Length");
setLowerLimit(1);
setDefault(200);
}
fpArray[x] = new FunctionParameter("fpLineColor", FunctionParameter.COLOR);
with(fpArray[x++])
{
setName("Line Color");
setDefault(Color.red);
}
fpArray[x] = new FunctionParameter("fpLineSize", FunctionParameter.NUMBER);
with(fpArray[x++])
{
setName("Line Size");
setDefault(2);
}
}
var bInit = false;
var bVersion = null;
var nPrev_HSDuration = 0;
var pUsedPoints = new Array();
var xSrc = null;
var nLinesCntr = 0;
function main(fpPriceSource, fpMaxLength, fpLineColor, fpLineSize)
{
if (bVersion == null) bVersion = verify();
if (bVersion == false) return;
if(!bInit)
{
switch (fpPriceSource)
{
case 'Open':
xSrc = open();
break;
case 'Close':
xSrc = close();
break;
case 'High':
xSrc = high();
break;
case 'Low':
xSrc = low();
break;
case 'HL/2':
xSrc = hl2();
break;
case 'HLC/3':
xSrc = hlc3();
break;
case 'OHLC/4':
xSrc = ohlc4();
break;
default : return;
}
bInit = true;
}
if(getBarState() == BARSTATE_ALLBARS)
{
pUsedPoints = new Array();
nPrev_HSDuration = 0;
}
var nNumBars = getCurrentBarCount();
var p1 = llv(5, xSrc).getValue(0);
if (p1 == null) return;
var fac = 1;
var nBarSince = -LastBarIndexWhen(function(i){return xSrc.getValue(i) < p1;});
if (nBarSince == null) return;
var He = hhv(Math.max(1, nBarSince), xSrc).getValue(0);
if (He == null) return;
var Heb = LastBarIndexWhen(function(i){return xSrc.getValue(i) == He;});
var Rhalf = Math.max(1, -Heb);
var Lhalf = fac * Rhalf;
var b0b = Math.min(-Rhalf -Lhalf, -nBarSince);
var tL1 = llv(Math.max(1, Int(2 * Lhalf / 3)), xSrc).getValue(-Rhalf);
if (tL1 == null) return;
var tL1b = LastBarIndexWhen(function(i){return xSrc.getValue(i - Rhalf) == tL1;}) - Rhalf;
var H1 = hhv(Math.max(1, Math.abs(tL1b - b0b)), xSrc).getValue(tL1b);
if (H1 == null) return;
var H1b = LastBarIndexWhen(function(i){return xSrc.getValue(i + tL1b) == H1;}) + tL1b;
var eltimi = llv(Math.max(1, Math.abs(tL1b - H1b)), xSrc).getValue(tL1b);
if (eltimi == null) return;
var L1b = LastBarIndexWhen(function(i){return xSrc.getValue(i + tL1b) <= ((tL1 + 2 * eltimi) / 3);}) + tL1b;
if(L1b == null || L1b > 0) return;
var L1 = xSrc.getValue(L1b);
var L2 = llv(Math.max(1, 2 * Int(Rhalf / 3)), xSrc).getValue(-Int(Rhalf / 3));
if (L2 == null) return;
var L2b = LastBarIndexWhen(function(i){return xSrc.getValue(i - Int(Rhalf / 3)) == L2;}) - Int(Rhalf / 3);
var H2 = hhv(Math.max(1, -L2b), xSrc).getValue(0);
if (H2 == null) return;
var H2b = LastBarIndexWhen(function(i){return xSrc.getValue(i) == H2;});
var L3b = LastBarIndexWhen(function(i){return i > H2b && xSrc.getValue(i) <= L2;});
if(L3b == null || L3b > 0) return;
var L0b = LastBarIndexWhen(function(i){return xSrc.getValue(i + H1b) <= L1 + 0.2 * (H1 - L1);}) + H1b;
if(L0b == null || L0b > 0) return;
var L0 = xSrc.getValue(L0b);
var L3 = xSrc.getValue(L3b);
// ================== CHECK FOR H&S PATTERN ======================
var bExpr1 = H1 > (L1 + 0.20 * (He - L1));
var bExpr2 = H1 < (He - 0.15 * (He - L1));
var bExpr3 = H2 > (L2 + 0.25 * (He - L2));
var bExpr4 = H2 < (He - 0.25 * (He - L2));
var bExpr5 = L2 < (L1 + 0.40 * (He - L1));
var bExpr6_1 = L2 > L1 + 0.20 * (He - L1);
var bIfTrue_bExpr6_1 = hhv(Int(Math.max((Heb - L2b)/3, 1)), xSrc).getValue(L2b) < L2 + 0.7 * (He - L2);
var bExpr6 = bExpr6_1 ? bIfTrue_bExpr6_1 : true;
var bExpr7 = L2 > (L1 - 0.15 * (He - L1));
var bExpr8 = Math.abs((H1 - L1) - (H2 - L2)) < Math.min(H1 - L1, H2 - L2);
var nVal9_1 = hhv(Math.max(1, Int((L1b - Heb)/2)), xSrc).getValue(-Int(Rhalf + (L1b - Heb)/2));
var nVal9_2 = llv(Math.max(1, Int((Heb - L1b)/2)), xSrc).getValue(-Int(Rhalf));
var bExpr9 = Math.abs(nVal9_1 - nVal9_2) < (He - L1)/2;
var bExpr10 = hhv(Math.max(1, -L3b), close()).getValue(0) < L3 + (H2 - L3)/3;
var bExpr11_1 = hhv(Math.max(1, Int((H2b - L2b)/3)), xSrc).getValue(H2b - Int(2*(H2b - L2b)/3)) > (L2 + 0.8 * (H2 - L2))
var bExpr11_2 = llv(Math.max(1, Int((H2b - L2b)/3)), xSrc).getValue(H2b) < (L2 + 0.25 * (H2 - L2));
var bExpr11 = (bExpr11_1 && bExpr11_2) == false;
var bExpr12_1 = (H1 - L1) > 0.25 * (He - L1);
var bExpr12_2 = (H2 - L2) > 0.25 * (He - L2);
var bExpr12_3 = Math.min((L1b - H1b), (H2b - L2b)) > 0.25 * (L2b - L1b);
var bExpr12 = (bExpr12_1 && bExpr12_2) || bExpr12_3;
var bExpr13 = hhv(Math.max(1, H1b - L0b), xSrc).getValue(H1b) < (He - 0.15 * (He - L1));
var bExpr14 = 2.5 * Math.min(Heb - H1b, H2b - Heb) > Math.max(Heb - H1b, H2b - Heb);
var bExpr15 = 3 * Math.min(L1b - L0b, L3b - L2b) > Math.max(L1b - L0b, L3b - L2b);
var bExpr16 = (L0b != null) && (L0b <= 0) && (-L0b <= nNumBars);
var nHSDuration = 0;
if
(
bExpr1 &&
bExpr2 &&
bExpr3 &&
bExpr4 &&
bExpr5 &&
bExpr6 &&
bExpr7 &&
bExpr8 &&
bExpr9 &&
bExpr10 &&
bExpr11 &&
bExpr12 &&
bExpr13 &&
bExpr14 &&
bExpr15 &&
bExpr16
)
nHSDuration = Math.abs(L3b - L0b);
// ===============================================================
if (nHSDuration > fpMaxLength)
return;
if (nHSDuration > 0 && (nHSDuration - nPrev_HSDuration) > 1)
{
var pPatternLines = new Array();
pPatternLines.push(new Line(L0b, H1b));
pPatternLines.push(new Line(H1b, L1b));
pPatternLines.push(new Line(L1b, Heb));
pPatternLines.push(new Line(Heb, L2b));
pPatternLines.push(new Line(L2b, H2b));
pPatternLines.push(new Line(H2b, L3b));
var pCurrentPoints = new Array();
pCurrentPoints.push(nNumBars + L0b);
pCurrentPoints.push(nNumBars + L1b);
pCurrentPoints.push(nNumBars + L2b);
pCurrentPoints.push(nNumBars + L3b);
pCurrentPoints.push(nNumBars + H1b);
pCurrentPoints.push(nNumBars + H2b);
pCurrentPoints.push(nNumBars + Heb);
var color = fpLineColor;
var getColor = function(n)
{
var r = 2*n % 250;
var g = 250 - 2*n % 250;
var b = 5*n % 250;
return color = Color.RGB(r, g, b);
}
if (CheckForRepeatedPoints(pCurrentPoints))
color = getColor(color % 250 * nLinesCntr % 250);
DrawPatternLines(pPatternLines, xSrc, fpLineSize, color);
for(var pointKey in pCurrentPoints)
pUsedPoints.push(pCurrentPoints[pointKey]);
}
nPrev_HSDuration = nHSDuration;
}
function CheckForRepeatedPoints(pPoints)
{
for(var pointKey in pPoints)
{
for (var usedPointKey in pUsedPoints)
{
if (pUsedPoints[usedPointKey] == pPoints[pointKey])
return true;
}
}
return false;
}
function Line(nStart, nEnd)
{
this.Start = nStart;
this.End = nEnd;
}
function DrawLine(oLine, xSeries, nThikness, nColor, sKey)
{
drawLineRelative
(
oLine.Start,
xSeries.getValue(oLine.Start),
oLine.End,
xSeries.getValue(oLine.End),
PS_SOLID,
nThikness,
nColor,
sKey
)
}
function DrawPatternLines(pLines, xSeries, nThikness, nColor)
{
for (var key in pLines)
{
DrawLine(pLines[key], xSeries, nThikness, nColor, nLinesCntr++);
}
}
function LastBarIndexWhen(fExpr)
{
for (var i = 0; i < getCurrentBarCount(); i++)
{
if (fExpr(-i))
return - i;
}
return null;
}
function Int(nNumber)
{
return Math.floor(nNumber);
}
// Verify eSignal version
function verify()
{
var b = false;
if (getBuildNumber() < 779)
{
drawTextAbsolute(5, 35, "This study requires version 8.0 or later.",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "error");
drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=http://www.esignal.com/download/default.asp",
Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
null, 13, "upgrade");
return b;
}
else
{
b = true;
}
return b;
}