SDK Trading
Algorithmic Trading System Architecture is based on SDK trading and API Trading. Fintechee provides SDK Trading which includes Algorithms for Trading. Automated Trading is based on SDK trading. Fintechee has RESTful API and JS API(running on the browser) which help traders monitor the market movements and trade Forex automatically.
Please use our WEB Trader to implement your trading strategies.
More Materials
Constant Definition
var BROKER_NAME = {
DEMO: "Fintechee Demo"
}
var TIME_FRAME = {
M1: "M1",
M5: "M5",
M15: "M15",
M30: "M30",
H1: "H1",
H4: "H4",
D: "D",
W: "W",
M: "M"
}
var ORDER_TYPE = {
OP_BUY: "BUY",
OP_SELL: "SELL",
OP_BUYLIMIT: "BUY LIMIT",
OP_SELLLIMIT: "SELL LIMIT",
OP_BUYSTOP: "BUY STOP",
OP_SELLSTOP: "SELL STOP"
}
var WHERE_TO_RENDER = {
CHART_WINDOW: "CHART_WINDOW",
SEPARATE_WINDOW: "SEPARATE_WINDOW"
}
var DATA_NAME = {
TIME: "Time",
OPEN: "Open",
HIGH: "High",
LOW: "Low",
CLOSE: "Close",
HL2: "HL2",
HLC3: "HLC3",
HLCC4: "HLCC4"
}
var RENDER_TYPE = {
HISTOGRAM: "Histogram",
LINE: "Line",
ROUND: "Round",
DASHARRAY: "Dasharray"
}
var PARAMETER_TYPE = {
INTEGER: "Integer",
NUMBER: "Number",
BOOLEAN: "Boolean",
STRING: "String"
}
Common Function
function isNumeric (number) {
if (typeof number == "undefined" || number == null) return false
return !isNaN(parseFloat(number)) && isFinite(number);
}
function isInteger (number) {
return !isNaN(number) &&
parseInt(Number(number)) == number &&
!isNaN(parseInt(number, 10))
}
function sma (dataInput, dataOutput, calculatedLength, period) {
var i = calculatedLength
if (calculatedLength > 0) {
i--
} else {
for (var j = 0; j < period - 1; j++) {
dataOutput[j] = 0
}
i = period - 1
}
var sum = 0
for (var j = i - period + 1; j < i; j++) {
sum += dataInput[j]
}
for (var j = i; j < dataInput.length; j++) {
sum += dataInput[j]
dataOutput[j] = sum / period
sum -= dataInput[j - period + 1]
}
}
function ema (dataInput, dataOutput, calculatedLength, period) {
var i = calculatedLength
var smthFctr = 2.0 / (period + 1)
if (i == 0) {
dataOutput[0] = dataInput[0]
i++
} else if (i == 1) {
} else {
i--
}
while (i < dataInput.length) {
dataOutput[i] = dataInput[i] * smthFctr + dataOutput[i - 1] * (1 - smthFctr)
i++
}
}
function smma (dataInput, dataOutput, calculatedLength, period) {
var i = calculatedLength
var sum = 0
if (i > 0) {
i--
} else {
i = period - 1
for (var j = 1; j < period; j++) {
dataOutput[i - j] = 0
sum += dataInput[i - j]
}
sum += dataInput[i]
dataOutput[i] = sum / period
i++
}
while (i < dataInput.length) {
sum = dataOutput[i - 1] * period - dataOutput[i - 1] + dataInput[i]
dataOutput[i] = sum / period
i++
}
}
function lwma (dataInput, dataOutput, calculatedLength, period) {
var i = calculatedLength
if (i > 0) {
i--
} else {
for (var j = 0; j < period - 1; j++) {
dataOutput[j] = 0
}
i = period - 1
}
var sum = 0
var diffsum = 0
var weight = 0
for (var j = 1; j < period; j++) {
sum += dataInput[i - j] * (period - j)
diffsum += dataInput[i - j]
weight += j
}
weight += period
while (i < dataInput.length) {
sum += dataInput[i] * period
dataOutput[i] = sum / weight
diffsum += dataInput[i]
sum -= diffsum
diffsum -= dataInput[i - period + 1]
i++
}
}
Indicator Example
Simple Moving Average
registerIndicator("sma", "Simple Moving Average(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "sma")
var period = getIndiParameter(context, "period")
var shift = getIndiParameter(context, "shift")
var calculatedLength = getCalculatedLength(context)
sma(dataInput, dataOutput, calculatedLength, period)
if (shift != null && calculatedLength == 0) {
setIndiShift(context, "sma", shift)
}
},[{
name: "period",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "shift",
value: 0,
required: false,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "sma",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Exponential Moving Average
registerIndicator("ema", "Exponential Moving Average(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "ema")
var period = getIndiParameter(context, "period")
var shift = getIndiParameter(context, "shift")
var calculatedLength = getCalculatedLength(context)
ema(dataInput, dataOutput, calculatedLength, period)
if (shift != null && calculatedLength == 0) {
setIndiShift(context, "ema", shift)
}
},[{
name: "period",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "shift",
value: 0,
required: false,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "ema",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Smoothed Moving Average
registerIndicator("smma", "Smoothed Moving Average(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "smma")
var period = getIndiParameter(context, "period")
var shift = getIndiParameter(context, "shift")
var calculatedLength = getCalculatedLength(context)
smma(dataInput, dataOutput, calculatedLength, period)
if (shift != null && calculatedLength == 0) {
setIndiShift(context, "smma", shift)
}
},[{
name: "period",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "shift",
value: 0,
required: false,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "smma",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Linear Weighted Moving Average
registerIndicator("lwma", "Linear Weighted Moving Average(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "lwma")
var period = getIndiParameter(context, "period")
var shift = getIndiParameter(context, "shift")
var calculatedLength = getCalculatedLength(context)
lwma(dataInput, dataOutput, calculatedLength, period)
if (shift != null && calculatedLength == 0) {
setIndiShift(context, "lwma", shift)
}
},[{
name: "period",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "shift",
value: 0,
required: false,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "lwma",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
}],
WHERE_TO_RENDER.CHART_WINDOW)
MACD
registerIndicator("macd", "MACD(v1.01)", function (context) {
var dataInput = getDataInput(context, 0)
var dataFEMA = getDataOutput(context, "fastEMA")
var dataSEMA = getDataOutput(context, "slowEMA")
var dataOutputMain = getDataOutput(context, "main")
var dataOutputSignal = getDataOutput(context, "signal")
var fEMA = getIndiParameter(context, "fastEMA")
var sEMA = getIndiParameter(context, "slowEMA")
var sgnlSMA = getIndiParameter(context, "signalSMA")
var calculatedLength = getCalculatedLength(context)
var i = calculatedLength
if (i == 0) {
dataFEMA[0] = dataInput[0]
dataSEMA[0] = dataInput[0]
dataOutputMain[0] = 0
i++
} else if (i == 1) {
} else {
i--
}
ema(dataInput, dataFEMA, calculatedLength, fEMA)
ema(dataInput, dataSEMA, calculatedLength, sEMA)
while (i < dataInput.length) {
dataOutputMain[i] = dataFEMA[i] - dataSEMA[i]
i++
}
sma(dataOutputMain, dataOutputSignal, calculatedLength, sgnlSMA)
},[{
name: "fastEMA",
value: 12,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "slowEMA",
value: 26,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "signalSMA",
value: 9,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "main",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "#4EC2B4"
},{
name: "signal",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#CCCCCC"
},{
name: "fastEMA",
visible: false
},{
name: "slowEMA",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Relative Strength Index
registerIndicator("rsi", "Relative Strength Index(v1.01)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "rsi")
var dataOutputHL = getDataOutput(context, "rsiHighLevel")
var dataOutputLL = getDataOutput(context, "rsiLowLevel")
var gainTmp = getDataOutput(context, "gainTmp")
var lossTmp = getDataOutput(context, "lossTmp")
var period = getIndiParameter(context, "period")
var highLevel = getIndiParameter(context, "highLevel")
var lowLevel = getIndiParameter(context, "lowLevel")
var calculatedLength = getCalculatedLength(context)
var ptr = null
var ptr2 = null
var diff = null
var gain = null
var loss = null
var gainSum = 0
var lossSum = 0
if (calculatedLength > 0) {
ptr = calculatedLength - 1
ptr2 = calculatedLength - period
} else {
for (var i = 0; i < period; i++) {
dataOutput[i] = 0
dataOutputHL[i] = highLevel
dataOutputLL[i] = lowLevel
}
ptr = period
ptr2 = 1
while (ptr2 <= ptr) {
diff = dataInput[ptr2] - dataInput[ptr2 - 1]
if (0 < diff) {
gainSum += diff
} else {
lossSum -= diff
}
ptr2++
}
gain = gainSum / period
loss = lossSum / period
if (0 == (gain + loss)) {
dataOutput[ptr] = 0
} else {
dataOutput[ptr] = 100 * gain / (gain + loss)
}
dataOutputHL[ptr] = highLevel
dataOutputLL[ptr] = lowLevel
gainTmp[ptr] = gain
lossTmp[ptr] = loss
ptr++
}
while (ptr < dataInput.length) {
gain = gainTmp[ptr - 1] * (period - 1)
loss = lossTmp[ptr - 1] * (period - 1)
diff = dataInput[ptr] - dataInput[ptr - 1]
if (0 < diff) {
gain += diff
} else {
loss -= diff
}
gain = gain / period
loss = loss / period
if (0 == (gain + loss)) {
dataOutput[ptr] = 0
} else {
dataOutput[ptr] = 100 * gain / (gain + loss)
}
dataOutputHL[ptr] = highLevel
dataOutputLL[ptr] = lowLevel
gainTmp[ptr] = gain
lossTmp[ptr] = loss
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "highLevel",
value: 70,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [1, 100]
},{
name: "lowLevel",
value: 30,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "rsi",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "rsiHighLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "rsiLowLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "gainTmp",
visible: false
},{
name: "lossTmp",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Average True Range
registerIndicator("atr", "Average True Range(v1.0)", function (context) {
var dataInputClose = getDataInput(context, 0)
var dataInputHigh = getDataInput(context, 1)
var dataInputLow = getDataInput(context, 2)
var tmpLine = getDataOutput(context, "tmp")
var dataOutput = getDataOutput(context, "atr")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var i = calculatedLength
var high = null
var low = null
var prevClose = null
if (i > 0) {
i--
} else {
tmpLine[i] = 0
i = 1
}
while (i < dataInputClose.length) {
high = dataInputHigh[i]
low = dataInputLow[i]
prevClose = dataInputClose[i - 1]
tmpLine[i] = Math.max(high, prevClose) - Math.min(low, prevClose)
i++
}
sma(tmpLine, dataOutput, calculatedLength, period)
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
},{
name: DATA_NAME.HIGH,
index: 1
},{
name: DATA_NAME.LOW,
index: 2
}],
[{
name: "tmp",
visible: false
},{
name: "atr",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Average Directional Index
registerIndicator("adx", "Average Directional Index(v1.0)", function (context) {
var dataInputClose = getDataInput(context, 0)
var dataInputHigh = getDataInput(context, 1)
var dataInputLow = getDataInput(context, 2)
var tmpLine = getDataOutput(context, "tmp")
var plusSdiTmp = getDataOutput(context, "plusSdiTmp")
var minusSdiTmp = getDataOutput(context, "minusSdiTmp")
var dataOutputAdx = getDataOutput(context, "adx")
var dataOutputPlusDi = getDataOutput(context, "plusDi")
var dataOutputMinusDi = getDataOutput(context, "minusDi")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var i = calculatedLength
if (i > 0) {
i--
} else {
plusSdiTmp[i] = 0
minusSdiTmp[i] = 0
i = 1
}
var plusDM = null
var minusDM = null
var trueRange = null
var currH = null
var currL = null
var prevH = null
var prevL = null
var prevC = null
while (i < dataInputClose.length) {
currH = dataInputHigh[i]
currL = dataInputLow[i]
prevH = dataInputHigh[i - 1]
prevL = dataInputLow[i - 1]
prevC = dataInputClose[i - 1]
plusDM = currH - prevH
minusDM = prevL - currL
if (0 > plusDM) {
plusDM = 0
}
if (0 > minusDM) {
minusDM = 0
}
if (plusDM == minusDM) {
plusDM = 0
minusDM = 0
} else if (plusDM < minusDM) {
plusDM = 0
} else if (plusDM > minusDM) {
minusDM = 0
}
trueRange = Math.max(Math.abs(currH - currL), Math.abs(currH - prevC))
trueRange = Math.max(trueRange, Math.abs(currL - prevC))
if (0 == trueRange) {
plusSdiTmp[i] = 0
minusSdiTmp[i] = 0
}else{
plusSdiTmp[i] = 100 * plusDM / trueRange
minusSdiTmp[i] = 100 * minusDM / trueRange
}
i++
}
ema(plusSdiTmp, dataOutputPlusDi, calculatedLength, period)
ema(minusSdiTmp, dataOutputMinusDi, calculatedLength, period)
i = calculatedLength
if (i > 0) {
i--
}
while (i < dataInputClose.length) {
var tmp = Math.abs(dataOutputPlusDi[i] + dataOutputMinusDi[i])
if (0 == tmp) {
tmpLine[i] = 0
} else {
tmpLine[i] = 100 * (Math.abs(dataOutputPlusDi[i] - dataOutputMinusDi[i]) / tmp)
}
i++
}
ema(tmpLine, dataOutputAdx, calculatedLength, period)
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
},{
name: DATA_NAME.HIGH,
index: 1
},{
name: DATA_NAME.LOW,
index: 2
}],
[{
name: "adx",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#CCCCCC"
},{
name: "plusDi",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#4EC2B4"
},{
name: "minusDi",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#DE5029"
},{
name: "tmp",
visible: false
},{
name: "plusSdiTmp",
visible: false
},{
name: "minusSdiTmp",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Parabolic SAR
registerIndicator("sar", "Parabolic SAR(v1.01)", function (context) {
var dataInputHigh = getDataInput(context, 0)
var dataInputLow = getDataInput(context, 1)
var dataOutput = getDataOutput(context, "sar")
var dataOutputIsLong = getDataOutput(context, "isLong")
var dataOutputAf = getDataOutput(context, "af")
var dataOutputEp = getDataOutput(context, "ep")
var acceleration = getIndiParameter(context, "acceleration")
var afMax = getIndiParameter(context, "afMax")
var calculatedLength = getCalculatedLength(context)
var i = calculatedLength
var prevH = null
var prevL = null
var currH = null
var currL = null
var sar = null
var isLong = null
var af = acceleration
var ep = null
if (i > 0) {
i -= 2
prevH = dataInputHigh[i - 1]
prevL = dataInputLow[i - 1]
isLong = dataOutputIsLong[i]
sar = dataOutput[i]
af = dataOutputAf[i]
ep = dataOutputEp[i]
} else {
dataOutput[i] = 0
dataOutputIsLong[i] = true
dataOutputAf[i] = af
dataOutputEp[i] = 0
i = 1
prevH = dataInputHigh[i - 1]
prevL = dataInputLow[i - 1]
isLong = true
sar = prevL
ep = prevH
}
while (i < dataInputHigh.length) {
currH = dataInputHigh[i]
currL = dataInputLow[i]
if (isLong) {
if (currL <= sar) {
isLong = false
sar = Math.max(ep, currH, prevH)
dataOutput[i] = sar
af = acceleration
ep = currL
sar = sar + af * (ep - sar)
sar = Math.max(sar, currH, prevH)
} else {
dataOutput[i] = sar
if (currH > ep) {
ep = currH
if (af - dataOutputAf[i - 1] <= 0) {
af += acceleration
}
if (af > afMax) {
af = afMax
}
}
sar = sar + af * (ep - sar)
sar = Math.min(sar, currL, prevL)
}
} else {
if (currH >= sar) {
isLong = true
sar = Math.min(ep, currL, prevL)
dataOutput[i] = sar
af = acceleration
ep = currH
sar = sar + af * (ep - sar)
sar = Math.min(sar, currL, prevL)
} else {
dataOutput[i] = sar
if (currL < ep) {
ep = currL
if (af - dataOutputAf[i - 1] <= 0) {
af += acceleration
}
if (af > afMax) {
af = afMax
}
}
sar = sar + af * (ep - sar)
sar = Math.max(sar, currH, prevH)
}
}
dataOutputIsLong[i] = isLong
dataOutputAf[i] = af
dataOutputEp[i] = ep
i++
prevH = currH
prevL = currL
}
},[{
name: "acceleration",
value: 0.02,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0.01, 0.1]
},{
name: "afMax",
value: 0.2,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0.1, 1]
}],
[{
name: DATA_NAME.HIGH,
index: 0
},{
name: DATA_NAME.LOW,
index: 1
}],
[{
name: "sar",
visible: true,
renderType: RENDER_TYPE.ROUND,
color: "steelblue"
},{
name: "isLong",
visible: false
},{
name: "af",
visible: false
},{
name: "ep",
visible: false
}],
WHERE_TO_RENDER.CHART_WINDOW)
Stochastic Oscillator
registerIndicator("stochastic", "Stochastic Ocillator(v1.01)", function (context) {
var dataInputClose = getDataInput(context, 0)
var dataInputHigh = getDataInput(context, 1)
var dataInputLow = getDataInput(context, 2)
var highestTmp = getDataOutput(context, "highestTmp")
var lowestTmp = getDataOutput(context, "lowestTmp")
var dataOutputMain = getDataOutput(context, "main")
var dataOutputSignal = getDataOutput(context, "signal")
var kP = getIndiParameter(context, "KPeriod")
var slowing = getIndiParameter(context, "slowing")
var dP = getIndiParameter(context, "DPeriod")
var method = getIndiParameter(context, "method")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
var maxParam = Math.max(kP + slowing - 1, dP)
if (ptr > 0) {
ptr--
} else {
ptr = maxParam - 1
for (var i = 1; i < maxParam; i++) {
dataOutputMain[ptr - i] = 0
highestTmp[ptr - i] = 0
lowestTmp[ptr - i] = 0
}
}
while (ptr < dataInputClose.length) {
var tmp = null
var highest = -Number.MAX_VALUE
var lowest = Number.MAX_VALUE
for (var ptr2 = (ptr - kP + 1); ptr2 <= ptr; ptr2++){
tmp = dataInputHigh[ptr2]
if (highest < tmp) {
highest = tmp
}
tmp = dataInputLow[ptr2]
if (lowest > tmp) {
lowest = tmp
}
}
highestTmp[ptr] = highest
lowestTmp[ptr] = lowest
ptr++
}
ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = maxParam - 1
}
while (ptr < dataInputClose.length) {
var highestSum = 0
var lowestSum = 0
for (var ptr2 = ptr - slowing + 1; ptr2 <= ptr; ptr2++) {
highestSum += highestTmp[ptr2] - lowestTmp[ptr2]
lowestSum += dataInputClose[ptr2] - lowestTmp[ptr2]
}
if (0 == highestSum) {
dataOutputMain[ptr] = 100
}else{
dataOutputMain[ptr] = lowestSum / highestSum * 100
}
ptr++
}
if ("sma" == method) {
sma(dataOutputMain, dataOutputSignal, calculatedLength, dP)
} else if ("ema" == method) {
ema(dataOutputMain, dataOutputSignal, calculatedLength, dP)
} else if ("smma" == method) {
smma(dataOutputMain, dataOutputSignal, calculatedLength, dP)
} else {
lwma(dataOutputMain, dataOutputSignal, calculatedLength, dP)
}
},[{
name: "KPeriod",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "slowing",
value: 3,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "DPeriod",
value: 3,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "method",
value: "sma",
required: true,
type: PARAMETER_TYPE.STRING
}],
[{
name: DATA_NAME.CLOSE,
index: 0
},{
name: DATA_NAME.HIGH,
index: 1
},{
name: DATA_NAME.LOW,
index: 2
}],
[{
name: "main",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#DE5029"
},{
name: "signal",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#4EC2B4"
},{
name: "highestTmp",
visible: false
},{
name: "lowestTmp",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Alligator
registerIndicator("alligator", "A series of Bill Williams' indicators(v1.01)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutputJaws = getDataOutput(context, "jaws")
var dataOutputTeeth = getDataOutput(context, "teeth")
var dataOutputLips = getDataOutput(context, "lips")
var method = getIndiParameter(context, "method")
var jawsPeriod = getIndiParameter(context, "jawsPeriod")
var jawsShift = getIndiParameter(context, "jawsShift")
var teethPeriod = getIndiParameter(context, "teethPeriod")
var teethShift = getIndiParameter(context, "teethShift")
var lipsPeriod = getIndiParameter(context, "lipsPeriod")
var lipsShift = getIndiParameter(context, "lipsShift")
var calculatedLength = getCalculatedLength(context)
if ("smma" == method) {
smma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)
smma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)
smma(dataInput, dataOutputLips, calculatedLength, lipsPeriod)
} else if ("sma" == method) {
sma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)
sma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)
sma(dataInput, dataOutputLips, calculatedLength, lipsPeriod)
} else if("ema" == method) {
ema(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)
ema(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)
ema(dataInput, dataOutputLips, calculatedLength, lipsPeriod)
} else {
lwma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)
lwma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)
lwma(dataInput, dataOutputLips, calculatedLength, lipsPeriod)
}
if (calculatedLength == 0) {
setIndiShift(context, "jaws", jawsShift)
setIndiShift(context, "teeth", teethShift)
setIndiShift(context, "lips", lipsShift)
}
},[{
name: "jawsPeriod",
value: 13,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "jawsShift",
value: 8,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
},{
name: "teethPeriod",
value: 8,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "teethShift",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
},{
name: "lipsPeriod",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "lipsShift",
value: 3,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
},{
name: "method",
value: "smma",
required: true,
type: PARAMETER_TYPE.STRING
}],
[{
name: DATA_NAME.HL2,
index: 0
}],
[{
name: "jaws",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "teeth",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#4EC2B4"
},{
name: "lips",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#DE5029"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Fractals
registerIndicator("fractals", "Fractals(v1.0)", function (context) {
var dataInputHigh = getDataInput(context, 0)
var dataInputLow = getDataInput(context, 1)
var dataOutputUp = getDataOutput(context, "fractalsUp")
var dataOutputDown = getDataOutput(context, "fractalsDown")
var calculatedLength = getCalculatedLength(context)
var ptr = null
if (calculatedLength > 0) {
ptr = calculatedLength - 3
} else {
for (var i = 0; i < dataInputHigh.length; i++) {
dataOutputUp[i] = 0
dataOutputDown[i] = 0
}
ptr = 2
}
var bFound = false
var highest = null
var lowest = null
while (ptr < dataInputHigh.length - 2) {
bFound = false
highest = dataInputHigh[ptr]
if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {
bFound = true
dataOutputUp[ptr] = highest
}
if (!bFound && ptr >= 3) {
if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr - 3] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {
bFound = true
dataOutputUp[ptr] = highest
}
}
if (!bFound && ptr >= 4) {
if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr - 3] && highest > dataInputHigh[ptr - 4] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {
bFound = true
dataOutputUp[ptr] = highest
}
}
if (!bFound && ptr >= 5) {
if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr - 3] && highest > dataInputHigh[ptr - 4] && highest > dataInputHigh[ptr - 5] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {
bFound = true
dataOutputUp[ptr] = highest
}
}
if (!bFound && ptr >= 6) {
if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr - 3] && highest > dataInputHigh[ptr - 4] && highest > dataInputHigh[ptr - 5] && highest > dataInputHigh[ptr - 6] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {
bFound = true
dataOutputUp[ptr] = highest
}
}
bFound = false
lowest = dataInputLow[ptr]
if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {
bFound = true
dataOutputDown[ptr] = lowest
}
if (!bFound && ptr >= 3) {
if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr - 3] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {
bFound = true
dataOutputDown[ptr] = lowest
}
}
if (!bFound && ptr >= 4) {
if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr - 3] && lowest < dataInputLow[ptr - 4] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {
bFound = true
dataOutputDown[ptr] = lowest
}
}
if (!bFound && ptr >= 5) {
if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr - 3] && lowest < dataInputLow[ptr - 4] && lowest < dataInputLow[ptr - 5] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {
bFound = true
dataOutputDown[ptr] = lowest
}
}
if (!bFound && ptr >= 6) {
if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr - 3] && lowest < dataInputLow[ptr - 4] && lowest < dataInputLow[ptr - 5] && lowest < dataInputLow[ptr - 6] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {
bFound = true
dataOutputDown[ptr] = lowest
}
}
ptr++
}
},[],
[{
name: DATA_NAME.HIGH,
index: 0
},{
name: DATA_NAME.LOW,
index: 1
}],
[{
name: "fractalsUp",
visible: true,
renderType: RENDER_TYPE.ROUND,
color: "green"
},{
name: "fractalsDown",
visible: true,
renderType: RENDER_TYPE.ROUND,
color: "red"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Bollinger Bands
registerIndicator("bands", "Bollinger Bands(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "ma")
var dataOutputUpper = getDataOutput(context, "upper")
var dataOutputLower = getDataOutput(context, "lower")
var method = getIndiParameter(context, "method")
var period = getIndiParameter(context, "period")
var deviations = getIndiParameter(context, "deviations")
var shift = getIndiParameter(context, "shift")
var calculatedLength = getCalculatedLength(context)
if ("smma" == method) {
smma(dataInput, dataOutput, calculatedLength, period)
} else if("ema" == method) {
ema(dataInput, dataOutput, calculatedLength, period)
} else if ("lwma" == method) {
lwma(dataInput, dataOutput, calculatedLength, period)
} else {
sma(dataInput, dataOutput, calculatedLength, period)
}
var ptr = null
var ptr2 = null
if (calculatedLength > 0) {
ptr = calculatedLength - 1
} else {
for (var i = 0; i < period - 1; i++) {
dataOutputUpper[i] = 0
dataOutputLower[i] = 0
}
ptr = period - 1
}
var devVal, sum, midVal, tmp
while (ptr < dataInput.length) {
sum = 0
ptr2 = ptr - period + 1
midVal = dataOutput[ptr]
while (ptr2 <= ptr) {
tmp = dataInput[ptr2] - midVal
sum += tmp * tmp
ptr2++
}
devVal = deviations * Math.sqrt(sum / period)
dataOutputUpper[ptr] = midVal + devVal
dataOutputLower[ptr] = midVal - devVal
ptr++
}
if (calculatedLength == 0) {
setIndiShift(context, "ma", shift)
setIndiShift(context, "upper", shift)
setIndiShift(context, "lower", shift)
}
},[{
name: "period",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "deviations",
value: 2.0,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0, 10]
},{
name: "shift",
value: 0,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
},{
name: "method",
value: "sma",
required: true,
type: PARAMETER_TYPE.STRING
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "ma",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "upper",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "steelblue"
},{
name: "lower",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "steelblue"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Envelopes
registerIndicator("envelopes", "Envelopes(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "ma")
var dataOutputUpper = getDataOutput(context, "upper")
var dataOutputLower = getDataOutput(context, "lower")
var method = getIndiParameter(context, "method")
var period = getIndiParameter(context, "period")
var deviations = getIndiParameter(context, "deviations")
var shift = getIndiParameter(context, "shift")
var calculatedLength = getCalculatedLength(context)
if ("smma" == method) {
smma(dataInput, dataOutput, calculatedLength, period)
} else if("ema" == method) {
ema(dataInput, dataOutput, calculatedLength, period)
} else if ("lwma" == method) {
lwma(dataInput, dataOutput, calculatedLength, period)
} else {
sma(dataInput, dataOutput, calculatedLength, period)
}
var ptr = null
if (calculatedLength > 0) {
ptr = calculatedLength - 1
} else {
for (var i = 0; i < period - 1; i++) {
dataOutputUpper[i] = 0
dataOutputLower[i] = 0
}
ptr = period - 1
}
while (ptr < dataInput.length) {
dataOutputUpper[ptr] = (1 + deviations / 100) * dataOutput[ptr]
dataOutputLower[ptr] = (1 - deviations / 100) * dataOutput[ptr]
ptr++
}
if (calculatedLength == 0) {
setIndiShift(context, "ma", shift)
setIndiShift(context, "upper", shift)
setIndiShift(context, "lower", shift)
}
},[{
name: "period",
value: 5,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "deviations",
value: 0.05,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0, 10]
},{
name: "shift",
value: 0,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [-30, 30]
},{
name: "method",
value: "sma",
required: true,
type: PARAMETER_TYPE.STRING
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "ma",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "upper",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "steelblue"
},{
name: "lower",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "steelblue"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Accelerator Oscillator
registerIndicator("ac", "Accelerator Oscillator(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataUp = getDataOutput(context, "up")
var dataDown = getDataOutput(context, "down")
var dataFSMA = getDataOutput(context, "fastSMA")
var dataSSMA = getDataOutput(context, "slowSMA")
var dataOutputMain = getDataOutput(context, "main")
var dataOutputSignal = getDataOutput(context, "signal")
var fSMA = 5
var sSMA = 34
var sgnlSMA = 5
var calculatedLength = getCalculatedLength(context)
var i = calculatedLength
if (i == 0) {
dataFSMA[0] = dataInput[0]
dataSSMA[0] = dataInput[0]
dataOutputMain[0] = 0
i++
} else if (i == 1) {
} else {
i--
}
sma(dataInput, dataFSMA, calculatedLength, fSMA)
sma(dataInput, dataSSMA, calculatedLength, sSMA)
while (i < dataInput.length) {
dataOutputMain[i] = dataFSMA[i] - dataSSMA[i]
i++
}
sma(dataOutputMain, dataOutputSignal, calculatedLength, sgnlSMA)
i = calculatedLength
if (i == 0) {
i++
} else if (i == 1) {
} else {
i--
}
var prev, curr
while (i < dataInput.length) {
prev = dataOutputMain[i - 1] - dataOutputSignal[i - 1]
curr = dataOutputMain[i] - dataOutputSignal[i]
if (prev <= curr) {
dataUp[i] = curr
dataDown[i] = 0
} else {
dataUp[i] = 0
dataDown[i] = curr
}
i++
}
},[],
[{
name: DATA_NAME.HL2,
index: 0
}],
[{
name: "up",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "#6CBA81"
},{
name: "down",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "#ECAE93"
},{
name: "fastSMA",
visible: false
},{
name: "slowSMA",
visible: false
},{
name: "main",
visible: false
},{
name: "signal",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Awesome Oscillator
registerIndicator("ao", "Awesome Oscillator(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataUp = getDataOutput(context, "up")
var dataDown = getDataOutput(context, "down")
var dataFSMA = getDataOutput(context, "fastSMA")
var dataSSMA = getDataOutput(context, "slowSMA")
var fSMA = 5
var sSMA = 34
var sgnlSMA = 5
var calculatedLength = getCalculatedLength(context)
var i = calculatedLength
if (i == 0) {
dataFSMA[0] = dataInput[0]
dataSSMA[0] = dataInput[0]
i++
} else if (i == 1) {
} else {
i--
}
sma(dataInput, dataFSMA, calculatedLength, fSMA)
sma(dataInput, dataSSMA, calculatedLength, sSMA)
var prev, curr
while (i < dataInput.length) {
prev = dataFSMA[i - 1] - dataSSMA[i - 1]
curr = dataFSMA[i] - dataSSMA[i]
if (prev <= curr) {
dataUp[i] = curr
dataDown[i] = 0
} else {
dataUp[i] = 0
dataDown[i] = curr
}
i++
}
},[],
[{
name: DATA_NAME.HL2,
index: 0
}],
[{
name: "up",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "#6CBA81"
},{
name: "down",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "#ECAE93"
},{
name: "fastSMA",
visible: false
},{
name: "slowSMA",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Ichimoku Kinko Hyo
registerIndicator("ichimoku", "Ichimoku Kinko Hyo(v1.0)", function (context) {
var dataInputHigh = getDataInput(context, 0)
var dataInputLow = getDataInput(context, 1)
var dataInputClose = getDataInput(context, 2)
var dataOutputTenkan = getDataOutput(context, "tenkan")
var dataOutputKijun = getDataOutput(context, "kijun")
var dataOutputChikou = getDataOutput(context, "chikou")
var dataOutputSpanA = getDataOutput(context, "spana")
var dataOutputSpanB = getDataOutput(context, "spanb")
var tenkan = getIndiParameter(context, "tenkan")
var kijun = getIndiParameter(context, "kijun")
var senkou = getIndiParameter(context, "senkou")
var spanA;
if (kijun < tenkan) {
spanA = tenkan;
}else{
spanA = kijun;
}
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
var maxParam = Math.max(tenkan, kijun, spanA, senkou)
if (ptr > 0) {
ptr--
} else {
ptr = maxParam - 1
for (var i = 1; i < maxParam; i++) {
dataOutputTenkan[ptr - i] = 0
dataOutputKijun[ptr - i] = 0
dataOutputChikou[ptr - i] = 0
dataOutputSpanA[ptr - i] = 0
dataOutputSpanB[ptr - i] = 0
}
}
var ptr2, tmp, highest, lowest
while (ptr < dataInputHigh.length) {
tmp = null
highest = -Number.MAX_VALUE
lowest = Number.MAX_VALUE
ptr2 = ptr - tenkan + 1
while (ptr2 <= ptr) {
tmp = dataInputHigh[ptr2]
if (highest < tmp) {
highest = tmp
}
tmp = dataInputLow[ptr2]
if (lowest > tmp) {
lowest = tmp
}
ptr2++
}
dataOutputTenkan[ptr] = (highest + lowest) / 2
tmp = null
highest = -Number.MAX_VALUE
lowest = Number.MAX_VALUE
ptr2 = ptr - kijun + 1
while (ptr2 <= ptr) {
tmp = dataInputHigh[ptr2]
if (highest < tmp) {
highest = tmp
}
tmp = dataInputLow[ptr2]
if (lowest > tmp) {
lowest = tmp
}
ptr2++
}
dataOutputKijun[ptr] = (highest + lowest) / 2
dataOutputSpanA[ptr] = (dataOutputTenkan[ptr] + dataOutputKijun[ptr]) / 2
tmp = null
highest = -Number.MAX_VALUE
lowest = Number.MAX_VALUE
ptr2 = ptr - senkou + 1
while (ptr2 <= ptr) {
tmp = dataInputHigh[ptr2]
if (highest < tmp) {
highest = tmp
}
tmp = dataInputLow[ptr2]
if (lowest > tmp) {
lowest = tmp
}
ptr2++
}
dataOutputSpanB[ptr] = (highest + lowest) / 2
dataOutputChikou[ptr] = dataInputClose[ptr]
ptr++
}
if (calculatedLength == 0) {
setIndiShift(context, "chikou", -kijun)
setIndiShift(context, "spana", kijun)
setIndiShift(context, "spanb", kijun)
}
},[{
name: "tenkan",
value: 9,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "kijun",
value: 26,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "senkou",
value: 52,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.HIGH,
index: 0
},{
name: DATA_NAME.LOW,
index: 1
},{
name: DATA_NAME.CLOSE,
index: 2
}],
[{
name: "tenkan",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#DE5029"
},{
name: "kijun",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "chikou",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#4EC2B4"
},{
name: "spana",
visible: true,
renderType: RENDER_TYPE.ROUND,
color: "steelblue"
},{
name: "spanb",
visible: true,
renderType: RENDER_TYPE.ROUND,
color: "#CCCCCC"
}],
WHERE_TO_RENDER.CHART_WINDOW)
Bears Power
registerIndicator("bears", "Bears Power(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataInputLow = getDataInput(context, 1)
var dataOutput = getDataOutput(context, "bears")
var dataOutputEma = getDataOutput(context, "ema")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period - 1
for (var i = 0; i < period - 1; i++) {
dataOutput[i] = 0
}
}
ema(dataInput, dataOutputEma, calculatedLength, period)
while (ptr < dataInput.length) {
dataOutput[ptr] = dataInputLow[ptr] - dataOutputEma[ptr]
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
},{
name: DATA_NAME.LOW,
index: 1
}],
[{
name: "bears",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "steelblue"
},{
name: "ema",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Bulls Power
registerIndicator("bulls", "Bulls Power(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataInputHigh = getDataInput(context, 1)
var dataOutput = getDataOutput(context, "bulls")
var dataOutputEma = getDataOutput(context, "ema")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period - 1
for (var i = 0; i < period - 1; i++) {
dataOutput[i] = 0
}
}
ema(dataInput, dataOutputEma, calculatedLength, period)
while (ptr < dataInput.length) {
dataOutput[ptr] = dataInputHigh[ptr] - dataOutputEma[ptr]
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
},{
name: DATA_NAME.HIGH,
index: 1
}],
[{
name: "bulls",
visible: true,
renderType: RENDER_TYPE.HISTOGRAM,
color: "steelblue"
},{
name: "ema",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Momentum
registerIndicator("momentum", "Momentum(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "momentum")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period - 1
for (var i = 0; i < period - 1; i++) {
dataOutput[i] = 0
}
}
while (ptr < dataInput.length) {
dataOutput[ptr] = dataInput[ptr] * 100 / dataInput[ptr - period]
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
}],
[{
name: "momentum",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Commodity Channel Index
registerIndicator("cci", "Commodity Channel Index(v1.0)", function (context) {
var dataInput = getDataInput(context, 0)
var dataOutput = getDataOutput(context, "cci")
var dataOutputHL = getDataOutput(context, "cciHighLevel")
var dataOutputLL = getDataOutput(context, "cciLowLevel")
var dataOutputSma = getDataOutput(context, "sma")
var highLevel = getIndiParameter(context, "highLevel")
var lowLevel = getIndiParameter(context, "lowLevel")
var period = getIndiParameter(context, "period")
var cciFactor = 0.015 / period;
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period - 1
for (var i = 0; i < period - 1; i++) {
dataOutput[i] = 0
dataOutputHL[i] = highLevel
dataOutputLL[i] = lowLevel
}
}
sma(dataInput, dataOutputSma, calculatedLength, period)
var sum, tmp, ptr2
while (ptr < dataInput.length) {
sum = 0
ptr2 = ptr - period + 1
while (ptr2 <= ptr) {
sum += Math.abs(dataInput[ptr2] - dataOutputSma[ptr])
ptr2++
}
tmp = sum * cciFactor
if (0 == tmp) {
dataOutput[ptr] = 0
} else {
dataOutput[ptr] = (dataInput[ptr] - dataOutputSma[ptr]) / tmp
}
dataOutputHL[ptr] = highLevel
dataOutputLL[ptr] = lowLevel
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "highLevel",
value: 100,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [1, 200]
},{
name: "lowLevel",
value: -100,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [-200, -1]
}],
[{
name: DATA_NAME.HLC3,
index: 0
}],
[{
name: "cci",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "cciHighLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "cciLowLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "sma",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
DeMarker
registerIndicator("demarker", "DeMarker(v1.0)", function (context) {
var dataInputHigh = getDataInput(context, 0)
var dataInputLow = getDataInput(context, 1)
var dataOutput = getDataOutput(context, "demarker")
var dataOutputHL = getDataOutput(context, "highLevel")
var dataOutputLL = getDataOutput(context, "lowLevel")
var dataOutputMax = getDataOutput(context, "max")
var dataOutputMin = getDataOutput(context, "min")
var dataOutputMaMax = getDataOutput(context, "maMax")
var dataOutputMaMin = getDataOutput(context, "maMin")
var highLevel = getIndiParameter(context, "highLevel")
var lowLevel = getIndiParameter(context, "lowLevel")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = 1
dataOutputMax[0] = 0;
dataOutputMin[0] = 0;
}
var tmp = 0
while (ptr < dataInputHigh.length) {
tmp = dataInputHigh[ptr] - dataInputHigh[ptr - 1]
if (0 > tmp) {
tmp = 0
}
dataOutputMax[ptr] = tmp
tmp = dataInputLow[ptr - 1] - dataInputLow[ptr]
if (0 > tmp) {
tmp = 0
}
dataOutputMin[ptr] = tmp
ptr++
}
sma(dataOutputMax, dataOutputMaMax, calculatedLength, period)
sma(dataOutputMin, dataOutputMaMin, calculatedLength, period)
ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period - 1
for (var i = 0; i < period - 1; i++) {
dataOutput[i] = 0
dataOutputHL[i] = highLevel
dataOutputLL[i] = lowLevel
}
}
while (ptr < dataInputHigh.length) {
tmp = dataOutputMaMax[ptr] + dataOutputMaMin[ptr]
if (0 == tmp) {
dataOutput[ptr] = 0
} else {
dataOutput[ptr] = dataOutputMaMax[ptr] / tmp
}
dataOutputHL[ptr] = highLevel
dataOutputLL[ptr] = lowLevel
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "highLevel",
value: 0.7,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [0, 1]
},{
name: "lowLevel",
value: 0.3,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [0, 1]
}],
[{
name: DATA_NAME.HIGH,
index: 0
},{
name: DATA_NAME.LOW,
index: 1
}],
[{
name: "demarker",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "highLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "lowLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "max",
visible: false
},{
name: "min",
visible: false
},{
name: "maMax",
visible: false
},{
name: "maMin",
visible: false
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Williams’ Percent Range
registerIndicator("wpr", "Williams' Percent Range(v1.0)", function (context) {
var dataInputClose = getDataInput(context, 0)
var dataInputHigh = getDataInput(context, 1)
var dataInputLow = getDataInput(context, 2)
var dataOutput = getDataOutput(context, "wpr")
var dataOutputHL = getDataOutput(context, "wprHighLevel")
var dataOutputLL = getDataOutput(context, "wprLowLevel")
var highLevel = getIndiParameter(context, "highLevel")
var lowLevel = getIndiParameter(context, "lowLevel")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period - 1
for (var i = 0; i < period - 1; i++) {
dataOutput[i] = 0
dataOutputHL[i] = highLevel
dataOutputLL[i] = lowLevel
}
}
while (ptr < dataInputClose.length) {
var maxArr = []
for (var i = 0; i < period; i++) {
maxArr.push(dataInputHigh[ptr - i])
}
var highest = Math.max.apply(null, maxArr)
var minArr = []
for (var i = 0; i < period; i++) {
minArr.push(dataInputLow[ptr - i])
}
var lowest = Math.min.apply(null, minArr)
if (0 == highest - lowest) {
dataOutput[ptr] = 0
} else {
dataOutput[ptr] = -100 * (highest - dataInputClose[ptr]) / (highest - lowest)
}
dataOutputHL[ptr] = highLevel
dataOutputLL[ptr] = lowLevel
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "highLevel",
value: -20,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [-100, 0]
},{
name: "lowLevel",
value: -80,
required: false,
type: PARAMETER_TYPE.NUMBER,
range: [-100, 0]
}],
[{
name: DATA_NAME.CLOSE,
index: 0
},{
name: DATA_NAME.HIGH,
index: 1
},{
name: DATA_NAME.LOW,
index: 2
}],
[{
name: "wpr",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "steelblue"
},{
name: "wprHighLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
},{
name: "wprLowLevel",
visible: true,
renderType: RENDER_TYPE.DASHARRAY,
color: "#AAAAAA"
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
Relative Vigor Index
registerIndicator("rvi", "Relative Vigor Index(v1.0)", function (context) {
var dataInputOpen = getDataInput(context, 0)
var dataInputHigh = getDataInput(context, 1)
var dataInputLow = getDataInput(context, 2)
var dataInputClose = getDataInput(context, 3)
var dataOutputMain = getDataOutput(context, "main")
var dataOutputSignal = getDataOutput(context, "signal")
var period = getIndiParameter(context, "period")
var calculatedLength = getCalculatedLength(context)
var ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period + 2
for (var i = 0; i < period + 2; i++) {
dataOutputMain[i] = 0
dataOutputSignal[i] = 0
}
}
var upTmp, downTmp, tmp, dTmp
while (ptr < dataInputOpen.length) {
tmp = 0
dTmp = 0
for (var i = ptr; i > ptr - period; i--) {
upTmp = ((dataInputClose[i] - dataInputOpen[i]) + 2 * (dataInputClose[i - 1] - dataInputOpen[i - 1]) + 2 * (dataInputClose[i - 2] - dataInputOpen[i - 2]) + (dataInputClose[i - 3] - dataInputOpen[i - 3])) / 6
downTmp = ((dataInputHigh[i] - dataInputLow[i]) + 2 * (dataInputHigh[i - 1] - dataInputLow[i - 1]) + 2 * (dataInputHigh[i - 2] - dataInputLow[i - 2]) + (dataInputHigh[i - 3] - dataInputLow[i - 3])) / 6
tmp += upTmp
dTmp += downTmp
}
if (0 == dTmp) {
dataOutputMain[ptr] = tmp
} else {
dataOutputMain[ptr] = tmp / dTmp
}
ptr++
}
ptr = calculatedLength
if (ptr > 0) {
ptr--
} else {
ptr = period + 2
}
while (ptr < dataInputOpen.length) {
dataOutputSignal[ptr] = (dataOutputMain[ptr] + 2 * dataOutputMain[ptr - 1] + 2 * dataOutputMain[ptr - 2] + dataOutputMain[ptr - 3]) / 6
ptr++
}
},[{
name: "period",
value: 14,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
[{
name: DATA_NAME.OPEN,
index: 0
},{
name: DATA_NAME.HIGH,
index: 1
},{
name: DATA_NAME.LOW,
index: 2
},{
name: DATA_NAME.CLOSE,
index: 3
}],
[{
name: "main",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#6CBA81"
},{
name: "signal",
visible: true,
renderType: RENDER_TYPE.LINE,
color: "#ECAE93"
}],
WHERE_TO_RENDER.SEPARATE_WINDOW)
EA Example
A test EA based on SMA
registerEA(
"sample_using_sma",
"A test EA based on sma(v1.02)",
[{ // parameters
name: "period",
value: 20,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
}],
function (context) { // Init()
var account = getAccount(context, 0)
var brokerName = getBrokerNameOfAccount(account)
var accountId = getAccountIdOfAccount(account)
var symbolName = "EUR/USD"
getQuotes (context, brokerName, accountId, symbolName)
window.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
var period = getEAParameter(context, "period")
window.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "sma", [{
name: "period",
value: period
}])
},
function (context) { // Deinit()
delete window.currTime
delete window.chartHandle
delete window.indiHandle
},
function (context) { // OnTick()
var arrTime = getData(context, window.chartHandle, DATA_NAME.TIME)
if (typeof window.currTime == "undefined") {
window.currTime = arrTime[arrTime.length - 1]
} else if (window.currTime != arrTime[arrTime.length - 1]) {
window.currTime = arrTime[arrTime.length - 1]
} else {
return
}
var account = getAccount(context, 0)
var brokerName = getBrokerNameOfAccount(account)
var accountId = getAccountIdOfAccount(account)
var symbolName = "EUR/USD"
var arrClose = getData(context, window.chartHandle, DATA_NAME.CLOSE)
var arrSma = getData(context, window.indiHandle, "sma")
var ask = getAsk(context, brokerName, accountId, symbolName)
var bid = getBid(context, brokerName, accountId, symbolName)
var limitPrice = 0.0003
var stopPrice = 0.0003
var volume = 0.01
if (arrClose[arrClose.length - 3] < arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] > arrSma[arrSma.length - 2]) {
sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUYLIMIT, ask-limitPrice, 0, volume, ask+limitPrice, bid-3*stopPrice, "", 0, 0)
} else if (arrClose[arrClose.length - 3] > arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] < arrSma[arrSma.length - 2]) {
sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELLLIMIT, bid+limitPrice, 0, volume, bid-limitPrice, ask+3*stopPrice, "", 0, 0)
}
}
)
Trading Arbitrage
registerEA(
"sample_trading_arbitrage",
"Two accounts signed up on the different servers are required to trade arbitrage. Additionally please make sure that you have signed in to both accounts and logged out from the accounts in investor mode.(v1.02)",
[],// parameters
function (context) { // Init()
var account1 = getAccount(context, 0)
var account2 = getAccount(context, 1)
var acc1 = {
brokerName: getBrokerNameOfAccount(account1),
accountId: getAccountIdOfAccount(account1),
symbolName: "EUR/USD"
}
var acc2 = {
brokerName: getBrokerNameOfAccount(account2),
accountId: getAccountIdOfAccount(account2),
symbolName: "EUR/USD"
}
getQuotes (context, acc1.brokerName, acc1.accountId, acc1.symbolName)
getQuotes (context, acc2.brokerName, acc2.accountId, acc2.symbolName)
window.acc1 = acc1
window.acc2 = acc2
},
function (context) { // Deinit()
delete window.currTime
delete window.acc1
delete window.acc2
},
function (context) { // OnTick()
var currTime = new Date().getTime()
if (typeof window.currTime == "undefined") {
window.currTime = currTime
} else if (window.currTime <= currTime - 1000) {
window.currTime = currTime
} else {
return
}
var acc1 = window.acc1
var acc2 = window.acc2
var ask1 = getAsk(context, acc1.brokerName, acc1.accountId, acc1.symbolName)
var ask2 = getAsk(context, acc2.brokerName, acc2.accountId, acc2.symbolName)
var bid1 = getBid(context, acc1.brokerName, acc1.accountId, acc1.symbolName)
var bid2 = getBid(context, acc2.brokerName, acc2.accountId, acc2.symbolName)
var volume = 0.01
if (ask1 < bid2) {
var tradeNum = getOpenTradesListLength(context)
var acc1TradeId = null
var acc2TradeId = null
for (var i = tradeNum - 1; i >= 0; i--) {
var trade = getOpenTrade(context, i)
var brokerName = getBrokerName(trade)
var accountId = getAccountId(trade)
var tradeId = getTradeId(trade)
var orderType = getOrderType(trade)
if (brokerName == acc1.brokerName && accountId == acc1.accountId && orderType == ORDER_TYPE.OP_SELL) {
acc1TradeId = tradeId
}
if (brokerName == acc2.brokerName && accountId == acc2.accountId && orderType == ORDER_TYPE.OP_BUY) {
acc2TradeId = tradeId
}
}
if (acc1TradeId == null) {
sendOrder(acc1.brokerName, acc1.accountId, acc1.symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
} else {
closeTrade(acc1.brokerName, acc1.accountId, acc1TradeId, 0, 0)
}
if (acc2TradeId == null) {
sendOrder(acc2.brokerName, acc2.accountId, acc2.symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
} else {
closeTrade(acc2.brokerName, acc2.accountId, acc2TradeId, 0, 0)
}
} else if (ask2 < bid1) {
var tradeNum = getOpenTradesListLength(context)
var acc1TradeId = null
var acc2TradeId = null
for (var i = tradeNum - 1; i >= 0; i--) {
var trade = getOpenTrade(context, i)
var brokerName = getBrokerName(trade)
var accountId = getAccountId(trade)
var tradeId = getTradeId(trade)
var orderType = getOrderType(trade)
if (brokerName == acc2.brokerName && accountId == acc2.accountId && orderType == ORDER_TYPE.OP_SELL) {
acc2TradeId = tradeId
}
if (brokerName == acc1.brokerName && accountId == acc1.accountId && orderType == ORDER_TYPE.OP_BUY) {
acc1TradeId = tradeId
}
}
if (acc2TradeId == null) {
sendOrder(acc2.brokerName, acc2.accountId, acc2.symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
} else {
closeTrade(acc2.brokerName, acc2.accountId, acc2TradeId, 0, 0)
}
if (acc1TradeId == null) {
sendOrder(acc1.brokerName, acc1.accountId, acc1.symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
} else {
closeTrade(acc1.brokerName, acc1.accountId, acc1TradeId, 0, 0)
}
}
}
)
Neural Network
registerEA(
"sample_training_neuron_model",
"A test EA to train neuron model(v1.02)",
[{ // parameters
name: "period",
value: 20,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "inputNum",
value: 20,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "hiddenNum",
value: 50,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "diffPrice",
value: 0.0001,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0, 10]
}],
function (context) { // Init()
var account = getAccount(context, 0)
var brokerName = getBrokerNameOfAccount(account)
var accountId = getAccountIdOfAccount(account)
var symbolName = "EUR/USD"
window.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
var period = getEAParameter(context, "period")
window.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
name: "period",
value: period
}])
},
function (context) { // Deinit()
var period = getEAParameter(context, "period")
var inputNum = getEAParameter(context, "inputNum")
var hiddenNum = getEAParameter(context, "hiddenNum")
var arrOpen = getData(context, window.chartHandle, DATA_NAME.OPEN)
var arrClose = getData(context, window.chartHandle, DATA_NAME.CLOSE)
var arrRsi = getData(context, window.indiHandle, "rsi")
if (arrRsi.length <= period + 1) return
if (inputNum + period - 1 > arrRsi.length) throw new Error("No enough data.")
// extend the prototype chain
Perceptron.prototype = new synaptic.Network()
Perceptron.prototype.constructor = Perceptron
var myPerceptron = new Perceptron(inputNum, hiddenNum, 1)
var myTrainer = new synaptic.Trainer(myPerceptron)
var diffPrice = getEAParameter(context, "diffPrice")
var trainingSet = []
var longCount = 0
var shortCount = 0
for (var i = period - 1; i < arrRsi.length - inputNum; i++) {
if (arrClose[i * inputNum + inputNum] - arrOpen[i * inputNum + inputNum] > diffPrice) {
var input = []
for (var j = 0; j < inputNum; j++) {
input.push(arrRsi[i * inputNum + j] / 100)
}
trainingSet.push({
input: input,
output: [0]
})
longCount++
} else if (arrOpen[i * inputNum + inputNum] - arrClose[i * inputNum + inputNum] > diffPrice) {
var input = []
for (var j = 0; j < inputNum; j++) {
input.push(arrRsi[i * inputNum + j] / 100)
}
trainingSet.push({
input: input,
output: [1]
})
shortCount++
}
}
myTrainer.train(trainingSet)
// We use localstorage.reservedZone to store the neural network network.
// Please don't change the name "reservedZone" or your data stored in this zone will be removed while the version is updated.
if (typeof localStorage.reservedZone == "undefined") {
localStorage.reservedZone = JSON.stringify({sample_training_neuron_model: myPerceptron.toJSON()})
} else {
var reservedZone = JSON.parse(localStorage.reservedZone)
reservedZone.sample_training_neuron_model = myPerceptron.toJSON()
localStorage.reservedZone = JSON.stringify(reservedZone)
}
printMessage(longCount + ", " + shortCount)
printMessage(JSON.stringify(trainingSet))
printMessage(JSON.stringify(myPerceptron.toJSON()))
delete window.chartHandle
delete window.indiHandle
},
function (context) { // OnTick()
}
)
registerEA(
"sample_run_neuron_model",
"A test EA to run neuron model(v1.03)",
[{ // parameters
name: "period",
value: 20,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "inputNum",
value: 20,
required: true,
type: PARAMETER_TYPE.INTEGER,
range: [1, 100]
},{
name: "threshold",
value: 0.3,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0, 1]
},{
name: "takeProfit",
value: 0.0001,
required: true,
type: PARAMETER_TYPE.NUMBER,
range: [0, 100]
}],
function (context) { // Init()
// We use localstorage.reservedZone to store the neural network network.
// Please don't change the name "reservedZone" or your data stored in this zone will be removed while the version is updated.
if (typeof localStorage.reservedZone == "undefined") return
var reservedZone = JSON.parse(localStorage.reservedZone)
if (typeof reservedZone.sample_training_neuron_model == "undefined") return
window.myPerceptron = synaptic.Network.fromJSON(reservedZone.sample_training_neuron_model)
var account = getAccount(context, 0)
var brokerName = getBrokerNameOfAccount(account)
var accountId = getAccountIdOfAccount(account)
var symbolName = "EUR/USD"
getQuotes (context, brokerName, accountId, symbolName)
window.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
var period = getEAParameter(context, "period")
window.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
name: "period",
value: period
}])
},
function (context) { // Deinit()
delete window.currTime
delete window.chartHandle
delete window.indiHandle
delete window.myPerceptron
},
function (context) { // OnTick()
var arrTime = getData(context, window.chartHandle, DATA_NAME.TIME)
if (typeof window.currTime == "undefined") {
window.currTime = arrTime[arrTime.length - 1]
} else if (window.currTime != arrTime[arrTime.length - 1]) {
window.currTime = arrTime[arrTime.length - 1]
} else {
return
}
var account = getAccount(context, 0)
var brokerName = getBrokerNameOfAccount(account)
var accountId = getAccountIdOfAccount(account)
var symbolName = "EUR/USD"
var period = getEAParameter(context, "period")
var inputNum = getEAParameter(context, "inputNum")
var threshold = getEAParameter(context, "threshold")
var takeProfit = getEAParameter(context, "takeProfit")
var arrRsi = getData(context, window.indiHandle, "rsi")
if (inputNum + period - 1 > arrRsi.length) throw new Error("No enough data.")
var input = []
for (var i = arrRsi.length - inputNum - 1; i < arrRsi.length - 1; i++) {
input.push(arrRsi[i] / 100)
}
var result = window.myPerceptron.activate(input)[0]
printMessage(result)
var ask = getAsk(context, brokerName, accountId, symbolName)
var bid = getBid(context, brokerName, accountId, symbolName)
var volume = 0.01
if (result < 0.5 - threshold) {
sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, ask+takeProfit, bid-3*takeProfit, "", 0, 0)
} else if (result > 0.5 + threshold) {
sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, bid-takeProfit, ask+3*takeProfit, "", 0, 0)
}
}
)