[
  {
    "path": "AI/aitrader_12_eurusd.json",
    "content": "{\"modelTopology\":{\"class_name\":\"Sequential\",\"config\":{\"name\":\"sequential_20\",\"layers\":[{\"class_name\":\"Conv1D\",\"config\":{\"filters\":6,\"kernel_initializer\":{\"class_name\":\"VarianceScaling\",\"config\":{\"scale\":1,\"mode\":\"fan_in\",\"distribution\":\"normal\",\"seed\":null}},\"kernel_regularizer\":null,\"kernel_constraint\":null,\"kernel_size\":[20],\"strides\":[20],\"padding\":\"valid\",\"dilation_rate\":[1],\"activation\":\"relu\",\"use_bias\":true,\"bias_initializer\":{\"class_name\":\"Zeros\",\"config\":{}},\"bias_regularizer\":null,\"activity_regularizer\":null,\"bias_constraint\":null,\"name\":\"conv1d_Conv1D20\",\"trainable\":true,\"batch_input_shape\":[null,20,1],\"dtype\":\"float32\"}},{\"class_name\":\"Flatten\",\"config\":{\"name\":\"flatten_Flatten20\",\"trainable\":true}},{\"class_name\":\"Dense\",\"config\":{\"units\":2,\"activation\":\"softmax\",\"use_bias\":true,\"kernel_initializer\":{\"class_name\":\"VarianceScaling\",\"config\":{\"scale\":1,\"mode\":\"fan_in\",\"distribution\":\"normal\",\"seed\":null}},\"bias_initializer\":{\"class_name\":\"Zeros\",\"config\":{}},\"kernel_regularizer\":null,\"bias_regularizer\":null,\"activity_regularizer\":null,\"kernel_constraint\":null,\"bias_constraint\":null,\"name\":\"dense_Dense20\",\"trainable\":true}}]},\"keras_version\":\"tfjs-layers 2.0.0\",\"backend\":\"tensor_flow.js\"},\"format\":\"layers-model\",\"generatedBy\":\"TensorFlow.js tfjs-layers v2.0.0\",\"convertedBy\":null,\"weightsManifest\":[{\"paths\":[\"./aitrader_12_eurusd.weights.bin\"],\"weights\":[{\"name\":\"conv1d_Conv1D20/kernel\",\"shape\":[20,1,6],\"dtype\":\"float32\"},{\"name\":\"conv1d_Conv1D20/bias\",\"shape\":[6],\"dtype\":\"float32\"},{\"name\":\"dense_Dense20/kernel\",\"shape\":[6,2],\"dtype\":\"float32\"},{\"name\":\"dense_Dense20/bias\",\"shape\":[2],\"dtype\":\"float32\"}]}]}"
  },
  {
    "path": "AI/aitrader_12_gbpusd.json",
    "content": "{\"modelTopology\":{\"class_name\":\"Sequential\",\"config\":{\"name\":\"sequential_8\",\"layers\":[{\"class_name\":\"Conv1D\",\"config\":{\"filters\":6,\"kernel_initializer\":{\"class_name\":\"VarianceScaling\",\"config\":{\"scale\":1,\"mode\":\"fan_in\",\"distribution\":\"normal\",\"seed\":null}},\"kernel_regularizer\":null,\"kernel_constraint\":null,\"kernel_size\":[20],\"strides\":[20],\"padding\":\"valid\",\"dilation_rate\":[1],\"activation\":\"relu\",\"use_bias\":true,\"bias_initializer\":{\"class_name\":\"Zeros\",\"config\":{}},\"bias_regularizer\":null,\"activity_regularizer\":null,\"bias_constraint\":null,\"name\":\"conv1d_Conv1D8\",\"trainable\":true,\"batch_input_shape\":[null,20,1],\"dtype\":\"float32\"}},{\"class_name\":\"Flatten\",\"config\":{\"name\":\"flatten_Flatten8\",\"trainable\":true}},{\"class_name\":\"Dense\",\"config\":{\"units\":2,\"activation\":\"softmax\",\"use_bias\":true,\"kernel_initializer\":{\"class_name\":\"VarianceScaling\",\"config\":{\"scale\":1,\"mode\":\"fan_in\",\"distribution\":\"normal\",\"seed\":null}},\"bias_initializer\":{\"class_name\":\"Zeros\",\"config\":{}},\"kernel_regularizer\":null,\"bias_regularizer\":null,\"activity_regularizer\":null,\"kernel_constraint\":null,\"bias_constraint\":null,\"name\":\"dense_Dense8\",\"trainable\":true}}]},\"keras_version\":\"tfjs-layers 2.0.0\",\"backend\":\"tensor_flow.js\"},\"format\":\"layers-model\",\"generatedBy\":\"TensorFlow.js tfjs-layers v2.0.0\",\"convertedBy\":null,\"weightsManifest\":[{\"paths\":[\"./aitrader_12_gbpusd.weights.bin\"],\"weights\":[{\"name\":\"conv1d_Conv1D8/kernel\",\"shape\":[20,1,6],\"dtype\":\"float32\"},{\"name\":\"conv1d_Conv1D8/bias\",\"shape\":[6],\"dtype\":\"float32\"},{\"name\":\"dense_Dense8/kernel\",\"shape\":[6,2],\"dtype\":\"float32\"},{\"name\":\"dense_Dense8/bias\",\"shape\":[2],\"dtype\":\"float32\"}]}]}"
  },
  {
    "path": "AI/readme.md",
    "content": "AI Trader\nhttps://www.fintechee.com/ai-trader/\n\n\nWe will provide some AI models for free.\n\n\nOur models are designed for long-term timeframes, meaning signals are generated less frequently. However, this approach is the least risky and has the potential to deliver a 30-50% annual profit, excluding compound interest.\n\n\nWe store backtesting reports in this repo: https://github.com/fintechees/AI-Trader-Backtesting-Report\n\n\nIf you are interested in purchasing our paid AI model, please contact us: admin@fintechee.com.\n\n\nCampaign!!\n\nWe will provide an Expert Advisor (EA) to the individual trader. Please refer to the M2Report.zip(The file is password-protected, the password is fuckcndictator) file for performance details.\n\nThe individual trader is required to have a FIX API account.\nWe will set up a dedicated platform for this trader, linked to a single account.\nThe monthly fee is $100 USD, which includes cloud service costs.\n"
  },
  {
    "path": "EA/Arbitrage/README.md",
    "content": "We will add more details to introduce how to use this EA.\n"
  },
  {
    "path": "EA/Arbitrage/fintechee_external_arbitrage.js",
    "content": "registerEA(\n  \"fintechee_external_arbitrage\",\n  \"A test EA to trade arbitrage based on the price difference between Fintechee and the external trading platform(v1.0)\",\n  [{\n    name: \"externalSys\",\n    value: \"Oanda\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }, {\n    name: \"autoLoad\",\n    value: true,\n    required: true,\n    type: PARAMETER_TYPE.BOOLEAN,\n    range: null\n  }, {\n    name: \"autoSave\",\n    value: true,\n    required: true,\n    type: PARAMETER_TYPE.BOOLEAN,\n    range: null\n  }, {\n    name: \"backgroundColor\",\n    value: \"#dfc29a\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function (context) { // Init()\n    var externalSys = getEAParameter(context, \"externalSys\")\n\n    if (externalSys == \"Oanda\") {\n      if (typeof window.pluginForOanda == \"undefined\") {\n        throw new Error(\"You need to run plugin_for_oanda(you can find it in our Github repo -- Plugin-for-Oanda) first. If you have run the plugin, please be patient with the loading time.\")\n      }\n    } else {\n      throw new Error(\"The specific external trading platform is not supported.\")\n    }\n\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n\n    var currTime = new Date().getTime()\n\n    if (typeof window.arbitrage == \"undefined\") {\n      window.arbitrage = {\n        autoLoad: getEAParameter(context, \"autoLoad\"),\n        autoSave: getEAParameter(context, \"autoSave\"),\n        bgColor: getEAParameter(context, \"backgroundColor\"),\n        latestDay: new Date().getDay(),\n        latestSaveTime: currTime,\n        quotes: [],\n        statistics: [],\n        loadStatistics: function () {\n          if (typeof localStorage.reservedZone != \"undefined\") {\n            var reservedZone = JSON.parse(localStorage.reservedZone)\n\n            if (typeof reservedZone.arbitrageStatistics != \"undefined\" && typeof reservedZone.arbitrageStatistics.statistics != \"undefined\") {\n              if (new Date(reservedZone.arbitrageStatistics.latestSaveTime).getDay() < window.latestDay) {\n                for (var i in reservedZone.arbitrageStatistics.statistics) {\n                  var statistics = reservedZone.arbitrageStatistics.statistics[i]\n                  this.statistics[statistics.symbolName] = {\n                    h: [],\n                    h2: [],\n                    ph: statistics.h,\n                    ph2: statistics.h2\n                  }\n                  for (var j = 0; j <= 23; j++) {\n                    this.statistics[statistics.symbolName].h.push(0)\n                    this.statistics[statistics.symbolName].h2.push(0)\n                  }\n                }\n              } else {\n                for (var i in reservedZone.arbitrageStatistics.statistics) {\n                  var statistics = reservedZone.arbitrageStatistics.statistics[i]\n                  this.statistics[statistics.symbolName] = {\n                    h: statistics.h,\n                    h2: statistics.h2,\n                    ph: statistics.ph,\n                    ph2: statistics.ph2\n                  }\n                }\n              }\n            }\n          }\n        },\n        saveStatistics: function () {\n          var reservedZone = {}\n\n          if (typeof localStorage.reservedZone != \"undefined\") {\n            reservedZone = JSON.parse(localStorage.reservedZone)\n          }\n\n          reservedZone.arbitrageStatistics = {\n            latestSaveTime: new Date().getTime(),\n            statistics: []\n          }\n\n          for (var i in this.statistics) {\n            reservedZone.arbitrageStatistics.statistics.push({\n              symbolName: i,\n              h: this.statistics[i].h,\n              h2: this.statistics[i].h2,\n              ph: this.statistics[i].ph,\n              ph2: this.statistics[i].ph2\n            })\n          }\n\n          localStorage.reservedZone = JSON.stringify(reservedZone)\n        },\n        count: function (symbolName, hour) {\n          this.statistics[symbolName].h[hour]++\n        },\n        count2: function (symbolName, hour) {\n          this.statistics[symbolName].h2[hour]++\n        },\n        chartLibUrl: \"https://cdn.jsdelivr.net/npm/chart.js@2.8.0\",\n        bLibLoaded: false,\n        loadChartJsLib: function () {\n          var tags = document.getElementsByTagName(\"script\")\n          for (var i = tags.length - 1; i >= 0; i--) {\n            if (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == this.chartLibUrl) {\n              this.bLibLoaded = true\n              break\n            }\n          }\n\n          var that = this\n\n          if (!this.bLibLoaded) {\n            var script = document.createElement(\"script\")\n            script.id = \"chartjs_lib\"\n\n            document.body.appendChild(script)\n            script.onload = function () {\n              that.bLibLoaded = true\n              that.initArbitrageChart()\n              popupMessage(\"The ChartJS lib has been loaded successfully!\")\n            }\n            script.onerror = function () {\n              that.bLibLoaded = false\n              popupErrorMessage(\"Failed to load the ChartJS lib.\")\n            }\n            script.async = true\n            script.src = this.chartLibUrl\n          } else {\n            this.initArbitrageChart()\n          }\n        },\n        currentChartSymbolName: \"EUR/USD\",\n        initArbitrageChart: function () {\n          var ctx = document.getElementById(\"arbitrage_chart\").getContext(\"2d\")\n          var statistics = this.statistics[this.currentChartSymbolName]\n\n          var labels = []\n          var data = []\n          var data2 = []\n          var pdata = []\n          var pdata2 = []\n          for (var i = 0; i <= 23; i++) {\n            labels.push(i + \"\")\n            data.push(statistics.h[i])\n            data2.push(statistics.h2[i])\n            pdata.push(statistics.ph[i])\n            pdata2.push(statistics.ph2[i])\n          }\n\n          this.arbitrageChart = new Chart(ctx, {\n              type: \"line\",\n              data: {\n                  labels: labels,\n                  datasets: [{\n                      label: this.currentChartSymbolName + \"(F-X)\", // F stands for Fintechee, X stands for eXternal sys\n                      backgroundColor: \"rgba(255,255,255,0)\",\n                      borderColor: \"#DB2828\",\n                      data: data\n                  }, {\n                      label: this.currentChartSymbolName + \"(X-F)\",\n                      backgroundColor: \"rgba(255,255,255,0)\",\n                      borderColor: \"#21BA45\",\n                      data: data2\n                  }, {\n                      label: this.currentChartSymbolName + \"(F-X)\",\n                      backgroundColor: \"rgba(255,255,255,0)\",\n                      borderColor: \"#DB2828\",\n                      borderDash: [2, 3],\n                      data: pdata\n                  }, {\n                      label: this.currentChartSymbolName + \"(X-F)\",\n                      backgroundColor: \"rgba(255,255,255,0)\",\n                      borderColor: \"#21BA45\",\n                      borderDash: [2, 3],\n                      data: pdata2\n                  }]\n              },\n              options: {\n                responsive: true,\n                maintainAspectRatio: false\n              }\n          })\n        },\n        updateArbitrageChart: function (symbolName, bAll, hour) {\n          if (bAll) {\n            for (var i = 0; i <= 23; i++) {\n              this.arbitrageChart.data.datasets[0].data[i] = this.statistics[symbolName].h[i]\n              this.arbitrageChart.data.datasets[2].data[i] = this.statistics[symbolName].ph[i]\n            }\n          } else {\n            this.arbitrageChart.data.datasets[0].data[hour] = this.statistics[symbolName].h[hour]\n          }\n\n          this.arbitrageChart.update()\n        },\n        updateArbitrageChart2: function (symbolName, bAll, hour) {\n          if (bAll) {\n            for (var i = 0; i <= 23; i++) {\n              this.arbitrageChart.data.datasets[1].data[i] = this.statistics[symbolName].h2[i]\n              this.arbitrageChart.data.datasets[3].data[i] = this.statistics[symbolName].ph2[i]\n            }\n          } else {\n            this.arbitrageChart.data.datasets[1].data[hour] = this.statistics[symbolName].h2[hour]\n          }\n\n          this.arbitrageChart.update()\n        },\n        updatePrevArbitrage: function () {\n          for (var i in this.statistics) {\n            this.statistics[i].ph = this.statistics[i].h\n            this.statistics[i].ph2 = this.statistics[i].h2\n            this.statistics[i].h = []\n            this.statistics[i].h2 = []\n\n            for (var j = 0; j <= 23; j++) {\n              this.statistics[i].h.push(0)\n              this.statistics[i].h2.push(0)\n            }\n          }\n        },\n        chartIds: [],\n        initDashboard: function () {\n          if (typeof $(\"#arbitrage_chart_dashboard\").html() == \"undefined\") {\n            var arbitrageChartPanel = '<div id=\"arbitrage_chart_dashboard\" style=\"background:' + this.bgColor + ';height:100%\">' +\n              '<div class=\"row\" style=\"background:' + this.bgColor + ';text-align:center\">' +\n                '<div class=\"ui buttons\">' +\n                  // '<div class=\"ui button\" style=\"background:' + this.bgColor + '\" id=\"btn_show_arbitrage_prices\">List</div>' +\n                  '<div class=\"ui button\" style=\"background:' + this.bgColor + '\" id=\"btn_load_arbitrage_statistics\">Load</div>' +\n                  '<div class=\"ui button\" style=\"background:' + this.bgColor + '\" id=\"btn_save_arbitrage_statistics\">Save</div>' +\n                '</div>' +\n              '</div>' +\n              '<div class=\"row\">' +\n                '<table id=\"arbitrage_prices\" class=\"cell-border\">' +\n                '</table>' +\n              '</div>' +\n              '<div class=\"row\">' +\n                '<div class=\"chart-container\" style=\"background:' + this.bgColor + ';position:relative;height:35vh\">' +\n                  '<canvas id=\"arbitrage_chart\"></canvas>' +\n                '</div>' +\n              '</div>' +\n            '</div>'\n\n            var arbitragePricesPanel = '<div class=\"ui fullscreen modal\" id=\"arbitrage_prices_dashboard\">' +\n              '<div class=\"content\">' +\n              '</div>' +\n            '</div>'\n\n            $(\"#reserved_zone\").append(arbitragePricesPanel)\n\n            if (getLayoutId() != 3) {\n        \t\t\tchangeLayout(3)\n        \t\t}\n\n        \t\tthis.chartIds = getLayout(2)\n        \t\tfor (var i in this.chartIds) {\n        \t\t\tmoveLayout(this.chartIds[i], 1)\n        \t\t}\n\n            embedHtml(arbitrageChartPanel, 2)\n          }\n\n          var that = this\n\n          if (!$.fn.dataTable.isDataTable(\"#arbitrage_prices\")) {\n      \t\t\tthis.pricesTable = $(\"#arbitrage_prices\").DataTable({\n      \t\t\t\tdata: [],\n      \t\t\t\tcolumns: [\n                {\n                  title: \"Instruments\"\n                }, {\n                  title: \"Fintechee-Ext\",\n                  render: function (data, type, row) {\n      \t\t\t\t\t\t\tif (data > 0) {\n      \t\t\t\t\t\t\t\treturn '<p style = \"background:#21BA45;color:#FFFFFF\" >' + data + '</p>'\n      \t\t\t\t\t\t\t} else {\n      \t\t\t\t\t\t\t\treturn '<p style = \"background:' + that.bgColor + ';color:#DB2828\" >' + data + '</p>'\n      \t\t\t\t\t\t\t}\n      \t\t\t\t\t\t}\n      \t\t\t\t\t}, {\n                  title: \"Ext-Fintechee\",\n                  render: function (data, type, row) {\n                    if (data > 0) {\n                      return '<p style = \"background:#21BA45;color:#FFFFFF\" >' + data + '</p>'\n                    } else {\n                      return '<p style = \"background:' + that.bgColor + ';color:#DB2828\" >' + data + '</p>'\n                    }\n      \t\t\t\t\t\t}\n      \t\t\t\t\t}, {\n                  title: \"External\"\n                }, {\n                  title: \"Op\"\n                }\n      \t\t\t\t],\n              headerCallback: function (thead, data, start, end, display) {\n                $(thead).css(\"background-color\", that.bgColor)\n              },\n              rowCallback: function (row, data, index) {\n                $(\"td\", row).css(\"background-color\", that.bgColor)\n              },\n              ordering: false,\n              searching: false,\n              bPaginate: false,\n              bLengthChange: false,\n              bFilter: false,\n              bInfo: false,\n              scrollY: \"50vh\",\n              scrollCollapse: true,\n              paging: false,\n              columnDefs: [\n                {width: \"20%\", targets: 0, className: \"dt-body-center\"},\n                {width: \"20%\", targets: 1, className: \"dt-body-right\"},\n                {width: \"20%\", targets: 2, className: \"dt-body-right\"},\n                {width: \"20%\", targets: 3, className: \"dt-body-right\"},\n                {width: \"20%\", targets: 4, className: \"dt-body-center\"},\n                {width: \"20%\", targets: [0], className: \"dt-head-center\"},\n                {width: \"20%\", targets: [1], className: \"dt-head-center\"},\n                {width: \"20%\", targets: [2], className: \"dt-head-center\"},\n                {width: \"20%\", targets: [3], className: \"dt-head-center\"},\n                {width: \"20%\", targets: [4], className: \"dt-head-center\"},\n                {\n                  targets: -1,\n                  data: null,\n                  defaultContent: '<button id=\"btn_check_arbitrage\" class=\"ui button\" style=\"padding:0;background:' + this.bgColor + '\"><i class=\"tachometer alternate blue icon\"></i></button>' +\n                                  '<button id=\"btn_sell\" class=\"ui button\" style=\"padding:0;background:' + this.bgColor + ';color:#DB2828\">S</button>' +\n                                  '<button id=\"btn_buy\" class=\"ui button\" style=\"padding:0;background:' + this.bgColor + ';color:#21BA45\">B</button>'\n                }\n              ]\n      \t\t\t})\n\n            for (var i in this.quotes) {\n              $(\"#arbitrage_prices\").DataTable().row.add([\n                i,\n                \"\",\n                \"\",\n                \"\",\n                \"\"\n              ]).draw(false)\n            }\n\n            $(\"#arbitrage_prices tbody\").on(\"click\", \"[id*=btn_check_arbitrage]\", function () {\n              if (typeof that.pricesTable != \"undefined\") {\n                var data = that.pricesTable.row($(this).parents(\"tr\")).data()\n                if (typeof data == \"undefined\") {\n                  data = that.pricesTable.row($(this)).data()\n                }\n\n                that.currentChartSymbolName = data[0]\n                that.arbitrageChart.data.datasets[0].label = that.currentChartSymbolName + \"(F-X)\" // F stands for Fintechee, O stands for eXternal sys\n                that.arbitrageChart.data.datasets[1].label = that.currentChartSymbolName + \"(X-F)\"\n                that.arbitrageChart.data.datasets[2].label = that.currentChartSymbolName + \"(F-X)\"\n                that.arbitrageChart.data.datasets[3].label = that.currentChartSymbolName + \"(X-F)\"\n                that.updateArbitrageChart(data[0], true, -1)\n                that.updateArbitrageChart2(data[0], true, -1)\n              }\n            })\n\n            $(\"#btn_load_arbitrage_statistics\").on(\"click\", function () {\n              that.loadStatistics()\n            })\n\n            $(\"#btn_save_arbitrage_statistics\").on(\"click\", function () {\n              that.saveStatistics()\n            })\n      \t\t}\n\n          for (var i in this.quotes) {\n            this.statistics[i] = {\n              h: [],\n              h2: [],\n              ph: [],\n              ph2: []\n            }\n\n            for (var j = 0; j <= 23; j++) {\n              this.statistics[i].h.push(0)\n              this.statistics[i].h2.push(0)\n              this.statistics[i].ph.push(0)\n              this.statistics[i].ph2.push(0)\n            }\n          }\n        }\n      }\n    }\n\n    if (externalSys == \"Oanda\") {\n      window.arbitrage.quotes = window.pluginForOanda.quotes\n    }\n\n    window.arbitrage.initDashboard()\n\t\twindow.arbitrage.loadChartJsLib()\n\n    if (window.arbitrage.autoLoad) {\n      window.arbitrage.loadStatistics()\n    }\n\n    for (var i in window.arbitrage.quotes) {\n      getQuotes(context, brokerName, accountId, i.replace(\"_\", \"/\"))\n    }\n  },\n  function (context) { // Deinit()\n    embedHtml(\"\", 2)\n\n\t\tfor (var i in window.arbitrage.chartIds) {\n\t\t\tmoveLayout(window.arbitrage.chartIds[i], 2)\n\t\t}\n\n    if (!window.arbitrage.bLibLoaded) {\n\t\t\tvar script = document.getElementById(\"chartjs_lib\")\n\t\t\tscript.remove()\n\t\t}\n  },\n  function (context) { // OnTick()\n    var externalSys = getEAParameter(context, \"externalSys\")\n\n    if (externalSys == \"Oanda\") {\n      if (typeof window.pluginForOanda == \"undefined\") {\n        return\n      }\n    } else {\n      return\n    }\n\n    var currTime = new Date().getTime()\n    var hour = new Date(currTime).getHours()\n    var day = new Date(currTime).getDay()\n\n    if (window.arbitrage.autoSave && currTime - window.arbitrage.latestSaveTime > 60000) {\n      window.arbitrage.saveStatistics()\n      window.arbitrage.latestSaveTime = currTime\n    }\n\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n\n    var currentTick = getCurrentTick(context)\n    var symbolName = currentTick.symbolName\n    var askFintechee = currentTick.ask\n    var bidFintechee = currentTick.bid\n\n    if (window.arbitrage.latestDay != day) {\n      window.arbitrage.updatePrevArbitrage()\n      window.arbitrage.updateArbitrageChart(symbolName, true, -1)\n      window.arbitrage.updateArbitrageChart2(symbolName, true, -1)\n      window.arbitrage.latestDay = day\n    }\n\n    if (window.arbitrage.quotes[symbolName] == null) return\n\n    var askExt = window.arbitrage.quotes[symbolName].ask\n    var bidExt = window.arbitrage.quotes[symbolName].bid\n\n    if (askFintechee != null && bidFintechee != null && askExt != null && bidExt != null) {\n      var table = $('#arbitrage_prices').DataTable()\n      var tb = $('#arbitrage_prices').dataTable()\n\n      table.columns().eq(0).each(function (index) {\n        if (index == 0) {\n          var column = table.column(index).data()\n          for (var i in column) {\n            if (isNaN(i)) continue\n\n            var rowId = parseInt(i)\n\n            if (column[i] == symbolName) {\n              tb.fnUpdate(Math.round((bidExt - askFintechee) * 100000) / 100000, rowId, 1, false, false)\n              tb.fnUpdate(Math.round((bidFintechee - askExt) * 100000) / 100000, rowId, 2, false, false)\n              tb.fnUpdate(Math.round((askExt + bidExt) / 2 * 100000) / 100000, rowId, 3, false, false)\n              break\n            }\n          }\n        }\n      })\n\n      if (bidExt > askFintechee) {\n        window.arbitrage.count(symbolName, hour)\n        if (symbolName == window.arbitrage.currentChartSymbolName) {\n          window.arbitrage.updateArbitrageChart(symbolName, false, hour)\n        }\n        // var msg = new Date() + \" \" + symbolName + \" Chance!! Ext Bid: \" + bidExt + \", Fintechee Ask: \" + askFintechee + \", Difference: \" + (bidExt - askFintechee) + \"\\n\"\n        // printMessage(msg)\n      }\n      if (bidFintechee > askExt) {\n        window.arbitrage.count2(symbolName, hour)\n        if (symbolName == window.arbitrage.currentChartSymbolName) {\n          window.arbitrage.updateArbitrageChart2(symbolName, false, hour)\n        }\n        // var msg = new Date() + \" \" + symbolName + \" Chance!! Fintechee Bid: \" + bidFintechee + \", Ext Ask: \" + askExt + \", Difference: \" + (bidFintechee - askExt) + \"\\n\"\n        // printMessage(msg)\n      }\n    }\n  }\n)\n"
  },
  {
    "path": "EA/Arbitrage/guide_for_fintechee_external_arbitrage.txt",
    "content": "To utilize this EA and display the statistics panel regarding the frequencies of arbitrage opportunities, you must first open the “plugin_for_oanda”.\n\nOnce you have launched the “plugin_for_oanda”, a panel will appear to set up your Oanda account ID and token information. Simply input the necessary information and hit the “Connect” button. If you successfully log in, two popup messages will appear.\n\nFollowing this, proceed to run “fintechee_external_arbitrage”. You can specify Oanda as your external trading platform. The price variance is derived from two streaming quotes: one from Fintechee’s FIX API engine, and the other from the external trading platform.\n\nThe statistical analysis is based on hourly tallies, with most of the price variation peaks occurring during 12pm-4pm (UTC). If the numerical value appears as green, it denotes that the price variance is positive, and consequently, an arbitrage opportunity has arisen.\n\n"
  },
  {
    "path": "EA/Arbitrage/sample_trading_arbitrage.js",
    "content": "registerEA(\n\t\t\"sample_trading_arbitrage\",\n\t\t\"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.04)\",\n\t\t[],// parameters\n\t\tfunction (context) { // Init()\n\t\t\tvar account1 = getAccount(context, 0)\n\t\t\tvar account2 = getAccount(context, 1)\n\n\t\t\tvar acc1 = {\n\t\t\t\tbrokerName: getBrokerNameOfAccount(account1),\n\t\t\t\taccountId: getAccountIdOfAccount(account1),\n\t\t\t\tsymbolName: \"EUR/USD\"\n\t\t\t}\n\t\t\tvar acc2 = {\n\t\t\t\tbrokerName: getBrokerNameOfAccount(account2),\n\t\t\t\taccountId: getAccountIdOfAccount(account2),\n\t\t\t\tsymbolName: \"EUR/USD\"\n\t\t\t}\n\n\t\t\tgetQuotes (context, acc1.brokerName, acc1.accountId, acc1.symbolName)\n\t\t\tgetQuotes (context, acc2.brokerName, acc2.accountId, acc2.symbolName)\n\n\t\t\tcontext.acc1 = acc1\n\t\t\tcontext.acc2 = acc2\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t\tvar currTime = new Date().getTime()\n\t\t\tif (typeof context.currTime == \"undefined\") {\n\t\t\t\tcontext.currTime = currTime\n\t\t\t} else if (context.currTime <= currTime - 1000) {\n\t\t\t\tcontext.currTime = currTime\n\t\t\t} else {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar acc1 = context.acc1\n\t\t\tvar acc2 = context.acc2\n\n\t\t\tvar ask1 = null\n\t\t\tvar ask2 = null\n\t\t\tvar bid1 = null\n\t\t\tvar bid2 = null\n\n\t\t\ttry {\n\t\t\t\task1 = getAsk(context, acc1.brokerName, acc1.accountId, acc1.symbolName)\n\t\t\t\task2 = getAsk(context, acc2.brokerName, acc2.accountId, acc2.symbolName)\n\t\t\t\tbid1 = getBid(context, acc1.brokerName, acc1.accountId, acc1.symbolName)\n\t\t\t\tbid2 = getBid(context, acc2.brokerName, acc2.accountId, acc2.symbolName)\n\t\t\t} catch (e) {\n\t\t\t\t// This try-catch is used to bypass the \"error throw\" when you start the EA too early to call getAsk or getBid(at that time, bid or ask may be not ready yet.)\n\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar volume = 0.01\n\n\t\t\tif (ask1 < bid2) {\n\t\t\t\tvar tradeNum = getOpenTradesListLength(context)\n\n\t\t\t\tvar acc1TradeId = null\n\t\t\t\tvar acc2TradeId = null\n\n\t\t\t\tfor (var i = tradeNum - 1; i >= 0; i--) {\n\t\t\t\t\tvar trade = getOpenTrade(context, i)\n\t\t\t\t\tvar brokerName = getBrokerName(trade)\n\t\t\t\t\tvar accountId = getAccountId(trade)\n\t\t\t\t\tvar tradeId = getTradeId(trade)\n\t\t\t\t\tvar orderType = getOrderType(trade)\n\t\t\t\t\tif (brokerName == acc1.brokerName && accountId == acc1.accountId && orderType == ORDER_TYPE.OP_SELL) {\n\t\t\t\t\t\tacc1TradeId = tradeId\n\t\t\t\t\t}\n\t\t\t\t\tif (brokerName == acc2.brokerName && accountId == acc2.accountId && orderType == ORDER_TYPE.OP_BUY) {\n\t\t\t\t\t\tacc2TradeId = tradeId\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (acc1TradeId == null) {\n\t\t\t\t\tsendOrder(acc1.brokerName, acc1.accountId, acc1.symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\t\t} else {\n\t\t\t\t\tcloseTrade(acc1.brokerName, acc1.accountId, acc1TradeId, 0, 0)\n\t\t\t\t}\n\n\t\t\t\tif (acc2TradeId == null) {\n\t\t\t\t\tsendOrder(acc2.brokerName, acc2.accountId, acc2.symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\t\t} else {\n\t\t\t\t\tcloseTrade(acc2.brokerName, acc2.accountId, acc2TradeId, 0, 0)\n\t\t\t\t}\n\t\t\t} else if (ask2 < bid1) {\n\t\t\t\tvar tradeNum = getOpenTradesListLength(context)\n\n\t\t\t\tvar acc1TradeId = null\n\t\t\t\tvar acc2TradeId = null\n\n\t\t\t\tfor (var i = tradeNum - 1; i >= 0; i--) {\n\t\t\t\t\tvar trade = getOpenTrade(context, i)\n\t\t\t\t\tvar brokerName = getBrokerName(trade)\n\t\t\t\t\tvar accountId = getAccountId(trade)\n\t\t\t\t\tvar tradeId = getTradeId(trade)\n\t\t\t\t\tvar orderType = getOrderType(trade)\n\t\t\t\t\tif (brokerName == acc2.brokerName && accountId == acc2.accountId && orderType == ORDER_TYPE.OP_SELL) {\n\t\t\t\t\t\tacc2TradeId = tradeId\n\t\t\t\t\t}\n\t\t\t\t\tif (brokerName == acc1.brokerName && accountId == acc1.accountId && orderType == ORDER_TYPE.OP_BUY) {\n\t\t\t\t\t\tacc1TradeId = tradeId\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (acc2TradeId == null) {\n\t\t\t\t\tsendOrder(acc2.brokerName, acc2.accountId, acc2.symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\t\t} else {\n\t\t\t\t\tcloseTrade(acc2.brokerName, acc2.accountId, acc2TradeId, 0, 0)\n\t\t\t\t}\n\n\t\t\t\tif (acc1TradeId == null) {\n\t\t\t\t\tsendOrder(acc1.brokerName, acc1.accountId, acc1.symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\t\t} else {\n\t\t\t\t\tcloseTrade(acc1.brokerName, acc1.accountId, acc1TradeId, 0, 0)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Built-in/README.md",
    "content": "The EAs in this folder will be updated automatically when you open the WEB trader.\n\nIf you customize the EAs in this folder, please rename them to avoid being overwritten.\n"
  },
  {
    "path": "EA/Built-in/sample_using_rsi.js",
    "content": "registerEA(\n\t\t\"sample_using_rsi\",\n\t\t\"A test EA based on rsi(v1.01)\",\n\t\t[{ // parameters\n\t\t\tname: \"period\",\n\t\t\tvalue: 20,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tgetQuotes (context, brokerName, accountId, symbolName)\n\t\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)\n\t\t\tvar period = getEAParameter(context, \"period\")\n\t\t\tcontext.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, \"rsi\", [{\n\t\t\t\tname: \"period\",\n\t\t\t\tvalue: period\n\t\t\t}])\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t\tvar arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n\t\t\tif (typeof context.currTime == \"undefined\") {\n\t\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\n\t\t\t} else if (context.currTime != arrTime[arrTime.length - 1]) {\n\t\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\n\t\t\t} else {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tvar arrRsi = getData(context, context.indiHandle, \"rsi\")\n\n\t\t\tvar ask = null\n\t\t\tvar bid = null\n\t\t\ttry {\n\t\t\t\task = getAsk(context, brokerName, accountId, symbolName)\n\t\t\t\tbid = getBid(context, brokerName, accountId, symbolName)\n\t\t\t} catch (e) {\n\t\t\t\t// This try-catch is used to bypass the \"error throw\" when you start the EA too early to call getAsk or getBid(at that time, bid or ask may be not ready yet.)\n\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar limitPrice = 0.0003\n\t\t\tvar stopPrice = 0.0003\n\t\t\tvar volume = 0.01\n\n\t\t\tif (30 < arrRsi[arrRsi.length - 3] && 30 > arrRsi[arrRsi.length - 2]) {\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUYLIMIT, ask-limitPrice, 0, volume, ask+limitPrice, bid-3*stopPrice, \"\", 0, 0)\n\t\t\t} else if (70 > arrRsi[arrRsi.length - 3] && 70 < arrRsi[arrRsi.length - 2]) {\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELLLIMIT, bid+limitPrice, 0, volume, bid-limitPrice, ask+3*stopPrice, \"\", 0, 0)\n\t\t\t}\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Built-in/sample_using_sma.js",
    "content": "registerEA(\n\t\t\"sample_using_sma\",\n\t\t\"A test EA based on sma(v1.04)\",\n\t\t[{ // parameters\n\t\t\tname: \"period\",\n\t\t\tvalue: 20,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tgetQuotes (context, brokerName, accountId, symbolName)\n\t\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)\n\t\t\tvar period = getEAParameter(context, \"period\")\n\t\t\tcontext.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, \"sma\", [{\n\t\t\t\tname: \"period\",\n\t\t\t\tvalue: period\n\t\t\t}])\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t\tvar arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n\t\t\tif (typeof context.currTime == \"undefined\") {\n\t\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\n\t\t\t} else if (context.currTime != arrTime[arrTime.length - 1]) {\n\t\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\n\t\t\t} else {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tvar arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)\n\t\t\tvar arrSma = getData(context, context.indiHandle, \"sma\")\n\n\t\t\tvar ask = null\n\t\t\tvar bid = null\n\t\t\ttry {\n\t\t\t\task = getAsk(context, brokerName, accountId, symbolName)\n\t\t\t\tbid = getBid(context, brokerName, accountId, symbolName)\n\t\t\t} catch (e) {\n\t\t\t\t// This try-catch is used to bypass the \"error throw\" when you start the EA too early to call getAsk or getBid(at that time, bid or ask may be not ready yet.)\n\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar limitPrice = 0.0003\n\t\t\tvar stopPrice = 0.0003\n\t\t\tvar volume = 0.01\n\n\t\t\tif (arrClose[arrClose.length - 3] < arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] > arrSma[arrSma.length - 2]) {\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUYLIMIT, ask-limitPrice, 0, volume, ask+limitPrice, bid-3*stopPrice, \"\", 0, 0)\n\t\t\t} else if (arrClose[arrClose.length - 3] > arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] < arrSma[arrSma.length - 2]) {\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELLLIMIT, bid+limitPrice, 0, volume, bid-limitPrice, ask+3*stopPrice, \"\", 0, 0)\n\t\t\t}\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Chaos/chaos.js",
    "content": "registerEA(\n  \"chaos\",\n  \"An EA based on Chaos theory(v1.0)\",\n  [{\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n    required: true,\n    type: \"String\",\n    range: null,\n    step: null\n  }, {\n    name: \"volume\",\n    value: 0.01,\n    required: true,\n    type: \"Number\",\n    range: [0.01, 1.0],\n    step: null\n  }, {\n    name: \"timeFrame\",\n    value: \"H4\",\n    required: true,\n    type: \"String\",\n    range: null,\n    step: null\n  }],\n  function (context) { // Init()\n    // Bill Williams' Chaos Trading Strategy is amazing.\n    // This EA is based on the theory written in his book \"Trading Chaos\".\n\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n    var timeFrame = getEAParameter(context, \"timeFrame\")\n\n    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n    context.fractalsHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"fractals\", [])\n    context.alligatorHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"alligator\", [{\n      name: \"jawsPeriod\", value: 13}, {name: \"jawsShift\", value: 8}, {\n      name: \"teethPeriod\", value: 8}, {name: \"teethShift\", value: 5}, {\n      name: \"lipsPeriod\", value: 5}, {name: \"lipsShift\", value: 3}, {\n      name: \"method\", value: \"smma\"}])\n    context.aoHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"ao\", [])\n    context.acHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"ac\", [])\n\n    context.chaos = {\n      fractalsUpIdx: -1,\n      fractalsDownIdx: -1,\n      fractalsUp: 0,\n      fractalsDown: 0,\n      fractalsUpTriggered: false,\n      fractalsDownTriggered: false,\n      getFractalsSignal: function (arrUp, arrDown) {\n        var cursor = arrUp.length - 4\n        var latestUpIdx = -1\n        var latestDownIdx = -1\n\n        while (cursor >= 0) {\n          if (arrUp[cursor] != 0) {\n            if (latestUpIdx == -1) {\n              latestUpIdx = cursor\n            }\n            if (latestDownIdx != -1) {\n              break\n            }\n          }\n          if (arrDown[cursor] != 0) {\n            if (latestDownIdx == -1) {\n              latestDownIdx = cursor\n            }\n            if (latestUpIdx != -1) {\n              break\n            }\n          }\n          cursor--\n        }\n\n        if (latestUpIdx != -1 && latestDownIdx != -1) {\n          if (latestUpIdx != this.fractalsUpIdx) {\n            this.fractalsUpIdx = latestUpIdx\n            this.fractalsUpTriggered = false\n          }\n          if (latestDownIdx != this.fractalsDownIdx) {\n            this.fractalsDownIdx = latestDownIdx\n            this.fractalsDownTriggered = false\n          }\n          this.fractalsUp = arrUp[latestUpIdx]\n          this.fractalsDown = arrDown[latestDownIdx]\n        }\n      },\n      checkFractalsSignal: function (arrTeeth, currTick) {\n        if (this.fractalsUp > 0) {\n          if (!this.fractalsUpTriggered) {\n            if (currTick > this.fractalsUp && currTick > arrTeeth[arrTeeth.length - 6]) {\n              this.fractalsUpTriggered = true\n              return 1\n            }\n          }\n        }\n\n        if (this.fractalsDown > 0) {\n          if (!this.fractalsDownTriggered) {\n            if (currTick < this.fractalsDown && currTick < arrTeeth[arrTeeth.length - 6]) {\n              this.fractalsDownTriggered = true\n              return 0\n            }\n          }\n        }\n\n        return -1\n      },\n      aoUpIdx1: -1,\n      aoDownIdx1: -1,\n      aoUp1: 0,\n      aoDown1: 0,\n      aoUpTriggered1: false,\n      aoDownTriggered1: false,\n      aoUpIdx2: -1,\n      aoDownIdx2: -1,\n      aoUp2: 0,\n      aoDown2: 0,\n      aoUpTriggered2: false,\n      aoDownTriggered2: false,\n      aoUpIdx3: -1,\n      aoDownIdx3: -1,\n      aoUp3: 0,\n      aoDown3: 0,\n      aoUpTriggered3: false,\n      aoDownTriggered3: false,\n      getAoSignal: function (arrUp, arrDown, arrHigh, arrLow) {\n        var arrLen = arrHigh.length\n\n        if (arrUp[arrLen - 2] > 0 && arrDown[arrLen - 3] > 0 && (arrUp[arrLen - 4] > arrDown[arrLen - 3] || arrDown[arrLen - 4] > arrDown[arrLen - 3])) {\n          if (arrLen - 2 != this.aoUpIdx1) {\n            this.aoUpIdx1 = arrLen - 2\n            this.aoDownIdx1 = -1\n            this.aoUp1 = arrHigh[arrLen - 2]\n            this.aoDown1 = 0\n            this.aoUpTriggered1 = false\n            this.aoDownTriggered1 = false\n          }\n        } else if (arrDown[arrLen - 2] < 0 && arrUp[arrLen - 3] < 0 && (arrUp[arrLen - 4] < arrUp[arrLen - 3] || arrDown[arrLen - 4] < arrUp[arrLen - 3])) {\n          if (arrLen - 2 != this.aoDownIdx1) {\n            this.aoUpIdx1 = -1\n            this.aoDownIdx1 = arrLen - 2\n            this.aoUp1 = 0\n            this.aoDown1 = arrLow[arrLen - 2]\n            this.aoUpTriggered1 = false\n            this.aoDownTriggered1 = false\n          }\n        } else {\n          this.aoUpIdx1 = -1\n          this.aoDownIdx1 = -1\n          this.aoUp1 = 0\n          this.aoDown1 = 0\n          this.aoUpTriggered1 = false\n          this.aoDownTriggered1 = false\n        }\n\n        if (arrUp[arrLen - 2] > 0 && (arrUp[arrLen - 3] < 0 || (arrUp[arrLen - 4] < 0 && arrUp[arrLen - 3] == 0 && arrDown[arrLen - 3] == 0))) {\n          if (arrLen - 2 != this.aoUpIdx2) {\n            this.aoUpIdx2 = arrLen - 2\n            this.aoDownIdx2 = -1\n            this.aoUp2 = arrHigh[arrLen - 2]\n            this.aoDown2 = 0\n            this.aoUpTriggered2 = false\n            this.aoDownTriggered2 = false\n          }\n        } else if (arrDown[arrLen - 2] < 0 && (arrDown[arrLen - 3] > 0 || (arrDown[arrLen - 4] > 0 && arrUp[arrLen - 3] == 0 && arrDown[arrLen - 3] == 0))) {\n          if (arrLen - 2 != this.aoDownIdx2) {\n            this.aoUpIdx2 = -1\n            this.aoDownIdx2 = arrLen - 2\n            this.aoUp2 = 0\n            this.aoDown2 = arrLow[arrLen - 2]\n            this.aoUpTriggered2 = false\n            this.aoDownTriggered2 = false\n          }\n        } else {\n          this.aoUpIdx2 = -1\n          this.aoDownIdx2 = -1\n          this.aoUp2 = 0\n          this.aoDown2 = 0\n          this.aoUpTriggered2 = false\n          this.aoDownTriggered2 = false\n        }\n\n        var cursor = arrLen - 3\n        var latestPeakIdx1 = -1\n        var latestPeakIdx2 = -1\n        var arrData = []\n        var bContinue = true\n\n        while (cursor >= 0) {\n          if ((arrUp[cursor] > 0 && arrDown[cursor + 1] > 0) ||\n              (arrDown[cursor] > 0 && arrUp[cursor + 1] > 0) ||\n              (arrUp[cursor] > 0 && arrUp[cursor + 1] > 0) ||\n              (arrDown[cursor] > 0 && arrDown[cursor + 1] > 0) ||\n              (arrUp[cursor] < 0 && arrDown[cursor + 1] < 0) ||\n              (arrDown[cursor] < 0 && arrUp[cursor + 1] < 0) ||\n              (arrUp[cursor] < 0 && arrUp[cursor + 1] < 0) ||\n              (arrDown[cursor] < 0 && arrDown[cursor + 1] < 0)) {\n\n          } else {\n            bContinue = false\n          }\n\n          if (arrUp[cursor + 1] != 0) {\n            arrData.push({\n              ao: arrUp[cursor + 1],\n              idx: cursor + 1\n            })\n          }\n          if (arrDown[cursor + 1] != 0) {\n            arrData.push({\n              ao: arrDown[cursor + 1],\n              idx: cursor + 1\n            })\n          }\n\n          var arrDataLen = arrData.length\n\n          if (arrDataLen > 1) {\n            if (arrData[arrDataLen - 1].ao < 0) {\n              if (arrDataLen == 2 && arrData[1].ao > arrData[0].ao) {\n                break\n              } else {\n                if (arrDataLen > 2 && arrData[arrDataLen - 1].ao > arrData[arrDataLen - 2].ao && arrData[arrDataLen - 2].ao < arrData[arrDataLen - 3].ao) {\n                  if (latestPeakIdx1 != -1) {\n                    latestPeakIdx2 = arrData[arrDataLen - 2].idx\n                    break\n                  } else {\n                    latestPeakIdx1 = arrData[arrDataLen - 2].idx\n                  }\n                }\n              }\n            } else {\n              if (arrDataLen == 2 && arrData[1].ao < arrData[0].ao) {\n                break\n              } else {\n                if (arrDataLen > 2 && arrData[arrDataLen - 1].ao < arrData[arrDataLen - 2].ao && arrData[arrDataLen - 2].ao > arrData[arrDataLen - 3].ao) {\n                  if (latestPeakIdx1 != -1) {\n                    latestPeakIdx2 = arrData[arrDataLen - 2].idx\n                    break\n                  } else {\n                    latestPeakIdx1 = arrData[arrDataLen - 2].idx\n                  }\n                }\n              }\n            }\n          }\n\n          if (!bContinue) {\n            break\n          }\n\n          cursor--\n        }\n\n        if (latestPeakIdx2 != -1) {\n          if (arrData[0].ao < 0 && arrDown[latestPeakIdx1] > arrDown[latestPeakIdx2]) {\n            if (latestPeakIdx1 + 1 != this.aoUpIdx3) {\n              this.aoUpIdx3 = latestPeakIdx1 + 1\n              this.aoDownIdx3 = -1\n              this.aoUp3 = arrHigh[latestPeakIdx1 + 1]\n              this.aoDown3 = 0\n              this.aoUpTriggered3 = false\n              this.aoDownTriggered3 = false\n            }\n          } else if (arrData[0].ao > 0 && arrUp[latestPeakIdx1] < arrUp[latestPeakIdx2]) {\n            if (latestPeakIdx1 + 1 != this.aoDownIdx3) {\n              this.aoUpIdx3 = -1\n              this.aoDownIdx3 = latestPeakIdx1 + 1\n              this.aoUp3 = 0\n              this.aoDown3 = arrLow[latestPeakIdx1 + 1]\n              this.aoUpTriggered3 = false\n              this.aoDownTriggered3 = false\n            }\n          } else {\n            this.aoUpIdx3 = -1\n            this.aoDownIdx3 = -1\n            this.aoUp3 = 0\n            this.aoDown3 = 0\n            this.aoUpTriggered3 = false\n            this.aoDownTriggered3 = false\n          }\n        } else {\n          this.aoUpIdx3 = -1\n          this.aoDownIdx3 = -1\n          this.aoUp3 = 0\n          this.aoDown3 = 0\n          this.aoUpTriggered3 = false\n          this.aoDownTriggered3 = false\n        }\n      },\n      checkAoSignal: function (currTick) {\n        var signal1 = -1\n        var signal2 = -1\n        var signal3 = -1\n\n        if (this.aoUp1 > 0) {\n          if (!this.aoUpTriggered1) {\n            if (currTick > this.aoUp1) {\n              this.aoUpTriggered1 = true\n              signal1 = 1\n            }\n          }\n        }\n\n        if (this.aoDown1 > 0) {\n          if (!this.aoDownTriggered1) {\n            if (currTick < this.aoDown1) {\n              this.aoDownTriggered1 = true\n              signal1 = 0\n            }\n          }\n        }\n\n        if (this.aoUp2 > 0) {\n          if (!this.aoUpTriggered2) {\n            if (currTick > this.aoUp2) {\n              this.aoUpTriggered2 = true\n              signal2 = 1\n            }\n          }\n        }\n\n        if (this.aoDown2 > 0) {\n          if (!this.aoDownTriggered2) {\n            if (currTick < this.aoDown2) {\n              this.aoDownTriggered2 = true\n              signal2 = 0\n            }\n          }\n        }\n\n        if (this.aoUp3 > 0) {\n          if (!this.aoUpTriggered3) {\n            if (currTick > this.aoUp3) {\n              this.aoUpTriggered3 = true\n              signal3 = 1\n            }\n          }\n        }\n\n        if (this.aoDown3 > 0) {\n          if (!this.aoDownTriggered3) {\n            if (currTick < this.aoDown3) {\n              this.aoDownTriggered3 = true\n              signal3 = 0\n            }\n          }\n        }\n\n        return {\n          signal1: signal1,\n          signal2: signal2,\n          signal3: signal3\n        }\n      },\n      acUpIdx1: -1,\n      acDownIdx1: -1,\n      acUp1: 0,\n      acDown1: 0,\n      acUpTriggered1: false,\n      acDownTriggered1: false,\n      acUpIdx2: -1,\n      acDownIdx2: -1,\n      acUp2: 0,\n      acDown2: 0,\n      acUpTriggered2: false,\n      acDownTriggered2: false,\n      getAcSignal: function (arrUp, arrDown, arrHigh, arrLow) {\n        var arrLen = arrHigh.length\n\n        if (arrDown[arrLen - 4] != 0 && arrUp[arrLen - 3] != 0 && arrUp[arrLen - 2] > 0) {\n          if (arrLen - 2 != this.acUpIdx1) {\n            this.acUpIdx1 = arrLen - 2\n            this.acDownIdx1 = -1\n            this.acUp1 = arrHigh[arrLen - 2]\n            this.acDown1 = 0\n            this.acUpTriggered1 = false\n            this.acDownTriggered1 = false\n          }\n        } else if (arrUp[arrLen - 4] != 0 && arrDown[arrLen - 3] != 0 && arrDown[arrLen - 2] < 0) {\n          if (arrLen - 2 != this.acDownIdx1) {\n            this.acUpIdx1 = -1\n            this.acDownIdx1 = arrLen - 2\n            this.acUp1 = 0\n            this.acDown1 = arrLow[arrLen - 2]\n            this.acUpTriggered1 = false\n            this.acDownTriggered1 = false\n          }\n        } else {\n          this.acUpIdx1 = -1\n          this.acDownIdx1 = -1\n          this.acUp1 = 0\n          this.acDown1 = 0\n          this.acUpTriggered1 = false\n          this.acDownTriggered1 = false\n        }\n\n        if (arrDown[arrLen - 5] < 0 && arrUp[arrLen - 4] < 0 && arrUp[arrLen - 3] < 0 && arrUp[arrLen - 2] != 0) {\n          if (arrLen - 2 != this.acUpIdx2) {\n            this.acUpIdx2 = arrLen - 2\n            this.acDownIdx2 = -1\n            this.acUp2 = arrHigh[arrLen - 2]\n            this.acDown2 = 0\n            this.acUpTriggered2 = false\n            this.acDownTriggered2 = false\n          }\n        } else if (arrUp[arrLen - 5] > 0 && arrDown[arrLen - 4] > 0 && arrDown[arrLen - 3] > 0 && arrDown[arrLen - 2] != 0) {\n          if (arrLen - 2 != this.acDownIdx2) {\n            this.acUpIdx2 = -1\n            this.acDownIdx2 = arrLen - 2\n            this.acUp2 = 0\n            this.acDown2 = arrLow[arrLen - 2]\n            this.acUpTriggered2 = false\n            this.acDownTriggered2 = false\n          }\n        } else {\n          this.acUpIdx2 = -1\n          this.acDownIdx2 = -1\n          this.acUp2 = 0\n          this.acDown2 = 0\n          this.acUpTriggered2 = false\n          this.acDownTriggered2 = false\n        }\n      },\n      checkAcSignal: function (currTick) {\n        var signal1 = -1\n        var signal2 = -1\n\n        if (this.acUp1 > 0) {\n          if (!this.acUpTriggered1) {\n            if (currTick > this.acUp1) {\n              this.acUpTriggered1 = true\n              signal1 = 1\n            }\n          }\n        }\n\n        if (this.acDown1 > 0) {\n          if (!this.acDownTriggered1) {\n            if (currTick < this.acDown1) {\n              this.acDownTriggered1 = true\n              signal1 = 0\n            }\n          }\n        }\n\n        if (this.acUp2 > 0) {\n          if (!this.acUpTriggered2) {\n            if (currTick > this.acUp2) {\n              this.acUpTriggered2 = true\n              signal2 = 1\n            }\n          }\n        }\n\n        if (this.acDown2 > 0) {\n          if (!this.acDownTriggered2) {\n            if (currTick < this.acDown2) {\n              this.acDownTriggered2 = true\n              signal2 = 0\n            }\n          }\n        }\n\n        return {\n          signal1: signal1,\n          signal2: signal2\n        }\n      },\n      mapUpIdx: -1,\n      mapDownIdx: -1,\n      mapUp: 0,\n      mapDown: 0,\n      mapUpTriggered: false,\n      mapDownTriggered: false,\n      mapUpCnt: 0,\n      mapDownCnt: 0,\n      mapUpSl: 0,\n      mapDownSl: 0,\n      mapUpSlTriggered: false,\n      mapDownSlTriggered: false,\n      getMapSignal: function (arrAoUp, arrAoDown, arrAcUp, arrAcDown, arrClose, arrHigh, arrLow) {\n        var arrLen = arrClose.length\n\n        if (arrAoUp[arrLen - 2] != 0 && arrAcUp[arrLen - 2] != 0) {\n          if (arrLen - 2 != this.mapUpIdx) {\n            if (this.mapUpIdx == -1) {\n              this.mapUpCnt = 1\n            } else {\n              this.mapUpCnt++\n            }\n            this.mapDownCnt = 0\n            this.mapUpIdx = arrLen - 2\n            this.mapDownIdx = -1\n            this.mapUp = arrClose[arrLen - 2]\n            this.mapDown = 0\n            this.mapUpTriggered = false\n            this.mapDownTriggered = false\n            if (this.mapUpCnt >= 6) {\n              this.mapUp = 0\n              this.mapUpTriggered = false\n              this.mapUpSl = arrLow[arrLen - 2]\n              this.mapUpSlTriggered = false\n            } else {\n              this.mapUpSl = 0\n              this.mapUpSlTriggered = false\n            }\n            this.mapDownSl = 0\n            this.mapDownSlTriggered = false\n          }\n        } else if (arrAoDown[arrLen - 2] != 0 && arrAcDown[arrLen - 2] != 0) {\n          if (arrLen - 2 != this.mapDownIdx) {\n            this.mapUpCnt = 0\n            if (this.mapDownIdx == -1) {\n              this.mapDownCnt = 1\n            } else {\n              this.mapDownCnt++\n            }\n            this.mapUpIdx = -1\n            this.mapDownIdx = arrLen - 2\n            this.mapUp = 0\n            this.mapDown = arrClose[arrLen - 2]\n            this.mapUpTriggered = false\n            this.mapDownTriggered = false\n            this.mapUpSl = 0\n            this.mapUpSlTriggered = false\n            if (this.mapDownCnt >= 6) {\n              this.mapDown = 0\n              this.mapDownTriggered = false\n              this.mapDownSl = arrHigh[arrLen - 2]\n              this.mapDownSlTriggered = false\n            } else {\n              this.mapDownSl = 0\n              this.mapDownSlTriggered = false\n            }\n          }\n        } else {\n          this.mapUpIdx = -1\n          this.mapDownIdx = -1\n          this.mapUp = 0\n          this.mapDown = 0\n          this.mapUpTriggered = false\n          this.mapDownTriggered = false\n          if (this.mapUpCnt >= 5) {\n            this.mapUpSl = arrLow[arrLen - 2]\n            this.mapUpSlTriggered = false\n          } else {\n            this.mapUpCnt = 0\n            this.mapUpSl = 0\n            this.mapUpSlTriggered = false\n          }\n          if (this.mapDownCnt >= 5) {\n            this.mapDownSl = arrHigh[arrLen - 2]\n            this.mapDownSlTriggered = false\n          } else {\n            this.mapDownCnt = 0\n            this.mapDownSl = 0\n            this.mapDownSlTriggered = false\n          }\n        }\n      },\n      checkMapSignal: function (currTick, prevHigh, prevLow) {\n        var signal = -1\n\n        if (this.mapUp > 0) {\n          if (!this.mapUpTriggered) {\n            if (currTick > this.mapUp) {\n              if (this.mapUpCnt >= 5) {\n                this.mapUp = 0\n                this.mapUpTriggered = false\n                this.mapUpSl = prevLow\n                this.mapUpSlTriggered = false\n              } else {\n                this.mapUpTriggered = true\n                this.mapUpSl = 0\n                this.mapUpSlTriggered = false\n              }\n              this.mapDownSl = 0\n              this.mapDownSlTriggered = false\n\n              signal = 1\n            }\n          }\n        }\n\n        if (this.mapDown > 0) {\n          if (!this.mapDownTriggered) {\n            if (currTick < this.mapDown) {\n              this.mapUpSl = 0\n              this.mapUpSlTriggered = false\n              if (this.mapDownCnt >= 5) {\n                this.mapDown = 0\n                this.mapDownTriggered = false\n                this.mapDownSl = prevHigh\n                this.mapDownSlTriggered = false\n              } else {\n                this.mapDownTriggered = true\n                this.mapDownSl = 0\n                this.mapDownSlTriggered = false\n              }\n\n              signal = 0\n            }\n          }\n        }\n\n        if (this.mapUpSl > 0) {\n          if (!this.mapUpSlTriggered) {\n            if (currTick < this.mapUpSl) {\n              this.mapUpSlTriggered = true\n              this.mapUpCnt = 0\n              signal = 3\n            }\n          }\n        }\n\n        if (this.mapDownSl > 0) {\n          if (!this.mapDownSlTriggered) {\n            if (currTick > this.mapDownSl) {\n              this.mapDownSlTriggered = true\n              this.mapDownCnt = 0\n              signal = 2\n            }\n          }\n        }\n\n        return signal\n      },\n      alligatorUpIdx1: -1,\n      alligatorDownIdx1: -1,\n      alligatorUp1: 0,\n      alligatorDown1: 0,\n      alligatorUpTriggered1: false,\n      alligatorDownTriggered1: false,\n      alligatorUpBase1: 0,\n      alligatorDownBase1: 0,\n      alligatorUpIdx2: -1,\n      alligatorDownIdx2: -1,\n      alligatorUp2: 0,\n      alligatorDown2: 0,\n      alligatorUpTriggered2: false,\n      alligatorDownTriggered2: false,\n      alligatorUpBase2: 0,\n      alligatorDownBase2: 0,\n      alligatorUpIdx3: -1,\n      alligatorDownIdx3: -1,\n      alligatorUp3: 0,\n      alligatorDown3: 0,\n      alligatorUpTriggered3: false,\n      alligatorDownTriggered3: false,\n      alligatorUpBase3: 0,\n      alligatorDownBase3: 0,\n      getAlligatorSignal: function (arrHigh, arrLow, currLip, currJaw, currAoUp, currAoDown, currAcUp, currAcDown) {\n        var arrLen = arrHigh.length\n\n        if (this.alligatorUpIdx1 != 0) {\n          if (this.alligatorUpBase1 > arrHigh[arrLen - 2]) {\n            this.alligatorUpIdx1 = -1\n            this.alligatorUp1 = 0\n            this.alligatorUpTriggered1 = false\n            this.alligatorUpBase1 = 0\n          }\n        }\n        if (this.alligatorDownIdx1 != 0) {\n          if (this.alligatorDownBase1 < arrLow[arrLen - 2]) {\n            this.alligatorDownIdx1 = -1\n            this.alligatorDown1 = 0\n            this.alligatorDownTriggered1 = false\n            this.alligatorDownBase1 = 0\n          }\n        }\n\n        if (arrHigh[arrLen - 3] > arrHigh[arrLen - 2] && arrHigh[arrLen - 2] > currLip) {\n          if (arrLen - 3 != this.alligatorUpIdx1) {\n            this.alligatorUpIdx1 = arrLen - 3\n            this.alligatorUp1 = arrHigh[arrLen - 3]\n            this.alligatorUpTriggered1 = false\n            this.alligatorUpBase1 = arrHigh[arrLen - 2]\n          }\n        } else if (arrLow[arrLen - 3] < arrLow[arrLen - 2] && arrLow[arrLen - 2] < currLip) {\n          if (arrLen - 3 != this.alligatorDownIdx1) {\n            this.alligatorDownIdx1 = arrLen - 3\n            this.alligatorDown1 = arrLow[arrLen - 3]\n            this.alligatorDownTriggered1 = false\n            this.alligatorDownBase1 = arrLow[arrLen - 2]\n          }\n        }\n\n        if (this.alligatorUpIdx2 != 0) {\n          if (this.alligatorUpBase2 > arrHigh[arrLen - 2]) {\n            this.alligatorUpIdx2 = -1\n            this.alligatorUp2 = 0\n            this.alligatorUpTriggered2 = false\n            this.alligatorUpBase2 = 0\n          }\n        }\n        if (this.alligatorDownIdx2 != 0) {\n          if (this.alligatorDownBase2 < arrLow[arrLen - 2]) {\n            this.alligatorDownIdx2 = -1\n            this.alligatorDown2 = 0\n            this.alligatorDownTriggered2 = false\n            this.alligatorDownBase2 = 0\n          }\n        }\n\n        if (arrHigh[arrLen - 4] > arrHigh[arrLen - 3] && arrHigh[arrLen - 3] > arrHigh[arrLen - 2] && arrHigh[arrLen - 2] < currJaw &&\n            ((currAoUp != 0 && currAcUp != 0) || (currAoUp != 0 && currAcDown != 0) || (currAoDown != 0 && currAcUp != 0))) {\n          if (arrLen - 4 != this.alligatorUpIdx2) {\n            this.alligatorUpIdx2 = arrLen - 4\n            this.alligatorUp2 = arrHigh[arrLen - 4]\n            this.alligatorUpTriggered2 = false\n            this.alligatorUpBase2 = arrHigh[arrLen - 2]\n          }\n        } else if (arrLow[arrLen - 4] < arrLow[arrLen - 3] && arrLow[arrLen - 3] < arrLow[arrLen - 2] && arrLow[arrLen - 2] > currJaw &&\n            ((currAoDown != 0 && currAcDown != 0) || (currAoUp != 0 && currAcDown != 0) || (currAoDown != 0 && currAcUp != 0))) {\n          if (arrLen - 4 != this.alligatorDownIdx2) {\n            this.alligatorDownIdx2 = arrLen - 4\n            this.alligatorDown2 = arrLow[arrLen - 4]\n            this.alligatorDownTriggered2 = false\n            this.alligatorDownBase2 = arrLow[arrLen - 2]\n          }\n        }\n\n        if (this.alligatorUpIdx3 != 0) {\n          if (this.alligatorUpBase3 > arrHigh[arrLen - 2]) {\n            this.alligatorUpIdx3 = -1\n            this.alligatorUp3 = 0\n            this.alligatorUpTriggered3 = false\n            this.alligatorUpBase3 = 0\n          }\n        }\n        if (this.alligatorDownIdx3 != 0) {\n          if (this.alligatorDownBase3 < arrLow[arrLen - 2]) {\n            this.alligatorDownIdx3 = -1\n            this.alligatorDown3 = 0\n            this.alligatorDownTriggered3 = false\n            this.alligatorDownBase3 = 0\n          }\n        }\n\n        if (arrHigh[arrLen - 6] > arrHigh[arrLen - 5] && arrHigh[arrLen - 5] > arrHigh[arrLen - 4] && arrHigh[arrLen - 4] > arrHigh[arrLen - 3] && arrHigh[arrLen - 3] > arrHigh[arrLen - 2] &&\n            arrHigh[arrLen - 2] < currJaw && currAoDown != 0 && currAcDown != 0) {\n          if (arrLen - 6 != this.alligatorUpIdx3) {\n            this.alligatorUpIdx3 = arrLen - 6\n            this.alligatorUp3 = arrHigh[arrLen - 6]\n            this.alligatorUpTriggered3 = false\n            this.alligatorUpBase3 = arrHigh[arrLen - 2]\n          }\n        } else if (arrLow[arrLen - 6] < arrLow[arrLen - 5] && arrLow[arrLen - 5] < arrLow[arrLen - 4] && arrLow[arrLen - 4] < arrLow[arrLen - 3] && arrLow[arrLen - 3] < arrLow[arrLen - 2] &&\n            arrLow[arrLen - 2] > currJaw && currAoUp != 0 && currAcUp != 0) {\n          if (arrLen - 6 != this.alligatorDownIdx3) {\n            this.alligatorDownIdx3 = arrLen - 6\n            this.alligatorDown3 = arrLow[arrLen - 6]\n            this.alligatorDownTriggered3 = false\n            this.alligatorDownBase3 = arrLow[arrLen - 2]\n          }\n        }\n      },\n      checkAlligatorSignal: function (currTick) {\n        var signal1 = -1\n        var signal2 = -1\n        var signal3 = -1\n\n        if (this.alligatorUp1 > 0) {\n          if (!this.alligatorUpTriggered1) {\n            if (currTick > this.alligatorUp1) {\n              this.alligatorUpTriggered1 = true\n              signal1 = 1\n            }\n          }\n        }\n\n        if (this.alligatorDown1 > 0) {\n          if (!this.alligatorDownTriggered1) {\n            if (currTick < this.alligatorDown1) {\n              this.alligatorDownTriggered1 = true\n              signal1 = 0\n            }\n          }\n        }\n\n        if (this.alligatorUp2 > 0) {\n          if (!this.alligatorUpTriggered2) {\n            if (currTick > this.alligatorUp2) {\n              this.alligatorUpTriggered2 = true\n              signal2 = 1\n            }\n          }\n        }\n\n        if (this.alligatorDown2 > 0) {\n          if (!this.alligatorDownTriggered2) {\n            if (currTick < this.alligatorDown2) {\n              this.alligatorDownTriggered2 = true\n              signal2 = 0\n            }\n          }\n        }\n\n        if (this.alligatorUp3 > 0) {\n          if (!this.alligatorUpTriggered3) {\n            if (currTick > this.alligatorUp3) {\n              this.alligatorUpTriggered3 = true\n              signal3 = 1\n            }\n          }\n        }\n\n        if (this.alligatorDown3 > 0) {\n          if (!this.alligatorDownTriggered3) {\n            if (currTick < this.alligatorDown3) {\n              this.alligatorDownTriggered3 = true\n              signal3 = 0\n            }\n          }\n        }\n\n        return {\n          signal1: signal1,\n          signal2: signal2,\n          signal3: signal3\n        }\n      },\n      checkCloseSignal: function (arrTeeth, arrClose) {\n        var arrLen = arrClose.length\n\n        if (arrTeeth[arrLen - 7] > arrClose[arrLen - 2] && arrClose[arrLen - 3] >= arrTeeth[arrLen - 8]) {\n          return 3\n        }\n        if (arrTeeth[arrLen - 7] < arrClose[arrLen - 2] && arrClose[arrLen - 3] <= arrTeeth[arrLen - 8]) {\n          return 2\n        }\n\n        return -1\n      },\n      trend: -1\n    }\n  },\n  function (context) { // Deinit()\n  },\n  function (context) { // OnTick()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n    var volume = getEAParameter(context, \"volume\")\n    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n    var arrHigh = getData(context, context.chartHandle, DATA_NAME.HIGH)\n    var arrLow = getData(context, context.chartHandle, DATA_NAME.LOW)\n    var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)\n    var arrTeeth = getData(context, context.alligatorHandle, \"teeth\")\n    var arrLips = getData(context, context.alligatorHandle, \"lips\")\n    var arrJaws = getData(context, context.alligatorHandle, \"jaws\")\n    var arrUp = getData(context, context.fractalsHandle, \"fractalsUp\")\n    var arrDown = getData(context, context.fractalsHandle, \"fractalsDown\")\n    var arrAoUp = getData(context, context.aoHandle, \"up\")\n    var arrAoDown = getData(context, context.aoHandle, \"down\")\n    var arrAcUp = getData(context, context.acHandle, \"up\")\n    var arrAcDown = getData(context, context.acHandle, \"down\")\n    var arrLen = arrTime.length\n\n    if (200 >= arrLen) throw new Error(\"No enough data.\")\n\n    var bGetSignals = false\n    if (typeof context.currTime == \"undefined\") {\n      context.currTime = arrTime[arrTime.length - 1]\n      bGetSignals = true\n    } else if (context.currTime != arrTime[arrTime.length - 1]) {\n      context.currTime = arrTime[arrTime.length - 1]\n      bGetSignals = true\n    }\n\n    if (bGetSignals) {\n      context.chaos.getFractalsSignal(arrUp, arrDown)\n      context.chaos.getAoSignal(arrAoUp, arrAoDown, arrHigh, arrLow)\n      context.chaos.getAcSignal(arrAcUp, arrAcDown, arrHigh, arrLow)\n      context.chaos.getMapSignal(arrAoUp, arrAoDown, arrAcUp, arrAcDown, arrClose, arrHigh, arrLow)\n      context.chaos.getAlligatorSignal(arrHigh, arrLow, arrLips[arrLen - 2], arrJaws[arrLen - 2], arrAoUp[arrLen - 2], arrAoDown[arrLen - 2], arrAcUp[arrLen - 2], arrAcDown[arrLen - 2])\n    }\n\n    var signal = -1\n\n    var fractalsSignal = context.chaos.checkFractalsSignal(arrTeeth, arrClose[arrLen - 1])\n    if (fractalsSignal != -1) {\n      signal = fractalsSignal\n      context.chaos.trend = fractalsSignal\n    }\n\n    if (context.chaos.trend == -1) {\n      return\n    }\n\n    var aoSignal = context.chaos.checkAoSignal(arrClose[arrLen - 1])\n    if (aoSignal.signal1 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    if (aoSignal.signal2 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    if (aoSignal.signal3 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    var acSignal = context.chaos.checkAcSignal(arrClose[arrLen - 1])\n    if (acSignal.signal1 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    if (acSignal.signal2 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    var mapSignal = context.chaos.checkMapSignal(arrClose[arrLen - 1], arrHigh[arrLen - 2], arrLow[arrLen - 2])\n    if (mapSignal == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    var alligatorSignal = context.chaos.checkAlligatorSignal(arrClose[arrLen - 1])\n    if (alligatorSignal.signal1 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    if (alligatorSignal.signal2 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n    if (alligatorSignal.signal3 == context.chaos.trend) {\n      signal = context.chaos.trend\n    }\n\n    var closeSignal = context.chaos.checkCloseSignal(arrTeeth, arrClose)\n    if (closeSignal != -1) {\n      signal = closeSignal\n    }\n    if ((mapSignal == 3 && context.chaos.trend == 1) || (mapSignal == 2 && context.chaos.trend == 0)) {\n      signal = mapSignal\n    }\n\n    if (signal == 1) {\n      popupMessage(\"You received an OPEN LONG signal!\")\n    } else if (signal == 0) {\n      popupMessage(\"You received an OPEN SHORT signal!\")\n    } else if (signal == 3) {\n      if (bGetSignals) {\n        popupMessage(\"You received a CLOSE LONG signal!\")\n      }\n    } else if (signal == 2) {\n      if (bGetSignals) {\n        popupMessage(\"You received a CLOSE SHORT signal!\")\n      }\n    }\n  },\n  function (context) { // OnTransaction()\n  }\n)\n"
  },
  {
    "path": "EA/Chaos/intro.txt",
    "content": "EA based on Trading Chaos(Bill Williams' book). All of the strategies described in the book have been implemented. Additionally, you may utilize “extra_mfi” as a supplementary tool.\n"
  },
  {
    "path": "EA/CopyTrading/README.md",
    "content": "This is just an example.\n"
  },
  {
    "path": "EA/CopyTrading/copy_trading_for_oanda.js",
    "content": "registerEA(\n\t\t\"copy_trading_for_oanda\",\n\t\t\"An EA to copy trading for Oanda(v1.02)\",\n\t\t[],\n\t\tfunction (context) { // Init()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t},\n\t\tfunction (context) { // OnTransaction()\n\t\t  if (typeof window.pluginForOanda != \"undefined\") {\n\t\t    var transType = getLatestTransType(context)\n\n\t\t    if (transType == \"Open Trade\") {\n\t\t\t\t\tvar trade = getLatestTrans(context)\n\t\t\t    var tradeSymbolName = getSymbolName(trade)\n\t\t\t    var tradeOrderType = getOrderType(trade)\n\t\t\t    var tradeLots = getOpenLots(trade)\n\n\t\t      if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {\n\t\t        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_BUY, tradeLots)\n\t\t      } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {\n\t\t        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_SELL, tradeLots)\n\t\t      }\n\t\t    } else if (transType == \"Trade Closed\") {\n\t\t\t\t\tvar trade = getLatestTrans(context)\n\t\t\t    var tradeSymbolName = getSymbolName(trade)\n\t\t\t    var tradeOrderType = getOrderType(trade)\n\t\t\t    var tradeLots = getOpenLots(trade)\n\n\t\t      if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {\n\t\t        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_SELL, tradeLots)\n\t\t      } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {\n\t\t        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_BUY, tradeLots)\n\t\t      }\n\t\t    }\n\t\t  }\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/CopyTrading/copy_trading_for_oanda_guide.txt",
    "content": "Use Case: A provides signals, B follows the signals from A to copy trade. A's account is a Fintechee-based account, B's account is an Oanda-based account.\n\nHow to do?\n1. A shares A's investor password with B.\nPlease note, enabling investor mode is not required for this step.\nIf you enable investor mode, then everyone can check your trading records.\nIf you disable investor mode(disabled by default), then only the followers that know your investor password can check your trading records.\n\n2. B signs into both accounts.\nB signs into A's account by entering A's investor password.\nB signs into B's Oanda-based account by launching an EA named plugin_for_oanda.\nYou can get plugin_for_oanda on Fintechee's Github repo:\nhttps://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/Plugin-for-Oanda/plugin_for_oanda.js\nOanda issues a token as login credential. So, B needs to input it into the corresponding parameter for oanda_loader.\n\n3. B launches copy_trading_for_oanda via Fintechee WEB Trader.\nYou can get copy_trading_for_oanda on Fintechee's Github repo:\nhttps://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/CopyTrading/copy_trading_for_oanda.js\nThere are no parameters because the EA will follow all the signals that it receives and trade via B's Oanda account.\nB has logged into A's account in the investor mode, so all the signals that A issues will be seen by B.\nThe EA will send orders via the plugin_for_oanda launched in the 2nd step.\n\nDone!\n\n"
  },
  {
    "path": "EA/CopyTrading/copy_trading_locally.js",
    "content": "registerEA(\n\"copy_trading_locally\",\n\"A simple EA to copy trading locally(v1.01)\",\n[{\n\tname: \"fromAccountId\",\n\tvalue: \"XXXXXXXXXX\", // e.g. account id:1066149, investor password: 1\n\trequired: true,\n\ttype: \"String\",\n\trange: null,\n\tstep: null\n}, {\n\tname: \"toAccountId\",\n\tvalue: \"XXXXXXXXXX\",\n\trequired: true,\n\ttype: \"String\",\n\trange: null,\n\tstep: null\n}],\nfunction (context) { // Init()\n\t\t},\nfunction (context) { // Deinit()\n\t\t},\nfunction (context) { // OnTick()\n\t\t},\nfunction (context) { // OnTransaction()\n  var account = getAccount(context, 0)\n  var brokerName = getBrokerNameOfAccount(account)\n  var fromAccountId = getEAParameter(context, \"fromAccountId\")\n  var toAccountId = getEAParameter(context, \"toAccountId\")\n  var volume = 0.01\n  var transType = getLatestTransType(context)\n\n  if (transType == \"Open Trade\" && tradeAccountId == fromAccountId) {\n\t\tvar trade = getLatestTrans(context)\n\t  var tradeAccountId = getAccountId(trade)\n\t  var tradeSymbolName = getSymbolName(trade)\n\t  var tradeOrderType = getOrderType(trade)\n\n    if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {\n      sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n    } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {\n      sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n    }\n  } else if (transType == \"Trade Closed\" && tradeAccountId == fromAccountId) {\n\t\tvar trade = getLatestTrans(context)\n\t  var tradeAccountId = getAccountId(trade)\n\t  var tradeSymbolName = getSymbolName(trade)\n\t  var tradeOrderType = getOrderType(trade)\n\n    var tradeOrderType2 = null\n\n    if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {\n      tradeOrderType2 = ORDER_TYPE.OP_BUY\n    } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {\n      tradeOrderType2 = ORDER_TYPE.OP_SELL\n    }\n\n    var count = getOpenTradesListLength(context)\n    var tradeId = null\n\n    for (var i = count - 1; i >= 0; i--) {\n      var openTrade = getOpenTrade(context, i)\n      var accountId = getAccountId(openTrade)\n      var symbolName = getSymbolName(openTrade)\n      var orderType = getOrderType(openTrade)\n\n      if (accountId == toAccountId && symbolName == tradeSymbolName && tradeOrderType2 == orderType) {\n        tradeId = getTradeId(openTrade)\n        break\n      }\n    }\n\n    if (tradeId != null) {\n      closeTrade(brokerName, toAccountId, tradeId, 0, 0)\n    } else {\n      if (tradeOrderType2 == ORDER_TYPE.OP_BUY) {\n        sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n      } else if (tradeOrderType2 == ORDER_TYPE.OP_SELL) {\n        sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "EA/CopyTrading/copy_trading_locally_guide.txt",
    "content": "Use Case: A provides signals, B follows the signals from A to copy trade. Both accounts are Fintechee-based.\n\nHow to do?\n1. A shares A's investor password with B.\nPlease note, enabling investor mode is not required for this step.\nIf you enable investor mode, then everyone can check your trading records.\nIf you disable investor mode(disabled by default), then only the followers that know your investor password can check your trading records.\n\n2. B signs into both accounts.\nB signs into A's account by entering A's investor password.\nB signs into B's own account by entering B's password.\n\n3. B launches copy_trading_locally via Fintechee WEB Trader.\nIf copy_trading_locally doesn't exist, you can get it on Fintechee's Github repo:\nhttps://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/CopyTrading/copy_trading_locally.js\nCopy the source codes and paste them into Fintechee WEB Trader's Javascript console and run it.\nThen you can find it listed on the EA list and launch it.\nThere are two parameters: fromAccountId and toAccountId.\nB sets fromAccountId to A's account ID and sets toAccountId to B's account ID.\n\nDone!\n\n"
  },
  {
    "path": "EA/Martingale/improved_martingale.js",
    "content": "registerEA(\n  \"improved_martingale\",\n  \"An EA based on an improved Martingale algorithm(v1.0)\",\n  [{\n    name: \"diffPrice\",\n    value: 0.002,\n    required: true,\n    type: PARAMETER_TYPE.NUMBER,\n    range: [0, 100]\n  }, {\n    name: \"diffPrice2\",\n    value: 0.001,\n    required: true,\n    type: PARAMETER_TYPE.NUMBER,\n    range: [0, 100]\n  }],\n  function(context) { // Init()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = \"EUR/USD\"\n\n    getQuotes(context, brokerName, accountId, symbolName)\n\n    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.H1)\n    context.maxCost = Number.MAX_VALUE\n    context.maxPos = 0\n    context.openTrades = []\n    context.res = []\n  },\n  function(context) { // Deinit()\n  },\n  function(context) { // OnTick()\n    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = \"EUR/USD\"\n    var diffPrice = getEAParameter(context, \"diffPrice\")\n\t\tvar diffPrice2 = getEAParameter(context, \"diffPrice2\")\n\n\t\tvar signal = Math.random() >= 0.5 ? 1 : 0 // This EA is created mainly to show you how to improve Martingale algo, so the signals are generated by random. Please replace the signal generator with your own algo.\n\n    var ask = null\n    var bid = null\n\n    try {\n      ask = getAsk(context, brokerName, accountId, symbolName)\n      bid = getBid(context, brokerName, accountId, symbolName)\n    } catch (e) {\n      // This try-catch is used to bypass the \"error throw\" when you start the EA too early to call getAsk or getBid(at that time, bid or ask may be not ready yet.)\n      printErrorMessage(e.message)\n      return\n    }\n\n    var count = getOpenTradesListLength(context)\n    var countL = 0\n    var countS = 0\n    var totalPLL = 0.0\n    var totalPLS = 0.0\n    var highPriceL = -Number.MAX_VALUE\n    var lowPriceL = Number.MAX_VALUE\n    var highPriceS = -Number.MAX_VALUE\n    var lowPriceS = Number.MAX_VALUE\n\n    for (var i = count - 1; i >= 0; i--) {\n      var openTrade = getOpenTrade(context, i)\n\n      var openPrice = getOpenPrice(openTrade)\n\n      if (getOrderType(openTrade) == ORDER_TYPE.OP_BUY) {\n        countL++\n        totalPLL += getUnrealizedPL(openTrade)\n\n        if (openPrice > highPriceL) highPriceL = openPrice\n        if (openPrice < lowPriceL) lowPriceL = openPrice\n      }\n      if (getOrderType(openTrade) == ORDER_TYPE.OP_SELL) {\n        countS++\n        totalPLS += getUnrealizedPL(openTrade)\n\n        if (openPrice > highPriceS) highPriceS = openPrice\n        if (openPrice < lowPriceS) lowPriceS = openPrice\n      }\n    }\n\n    if (totalPLL + totalPLS < context.maxCost) {\n      context.maxCost = totalPLL + totalPLS\n    }\n\n    if (Math.abs(countL - countS) > Math.abs(context.maxPos)) {\n      context.maxPos = countL - countS\n    }\n\n    if (typeof context.currTime == \"undefined\") {\n      context.currTime = arrTime[arrTime.length - 1]\n    } else if (context.currTime != arrTime[arrTime.length - 1]) {\n      context.currTime = arrTime[arrTime.length - 1]\n    } else {\n      return\n    }\n\n    var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)\n\n    var volume = 0.01\n\n    if (countL == 0 && countS == 0) {\n\t\t\tif (signal == 1) {\n        sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\t} else {\n        sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\t}\n\t\t} else if (((countL + countS) > 1 && (totalPLL + totalPLS) > 0.1 * (countL + countS)) ||\n\t\t\t\t\t\t\t(countL == 1 && countS == 0 && signal == 0 && (arrClose[arrClose.length - 1] - highPriceL) > diffPrice) ||\n\t\t\t\t\t\t\t(countL == 0 && countS == 1 && signal == 1 && (lowPriceS - arrClose[arrClose.length - 1]) > diffPrice)) {\n\n      var pos = Math.abs(countL - countS)\n      if (typeof context.res[pos] == \"undefined\") {\n        context.res[pos] = 1\n      } else {\n        context.res[pos]++\n      }\n      for (var i in context.res) {\n        printMessage(i + \", \" + context.res[i])\n      }\n\n      printMessage(\"Pos: \" + (countL - countS) + \", Unrealized PL: \" + (totalPLL + totalPLS) +\n                  \", Max Cost: \" + context.maxCost + \", Max Pos: \" + context.maxPos)\n\n      for (var i = count - 1; i >= 0; i--) {\n        var openTrade = getOpenTrade(context, i)\n\n        closeTrade(brokerName, accountId, getTradeId(openTrade), 0, 0)\n      }\n\t\t} else if (countL == 1 && countS == 0 && signal == 0 && (highPriceL - arrClose[arrClose.length - 1]) > diffPrice) {\n      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL == 0 && countS == 1 && signal == 1 && (arrClose[arrClose.length - 1] - lowPriceS) > diffPrice) {\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n    } else if (countL > 0 && countS > 0 && highPriceL > highPriceS && (arrClose[arrClose.length - 1] - highPriceL) > diffPrice && lowPriceL > lowPriceS) {\n      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL > 0 && countS > 0 && highPriceS > highPriceL && (arrClose[arrClose.length - 1] - highPriceS) > diffPrice && lowPriceL < lowPriceS) {\n      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL > 0 && countS > 0 && lowPriceL > lowPriceS && (lowPriceS - arrClose[arrClose.length - 1]) > diffPrice && highPriceL > highPriceS) {\n      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL > 0 && countS > 0 && lowPriceS > lowPriceL && (lowPriceL - arrClose[arrClose.length - 1]) > diffPrice && highPriceL < highPriceS) {\n      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n    } else if (countL > 0 && countS > 0 && highPriceL > highPriceS && (arrClose[arrClose.length - 1] - highPriceL) > diffPrice2 && lowPriceL < lowPriceS) {\n      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL > 0 && countS > 0 && highPriceS > highPriceL && (arrClose[arrClose.length - 1] - highPriceS) > diffPrice2 && lowPriceL > lowPriceS) {\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL > 0 && countS > 0 && lowPriceL > lowPriceS && (lowPriceS - arrClose[arrClose.length - 1]) > diffPrice2 && highPriceL < highPriceS) {\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\n\t\t} else if (countL > 0 && countS > 0 && lowPriceS > lowPriceL && (lowPriceL - arrClose[arrClose.length - 1]) > diffPrice2 && highPriceL > highPriceS) {\n\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\n    }\n  },\n  function(context) { // OnTransaction()\n  }\n)\n"
  },
  {
    "path": "EA/Martingale/improved_martingale.txt",
    "content": "Usually, Martingale strategy involves doubling the bet once a loss occurs and engaging in one-sided trading. In contrast, the “improved_martingale” strategy is a double-sided trading strategy.\nIf losses continue to accrue, profits can still be made on one side. This means that the profit on one side can help reduce the overall loss risk.\n"
  },
  {
    "path": "EA/Martingale/sample_martingale.js",
    "content": "registerEA(\r\n\t\"sample_martingale\",\r\n\t\"A test EA based on Martingale algorithm(v1.03)\",\r\n\t[{ // parameters\r\n\t\tname: \"period\",\r\n\t\tvalue: 5,\r\n\t\trequired: true,\r\n\t\ttype: PARAMETER_TYPE.INTEGER,\r\n\t\trange: [1, 100]\r\n\t}],\r\n\tfunction (context) { // Init()\r\n\t\tvar account = getAccount(context, 0)\r\n\t\tvar brokerName = getBrokerNameOfAccount(account)\r\n\t\tvar accountId = getAccountIdOfAccount(account)\r\n\t\tvar symbolName = \"EUR/USD\"\r\n\r\n\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)\r\n\t\tvar period = getEAParameter(context, \"period\")\r\n\t\tcontext.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, \"sma\", [{\r\n\t\t\tname: \"period\",\r\n\t\t\tvalue: period\r\n\t\t}])\r\n\t},\r\n\tfunction (context) { // Deinit()\r\n\t},\r\n\tfunction (context) { // OnTick()\r\n\t\tvar arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\r\n\t\tif (typeof context.currTime == \"undefined\") {\r\n\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\r\n\t\t} else if (context.currTime != arrTime[arrTime.length - 1]) {\r\n\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\r\n\t\t} else {\r\n\t\t\treturn\r\n\t\t}\r\n\r\n\t\tvar account = getAccount(context, 0)\r\n\t\tvar brokerName = getBrokerNameOfAccount(account)\r\n\t\tvar accountId = getAccountIdOfAccount(account)\r\n\t\tvar symbolName = \"EUR/USD\"\r\n\r\n\t\tvar count = getOpenTradesListLength(context)\r\n\t\tvar totalPL = 0.0\r\n\t\tvar highPrice = 0.0\r\n\t\tvar lowPrice = 100000000.0\r\n\t\tvar orientation = null\r\n\r\n\t\tfor (var i = count - 1; i >= 0; i--) {\r\n\t\t\tvar openTrade = getOpenTrade(context, i)\r\n\r\n\t\t\ttotalPL += getUnrealizedPL(openTrade)\r\n\r\n\t\t\tvar openPrice = getOpenPrice(openTrade)\r\n\r\n\t\t\tif (openPrice > highPrice) highPrice = openPrice\r\n\t\t\tif (openPrice < lowPrice) lowPrice = openPrice\r\n\t\t\tif (getOrderType(openTrade) == ORDER_TYPE.OP_BUY) orientation = ORDER_TYPE.OP_BUY\r\n\t\t\tif (getOrderType(openTrade) == ORDER_TYPE.OP_SELL) orientation = ORDER_TYPE.OP_SELL\r\n\t\t}\r\n\r\n\t\tvar arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)\r\n\t\tvar arrSma = getData(context, context.indiHandle, \"sma\")\r\n\r\n\t\tvar volume = 0.01\r\n\r\n\t\tif (count > 0 && totalPL > 0.1 * count) {\r\n\t\t\tfor (var i = count - 1; i >= 0; i--) {\r\n\t\t\t\tvar openTrade = getOpenTrade(context, i)\r\n\r\n\t\t\t\tcloseTrade(brokerName, accountId, getTradeId(openTrade), 0, 0)\r\n\t\t\t}\r\n\t\t} else if (count == 0) {\r\n\t\t\tif (arrClose[arrClose.length - 3] < arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] > arrSma[arrSma.length - 2]) {\r\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\r\n\t\t\t} else if (arrClose[arrClose.length - 3] > arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] < arrSma[arrSma.length - 2]) {\r\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (orientation == ORDER_TYPE.OP_BUY && (lowPrice - arrClose[arrClose.length - 1]) > 0.0005) {\r\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, \"\", 0, 0)\r\n\t\t\t}\r\n\t\t\tif (orientation == ORDER_TYPE.OP_SELL && (arrClose[arrClose.length - 1] - highPrice) > 0.0005) {\r\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, \"\", 0, 0)\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\tfunction (context) { // OnTransaction()\r\n\t\tprintMessage(\"test OnTransaction: \" + getLatestTransId(context) + \" \" + getLatestTransType(context))\r\n\t}\r\n)\r\n"
  },
  {
    "path": "EA/NeuralNetwork/nn_example.js",
    "content": "// Please check this post to know how to use this EA: https://www.fintecher.org/daily-trading/added-genetic-algorithm-for-trading.html\nregisterEA(\n\"nn_example\",\n\"A test EA to run neuron model for XOR(v1.0)\",\n[\n// hidden layer(1st neuron)\n{name: \"h11\", value: 20, required: true, type: \"Number\", range: [-100, 100], step: 10},\n{name: \"h12\", value: 20, required: true, type: \"Number\", range: [-100, 100], step: 10},\n{name: \"b1\", value: -10, required: true, type: \"Number\", range: [-100, 100], step: 10},\n// hidden layer(2nd neuron)\n{name: \"h21\", value: -20, required: true, type: \"Number\", range: [-100, 100], step: 10},\n{name: \"h22\", value: -20, required: true, type: \"Number\", range: [-100, 100], step: 10},\n{name: \"b2\", value: 30, required: true, type: \"Number\", range: [-100, 100], step: 10},\n// output layer\n{name: \"o1\", value: 20, required: true, type: \"Number\", range: [-100, 100], step: 10},\n{name: \"o2\", value: 20, required: true, type: \"Number\", range: [-100, 100], step: 10},\n{name: \"b\", value: -30, required: true, type: \"Number\", range: [-100, 100], step: 10},\n],\nfunction (context) { // Init()\n    // Please don't remove the source codes below, they are required to make an EA get boosted\n\tvar account = getAccount(context, 0)\n\tvar brokerName = getBrokerNameOfAccount(account)\n\tvar accountId = getAccountIdOfAccount(account)\n\tvar symbolName = \"EUR/USD\"\n\n\tgetQuotes (context, brokerName, accountId, symbolName)\n\n},\nfunction (context) { // Deinit()\n\tvar h11 = getEAParameter(context, \"h11\") // weight\n\tvar h12 = getEAParameter(context, \"h12\") // weight\n\tvar b1 = getEAParameter(context, \"b1\") // bias\n\tvar h21 = getEAParameter(context, \"h21\")\n\tvar h22 = getEAParameter(context, \"h22\")\n\tvar b2 = getEAParameter(context, \"b2\")\n\tvar o1 = getEAParameter(context, \"o1\") // weight\n\tvar o2 = getEAParameter(context, \"o2\") // weight\n\tvar b = getEAParameter(context, \"b\") // bias\n\n\tvar sigmoid = function (t) {\n\t\treturn 1 / (1 + Math.pow(Math.E, -t))\n\t}\n\n\tvar nn = function (p1, p2) {\n\t\treturn sigmoid(o1 * sigmoid(h11 * p1 + h12 * p2 + b1) + o2 * sigmoid(h21 * p1 + h22 * p2 + b2) + b)\n\t}\n\n\tvar error = 0\n\n\terror += nn(1, 1)\n\terror += 1 - nn(1, 0)\n\terror += 1 - nn(0, 1)\n\terror += nn(0, 0)\n\n\tsetOptimizationResult(context, -error)\n\n\tprintMessage(\"error: \" + error + \", \" + Math.round(nn(1, 1)) + \" \" + Math.round(nn(1, 0)) + \" \" + Math.round(nn(0, 1)) + \" \" + Math.round(nn(0, 0)))\n},\nfunction (context) { // OnTick()\n})\n"
  },
  {
    "path": "EA/NeuralNetwork/sample_run_neuron_model.js",
    "content": "registerEA(\n\t\t\"sample_run_neuron_model\",\n\t\t\"A test EA to run neuron model(v1.04)\",\n\t\t[{ // parameters\n\t\t\tname: \"period\",\n\t\t\tvalue: 20,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t},{\n\t\t\tname: \"inputNum\",\n\t\t\tvalue: 20,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t},{\n\t\t\tname: \"threshold\",\n\t\t\tvalue: 0.3,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\t\trange: [0, 1]\n\t\t},{\n\t\t\tname: \"takeProfit\",\n\t\t\tvalue: 0.0001,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\t\trange: [0, 100]\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\t// We use localstorage.reservedZone to store the neural network.\n\t\t\t// Please don't change the name \"reservedZone\" or your data stored in this zone will be removed while the version is updated.\n\t\t\tif (typeof localStorage.reservedZone == \"undefined\") return\n\n\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\t\t\tif (typeof reservedZone.sample_training_neuron_model == \"undefined\") return\n\t\t\tcontext.myPerceptron = synaptic.Network.fromJSON(reservedZone.sample_training_neuron_model)\n\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tgetQuotes (context, brokerName, accountId, symbolName)\n\t\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)\n\t\t\tvar period = getEAParameter(context, \"period\")\n\t\t\tcontext.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, \"rsi\", [{\n\t\t\t\tname: \"period\",\n\t\t\t\tvalue: period\n\t\t\t}])\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t\tvar arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n\t\t\tif (typeof context.currTime == \"undefined\") {\n\t\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\n\t\t\t} else if (context.currTime != arrTime[arrTime.length - 1]) {\n\t\t\t\tcontext.currTime = arrTime[arrTime.length - 1]\n\t\t\t} else {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tvar period = getEAParameter(context, \"period\")\n\t\t\tvar inputNum = getEAParameter(context, \"inputNum\")\n\t\t\tvar threshold = getEAParameter(context, \"threshold\")\n\t\t\tvar takeProfit = getEAParameter(context, \"takeProfit\")\n\t\t\tvar arrRsi = getData(context, context.indiHandle, \"rsi\")\n\n\t\t\tif (inputNum + period - 1 > arrRsi.length) throw new Error(\"No enough data.\")\n\n\t\t\tvar input = []\n\n\t\t\tfor (var i = arrRsi.length - inputNum - 1; i < arrRsi.length - 1; i++) {\n\t\t\t\tinput.push(arrRsi[i] / 100)\n\t\t\t}\n\n\t\t\tvar result = context.myPerceptron.activate(input)[0]\n\t\t\tprintMessage(result)\n\n\t\t\tvar ask = null\n\t\t\tvar bid = null\n\t\t\tvar volume = 0.01\n\n\t\t\ttry {\n\t\t\t\task = getAsk(context, brokerName, accountId, symbolName)\n\t\t\t\tbid = getBid(context, brokerName, accountId, symbolName)\n\t\t\t} catch (e) {\n\t\t\t\t// This try-catch is used to bypass the \"error throw\" when you start the EA too early to call getAsk or getBid(at that time, bid or ask may be not ready yet.)\n\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (result < 0.5 - threshold) {\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, ask+takeProfit, bid-3*takeProfit, \"\", 0, 0)\n\t\t\t} else if (result > 0.5 + threshold) {\n\t\t\t\tsendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, bid-takeProfit, ask+3*takeProfit, \"\", 0, 0)\n\t\t\t}\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/NeuralNetwork/sample_training_neuron_model.js",
    "content": "registerEA(\n\t\t\"sample_training_neuron_model\",\n\t\t\"A test EA to train neuron model(v1.03)\",\n\t\t[{ // parameters\n\t\t\tname: \"period\",\n\t\t\tvalue: 20,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t},{\n\t\t\tname: \"inputNum\",\n\t\t\tvalue: 20,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t},{\n\t\t\tname: \"hiddenNum\",\n\t\t\tvalue: 50,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [1, 100]\n\t\t},{\n\t\t\tname: \"diffPrice\",\n\t\t\tvalue: 0.0001,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\t\trange: [0, 10]\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = \"EUR/USD\"\n\n\t\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)\n\t\t\tvar period = getEAParameter(context, \"period\")\n\t\t\tcontext.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, \"rsi\", [{\n\t\t\t\tname: \"period\",\n\t\t\t\tvalue: period\n\t\t\t}])\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t\tvar period = getEAParameter(context, \"period\")\n\t\t\tvar inputNum = getEAParameter(context, \"inputNum\")\n\t\t\tvar hiddenNum = getEAParameter(context, \"hiddenNum\")\n\t\t\tvar arrOpen = getData(context, context.chartHandle, DATA_NAME.OPEN)\n\t\t\tvar arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)\n\t\t\tvar arrRsi = getData(context, context.indiHandle, \"rsi\")\n\n\t\t\tif (arrRsi.length <= period + 1) return\n\t\t\tif (inputNum + period - 1 > arrRsi.length) throw new Error(\"No enough data.\")\n\n\t\t\t// extend the prototype chain\n\t\t\tPerceptron.prototype = new synaptic.Network()\n\t\t\tPerceptron.prototype.constructor = Perceptron\n\n\t\t\tvar myPerceptron = new Perceptron(inputNum, hiddenNum, 1)\n\t\t\tvar myTrainer = new synaptic.Trainer(myPerceptron)\n\n\t\t\tvar diffPrice = getEAParameter(context, \"diffPrice\")\n\t\t\tvar trainingSet = []\n\t\t\tvar longCount = 0\n\t\t\tvar shortCount = 0\n\n\t\t\tfor (var i = period - 1; i < arrRsi.length - inputNum; i++) {\n\t\t\t\tif (arrClose[i * inputNum + inputNum] - arrOpen[i * inputNum + inputNum] > diffPrice) {\n\t\t\t\t\tvar input = []\n\n\t\t\t\t\tfor (var j = 0; j < inputNum; j++) {\n\t\t\t\t\t\tinput.push(arrRsi[i * inputNum + j] / 100)\n\t\t\t\t\t}\n\n\t\t\t\t\ttrainingSet.push({\n\t\t\t\t\t\tinput: input,\n\t\t\t\t\t\toutput: [0]\n\t\t\t\t\t})\n\n\t\t\t\t\tlongCount++\n\t\t\t\t} else if (arrOpen[i * inputNum + inputNum] - arrClose[i * inputNum + inputNum] > diffPrice) {\n\t\t\t\t\tvar input = []\n\n\t\t\t\t\tfor (var j = 0; j < inputNum; j++) {\n\t\t\t\t\t\tinput.push(arrRsi[i * inputNum + j] / 100)\n\t\t\t\t\t}\n\n\t\t\t\t\ttrainingSet.push({\n\t\t\t\t\t\tinput: input,\n\t\t\t\t\t\toutput: [1]\n\t\t\t\t\t})\n\n\t\t\t\t\tshortCount++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmyTrainer.train(trainingSet)\n\n\t\t\t// We use localstorage.reservedZone to store the neural network.\n\t\t\t// Please don't change the name \"reservedZone\" or your data stored in this zone will be removed while the version is updated.\n\t\t\tif (typeof localStorage.reservedZone == \"undefined\") {\n\t\t\t\tlocalStorage.reservedZone = JSON.stringify({sample_training_neuron_model: myPerceptron.toJSON()})\n\t\t\t} else {\n\t\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\t\t\t\treservedZone.sample_training_neuron_model = myPerceptron.toJSON()\n\t\t\t\tlocalStorage.reservedZone = JSON.stringify(reservedZone)\n\t\t\t}\n\n\t\t\tprintMessage(longCount + \", \" + shortCount)\n\t\t\tprintMessage(JSON.stringify(trainingSet))\n\t\t\tprintMessage(JSON.stringify(myPerceptron.toJSON()))\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/NeuralNetwork/usage.txt",
    "content": "“sample_training_neuron_model” and “sample_run_neuron_model” are two neural network-based EAs that must be used together. One cannot function without the other.\n“sample_training_neuron_model” trains the model, while “sample_run_neuron_model” generates signals based on the model trained by “sample_training_neuron_model”.\n\nTo help understand how a neural network works, we have included a simple example called “nn_example”.\n\nThe algorithm implemented in this folder is based on Synaptic, an AI framework. Tensorflow, a more advanced framework, runs convolutional neural networks. For more details on Tensorflow, refer to plugin_for_tensorflow.\n"
  },
  {
    "path": "EA/Oldie/README.md",
    "content": "This folder contains the deprecated programs.\n"
  },
  {
    "path": "EA/Oldie/README.txt",
    "content": "This folder contains deprecated programs.\n"
  },
  {
    "path": "EA/Oldie/fixapi_oanda_arbitrage.js",
    "content": "// Deprecated. A new version has been released. Please refer to EA/fintechee_external_arbitrage.js.\nregisterEA(\n  \"fixapi_oanda_arbitrage\",\n  \"A test EA to trade arbitrage based on the price difference between FIX API and Oanda(v1.10)\",\n  [{\n    name: \"autoLoad\",\n    value: true,\n    required: true,\n    type: PARAMETER_TYPE.BOOLEAN,\n    range: null\n  }, {\n    name: \"autoSave\",\n    value: true,\n    required: true,\n    type: PARAMETER_TYPE.BOOLEAN,\n    range: null\n  }, {\n    name: \"backgroundColor\",\n    value: \"#dfc29a\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function (context) { // Init()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    window.autoLoadArbitrageStats = getEAParameter(context, \"autoLoad\")\n    window.autoSaveArbitrageStats = getEAParameter(context, \"autoSave\")\n    window.arbitrageBgColor = getEAParameter(context, \"backgroundColor\")\n    window.latestDay = new Date().getDay()\n\n    if (typeof window.oandaLoaded != \"undefined\" && window.oandaLoaded) {\n      window.latestFIXTickTime = new Date().getTime()\n      window.latestSaveTime = window.latestFIXTickTime\n\n      if (typeof window.arbitrageStatistics == \"undefined\") {\n        for (var i in window.oandaApiLoader.oandaQuotes) {\n          getQuotes(context, brokerName, accountId, i.replace(\"_\", \"/\"))\n        }\n\n        window.arbitrageStatistics = []\n\n        for (var i in window.oandaApiLoader.oandaQuotes) {\n          window.arbitrageStatistics[i] = {\n            h: [],\n            h2: [],\n            ph: [],\n            ph2: []\n          }\n          for (var j = 0; j <= 23; j++) {\n            window.arbitrageStatistics[i].h.push(0)\n            window.arbitrageStatistics[i].h2.push(0)\n            window.arbitrageStatistics[i].ph.push(0)\n            window.arbitrageStatistics[i].ph2.push(0)\n          }\n        }\n\n        window.loadArbitrageStatistics = function (arbitrageStatistics) {\n          if (typeof localStorage.reservedZone != \"undefined\") {\n            var reservedZone = JSON.parse(localStorage.reservedZone)\n\n            if (typeof reservedZone.arbitrageStatistics != \"undefined\" && typeof reservedZone.arbitrageStatistics.statistics != \"undefined\") {\n              if (new Date(reservedZone.arbitrageStatistics.latestSaveTime).getDay() < window.latestDay) {\n                for (var i in reservedZone.arbitrageStatistics.statistics) {\n                  var statistics = reservedZone.arbitrageStatistics.statistics[i]\n                  arbitrageStatistics[statistics.symbolName] = {\n                    h: [],\n                    h2: [],\n                    ph: statistics.h,\n                    ph2: statistics.h2\n                  }\n                  for (var j = 0; j <= 23; j++) {\n                    arbitrageStatistics[statistics.symbolName].h.push(0)\n                    arbitrageStatistics[statistics.symbolName].h2.push(0)\n                  }\n                }\n              } else {\n                for (var i in reservedZone.arbitrageStatistics.statistics) {\n                  var statistics = reservedZone.arbitrageStatistics.statistics[i]\n                  arbitrageStatistics[statistics.symbolName] = {\n                    h: statistics.h,\n                    h2: statistics.h2,\n                    ph: statistics.ph,\n                    ph2: statistics.ph2\n                  }\n                }\n              }\n            }\n          }\n        }\n\n        window.saveArbitrageStatistics = function (arbitrageStatistics) {\n          var reservedZone = {}\n\n          if (typeof localStorage.reservedZone != \"undefined\") {\n            reservedZone = JSON.parse(localStorage.reservedZone)\n          }\n\n          reservedZone.arbitrageStatistics = {\n            latestSaveTime: new Date().getTime(),\n            statistics: []\n          }\n\n          for (var i in arbitrageStatistics) {\n            reservedZone.arbitrageStatistics.statistics.push({\n              symbolName: i,\n              h: arbitrageStatistics[i].h,\n              h2: arbitrageStatistics[i].h2,\n              ph: arbitrageStatistics[i].ph,\n              ph2: arbitrageStatistics[i].ph2\n            })\n          }\n\n          localStorage.reservedZone = JSON.stringify(reservedZone)\n        }\n\n        window.countArbitrage = function (symbolName, hour) {\n          window.arbitrageStatistics[symbolName].h[hour]++\n        }\n\n        window.countArbitrage2 = function (symbolName, hour) {\n          window.arbitrageStatistics[symbolName].h2[hour]++\n        }\n      }\n\n      if (typeof $(\"#arbitrage_dashboard\").html() != \"undefined\") {\n        $(\"#arbitrage_dashboard\").remove()\n      }\n\n      var arbitrageChartPanel = '<div id=\"arbitrage_chart_dashboard\" style=\"background:' + window.arbitrageBgColor + ';height:100%\">' +\n        '<div class=\"row\" style=\"background:' + window.arbitrageBgColor + ';text-align:center\">' +\n          '<div class=\"ui buttons\">' +\n            // '<div class=\"ui button\" style=\"background:' + window.arbitrageBgColor + '\" id=\"btn_show_arbitrage_prices\">List</div>' +\n            '<div class=\"ui button\" style=\"background:' + window.arbitrageBgColor + '\" id=\"btn_load_arbitrage_statistics\">Load</div>' +\n            '<div class=\"ui button\" style=\"background:' + window.arbitrageBgColor + '\" id=\"btn_save_arbitrage_statistics\">Save</div>' +\n          '</div>' +\n        '</div>' +\n        '<div class=\"row\">' +\n          '<table id=\"arbitrage_prices\" class=\"cell-border\">' +\n          '</table>' +\n        '</div>' +\n        '<div class=\"row\">' +\n          '<div class=\"chart-container\" style=\"background:' + window.arbitrageBgColor + ';position:relative;height:35vh\">' +\n            '<canvas id=\"arbitrage_chart\"></canvas>' +\n          '</div>' +\n        '</div>' +\n      '</div>'\n\n      var arbitragePricesPanel = '<div class=\"ui fullscreen modal\" id=\"arbitrage_prices_dashboard\">' +\n        '<div class=\"content\">' +\n        '</div>' +\n      '</div>'\n\n      $(\"#reserved_zone\").append(arbitragePricesPanel)\n\n      if (getLayoutId() != 3) {\n  \t\t\tchangeLayout(3)\n  \t\t}\n\n  \t\twindow.chartIds = getLayout(2)\n  \t\tfor (var i in window.chartIds) {\n  \t\t\tmoveLayout(window.chartIds[i], 1)\n  \t\t}\n\n      embedHtml(arbitrageChartPanel, 2)\n\n      if (!$.fn.dataTable.isDataTable(\"#arbitrage_prices\")) {\n  \t\t\twindow.arbitragePricesTable = $(\"#arbitrage_prices\").DataTable({\n  \t\t\t\tdata: [],\n  \t\t\t\tcolumns: [\n            {title: \"Instruments\"},\n            {title: \"FIX-Oanda\",\n  \t\t\t\t\trender: function (data, type, row) {\n  \t\t\t\t\t\t\tif (data > 0) {\n  \t\t\t\t\t\t\t\treturn '<p style = \"background:#21BA45;color:#FFFFFF\" >' + data + '</p>'\n  \t\t\t\t\t\t\t} else {\n  \t\t\t\t\t\t\t\treturn '<p style = \"background:' + window.arbitrageBgColor + ';color:#DB2828\" >' + data + '</p>'\n  \t\t\t\t\t\t\t}\n  \t\t\t\t\t\t}\n  \t\t\t\t\t},\n            {title: \"Oanda-FIX\",\n  \t\t\t\t\trender: function (data, type, row) {\n                if (data > 0) {\n                  return '<p style = \"background:#21BA45;color:#FFFFFF\" >' + data + '</p>'\n                } else {\n                  return '<p style = \"background:' + window.arbitrageBgColor + ';color:#DB2828\" >' + data + '</p>'\n                }\n  \t\t\t\t\t\t}\n  \t\t\t\t\t},\n            {title: \"Oanda\"},\n            {title: \"Op\"}\n  \t\t\t\t],\n          headerCallback: function (thead, data, start, end, display) {\n            $(thead).css(\"background-color\", window.arbitrageBgColor)\n          },\n          rowCallback: function (row, data, index) {\n            $(\"td\", row).css(\"background-color\", window.arbitrageBgColor)\n          },\n          ordering: false,\n          searching: false,\n          bPaginate: false,\n          bLengthChange: false,\n          bFilter: false,\n          bInfo: false,\n          scrollY: \"50vh\",\n          scrollCollapse: true,\n          paging: false,\n          columnDefs: [\n            {width: \"20%\", targets: 0, className: \"dt-body-center\"},\n            {width: \"20%\", targets: 1, className: \"dt-body-right\"},\n            {width: \"20%\", targets: 2, className: \"dt-body-right\"},\n            {width: \"20%\", targets: 3, className: \"dt-body-right\"},\n            {width: \"20%\", targets: 4, className: \"dt-body-center\"},\n            {width: \"20%\", targets: [0], className: \"dt-head-center\"},\n            {width: \"20%\", targets: [1], className: \"dt-head-center\"},\n            {width: \"20%\", targets: [2], className: \"dt-head-center\"},\n            {width: \"20%\", targets: [3], className: \"dt-head-center\"},\n            {width: \"20%\", targets: [4], className: \"dt-head-center\"},\n            {\n              targets: -1,\n              data: null,\n              defaultContent: '<button id=\"btn_check_arbitrage\" class=\"ui button\" style=\"padding:0;background:' + window.arbitrageBgColor + '\"><i class=\"tachometer alternate blue icon\"></i></button>' +\n                              '<button id=\"btn_sell\" class=\"ui button\" style=\"padding:0;background:' + window.arbitrageBgColor + ';color:#DB2828\">S</button>' +\n                              '<button id=\"btn_buy\" class=\"ui button\" style=\"padding:0;background:' + window.arbitrageBgColor + ';color:#21BA45\">B</button>'\n            }\n          ]\n  \t\t\t})\n\n        for (var i in window.oandaApiLoader.oandaQuotes) {\n          $(\"#arbitrage_prices\").DataTable().row.add([\n            i,\n            \"\",\n            \"\",\n            \"\",\n            \"\"\n          ]).draw(false)\n        }\n\n        $(\"#arbitrage_prices tbody\").on(\"click\", \"[id*=btn_check_arbitrage]\", function () {\n          if (typeof window.arbitragePricesTable != \"undefined\") {\n            var data = window.arbitragePricesTable.row($(this).parents(\"tr\")).data()\n            if (typeof data == \"undefined\") {\n              data = window.arbitragePricesTable.row($(this)).data()\n            }\n\n            window.currentChartSymbolName = data[0]\n            window.arbitrageChart.data.datasets[0].label = window.currentChartSymbolName + \"(F-O)\"\n            window.arbitrageChart.data.datasets[1].label = window.currentChartSymbolName + \"(O-F)\"\n            window.arbitrageChart.data.datasets[2].label = window.currentChartSymbolName + \"(F-O)\"\n            window.arbitrageChart.data.datasets[3].label = window.currentChartSymbolName + \"(O-F)\"\n            window.updateArbitrageChart(data[0], true, -1)\n            window.updateArbitrageChart2(data[0], true, -1)\n          }\n        })\n\n        $(\"#btn_load_arbitrage_statistics\").on(\"click\", function () {\n          window.loadArbitrageStatistics(window.arbitrageStatistics)\n        })\n\n        $(\"#btn_save_arbitrage_statistics\").on(\"click\", function () {\n          window.saveArbitrageStatistics(window.arbitrageStatistics)\n        })\n  \t\t}\n\n      if (window.autoLoadArbitrageStats) {\n        window.loadArbitrageStatistics(window.arbitrageStatistics)\n      }\n\n      if (typeof window.initArbitrageChart != \"undefined\") {\n        window.initArbitrageChart(window.arbitrageStatistics)\n      } else {\n        var script = document.createElement(\"script\")\n        document.body.appendChild(script)\n        script.onload = function () {\n          window.initArbitrageChart = function (arbitrageStatistics) {\n            var ctx = document.getElementById(\"arbitrage_chart\").getContext(\"2d\")\n            window.currentChartSymbolName = \"EUR/USD\"\n            var statistics = arbitrageStatistics[window.currentChartSymbolName]\n\n            var labels = []\n            var data = []\n            var data2 = []\n            var pdata = []\n            var pdata2 = []\n            for (var i = 0; i <= 23; i++) {\n              labels.push(i + \"\")\n              data.push(statistics.h[i])\n              data2.push(statistics.h2[i])\n              pdata.push(statistics.ph[i])\n              pdata2.push(statistics.ph2[i])\n            }\n\n            window.arbitrageChart = new Chart(ctx, {\n                type: \"line\",\n                data: {\n                    labels: labels,\n                    datasets: [{\n                        label: window.currentChartSymbolName + \"(F-O)\",\n                        backgroundColor: \"rgba(255,255,255,0)\",\n                        borderColor: \"#DB2828\",\n                        data: data\n                    }, {\n                        label: window.currentChartSymbolName + \"(O-F)\",\n                        backgroundColor: \"rgba(255,255,255,0)\",\n                        borderColor: \"#21BA45\",\n                        data: data2\n                    }, {\n                        label: window.currentChartSymbolName + \"(F-O)\",\n                        backgroundColor: \"rgba(255,255,255,0)\",\n                        borderColor: \"#DB2828\",\n                        borderDash: [2, 3],\n                        data: pdata\n                    }, {\n                        label: window.currentChartSymbolName + \"(O-F)\",\n                        backgroundColor: \"rgba(255,255,255,0)\",\n                        borderColor: \"#21BA45\",\n                        borderDash: [2, 3],\n                        data: pdata2\n                    }]\n                },\n                options: {\n                  responsive: true,\n                  maintainAspectRatio: false\n                }\n            })\n          }\n\n          window.updateArbitrageChart = function (symbolName, bAll, hour) {\n            if (bAll) {\n              for (var i = 0; i <= 23; i++) {\n                window.arbitrageChart.data.datasets[0].data[i] = window.arbitrageStatistics[symbolName].h[i]\n                window.arbitrageChart.data.datasets[2].data[i] = window.arbitrageStatistics[symbolName].ph[i]\n              }\n            } else {\n              window.arbitrageChart.data.datasets[0].data[hour] = window.arbitrageStatistics[symbolName].h[hour]\n            }\n\n            window.arbitrageChart.update()\n          }\n\n          window.updateArbitrageChart2 = function (symbolName, bAll, hour) {\n            if (bAll) {\n              for (var i = 0; i <= 23; i++) {\n                window.arbitrageChart.data.datasets[1].data[i] = window.arbitrageStatistics[symbolName].h2[i]\n                window.arbitrageChart.data.datasets[3].data[i] = window.arbitrageStatistics[symbolName].ph2[i]\n              }\n            } else {\n              window.arbitrageChart.data.datasets[1].data[hour] = window.arbitrageStatistics[symbolName].h2[hour]\n            }\n\n            window.arbitrageChart.update()\n          }\n\n          window.updatePrevArbitrage = function () {\n            for (var i in window.arbitrageStatistics) {\n              window.arbitrageStatistics[i].ph = window.arbitrageStatistics[i].h\n              window.arbitrageStatistics[i].ph2 = window.arbitrageStatistics[i].h2\n              window.arbitrageStatistics[i].h = []\n              window.arbitrageStatistics[i].h2 = []\n\n              for (var j = 0; j <= 23; j++) {\n                window.arbitrageStatistics[i].h.push(0)\n                window.arbitrageStatistics[i].h2.push(0)\n              }\n            }\n          }\n\n          window.initArbitrageChart(window.arbitrageStatistics)\n        }\n        script.onerror = function () {\n          alert(\"Failed to load required libs. Please refresh this page again.\")\n        }\n        script.async = true\n        script.src = \"https://cdn.jsdelivr.net/npm/chart.js@2.8.0\"\n      }\n\n      window.arbitrageNotification = \"\"\n    } else {\n      throw new Error(\"You need to run fintechee_oanda_loader(you can find it in our Github repo -- Plugin-for-Data-API) first. If you have run the loader, please be patient with the loading time.\")\n    }\n  },\n  function (context) { // Deinit()\n    embedHtml(\"\", 2)\n\n\t\tfor (var i in window.chartIds) {\n\t\t\tmoveLayout(window.chartIds[i], 2)\n\t\t}\n  },\n  function (context) { // OnTick()\n    if (typeof window.oandaLoaded != \"undefined\" && window.oandaLoaded) {\n      if (typeof window.latestFIXTickTime == \"undefined\" || typeof window.latestOandaTickTime == \"undefined\") return\n\n      var currTime = new Date().getTime()\n      var hour = new Date(currTime).getHours()\n      var day = new Date(currTime).getDay()\n      if (currTime - window.latestOandaTickTime > 30000) {\n        window.oandaApiLoader.resetupSocket()\n        window.oandaLoaded = false\n        return\n      }\n\n      if (window.autoSaveArbitrageStats && currTime - window.latestSaveTime > 60000) {\n        window.saveArbitrageStatistics(window.arbitrageStatistics)\n        window.latestSaveTime = currTime\n      }\n\n      window.latestFIXTickTime = currTime\n\n      var account = getAccount(context, 0)\n      var brokerName = getBrokerNameOfAccount(account)\n      var accountId = getAccountIdOfAccount(account)\n\n      var currentTick = getCurrentTick(context)\n      var symbolName = currentTick.symbolName\n      var askFIXAPI = currentTick.ask\n      var bidFIXAPI = currentTick.bid\n\n      if (window.latestDay != day) {\n        window.updatePrevArbitrage()\n        window.updateArbitrageChart(symbolName, true, -1)\n        window.updateArbitrageChart2(symbolName, true, -1)\n        window.latestDay = day\n      }\n\n      if (window.oandaApiLoader.oandaQuotes[symbolName] == null) return\n\n      var askOanda = window.oandaApiLoader.oandaQuotes[symbolName].ask\n      var bidOanda = window.oandaApiLoader.oandaQuotes[symbolName].bid\n\n      if (askFIXAPI != null && bidFIXAPI != null && askOanda != null && bidOanda != null) {\n        var table = $('#arbitrage_prices').DataTable()\n        var tb = $('#arbitrage_prices').dataTable()\n\n        table.columns().eq(0).each(function (index) {\n          if (index == 0) {\n            var column = table.column(index).data()\n            for (var i in column) {\n              if (isNaN(i)) continue\n\n              var rowId = parseInt(i)\n\n              if (column[i] == symbolName) {\n                tb.fnUpdate(Math.round((bidOanda - askFIXAPI) * 100000) / 100000, rowId, 1, false, false)\n                tb.fnUpdate(Math.round((bidFIXAPI - askOanda) * 100000) / 100000, rowId, 2, false, false)\n                tb.fnUpdate(Math.round((askOanda + bidOanda) / 2 * 100000) / 100000, rowId, 3, false, false)\n                break\n              }\n            }\n          }\n        })\n\n        if (bidOanda > askFIXAPI) {\n          window.countArbitrage(symbolName, hour)\n          if (symbolName == window.currentChartSymbolName) {\n            window.updateArbitrageChart(symbolName, false, hour)\n          }\n          // var msg = new Date() + \" \" + symbolName + \" Chance!! Oanda Bid: \" + bidOanda + \", FIXAPI Ask: \" + askFIXAPI + \", Difference: \" + (bidOanda - askFIXAPI) + \"\\n\"\n          // printMessage(msg)\n        }\n        if (bidFIXAPI > askOanda) {\n          window.countArbitrage2(symbolName, hour)\n          if (symbolName == window.currentChartSymbolName) {\n            window.updateArbitrageChart2(symbolName, false, hour)\n          }\n          // var msg = new Date() + \" \" + symbolName + \" Chance!! FIXAPI Bid: \" + bidFIXAPI + \", Oanda Ask: \" + askOanda + \", Difference: \" + (bidFIXAPI - askOanda) + \"\\n\"\n          // printMessage(msg)\n        }\n      }\n    }\n  }\n)\n"
  },
  {
    "path": "EA/Plugin-for-Deribit/plugin_for_deribit.js",
    "content": "registerEA(\n\"plugin_for_deribit\",\n\"A plugin to trade cryptocurrency options(v0.08)\",\n[{\n\tname: \"interval\",\n\tvalue: 30,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: null,\n\tstep: null\n}],\nfunction (context) { // Init()\n      var orderBookId = null\n      var loaded = false\n      var latestHb = null\n\n      var interval = getEAParameter(context, \"interval\") * 1000\n\n      function convertOptionName (rawName) {\n        var name = rawName.split(\"-\")\n        var year = name[1].substring(5, 7)\n        var mon = name[1].substring(2, 5)\n        var dt = name[1].substring(0, 2)\n        var month = \"00\"\n        if (mon == \"JAN\") {\n          month = \"01\"\n        } else if (mon == \"FEB\") {\n          month = \"02\"\n        } else if (mon == \"MAR\") {\n          month = \"03\"\n        } else if (mon == \"APR\") {\n          month = \"04\"\n        } else if (mon == \"MAY\") {\n          month = \"05\"\n        } else if (mon == \"JUN\") {\n          month = \"06\"\n        } else if (mon == \"JUL\") {\n          month = \"07\"\n        } else if (mon == \"AUG\") {\n          month = \"08\"\n        } else if (mon == \"SEP\") {\n          month = \"09\"\n        } else if (mon == \"OCT\") {\n          month = \"10\"\n        } else if (mon == \"NOV\") {\n          month = \"11\"\n        } else if (mon == \"DEC\") {\n          month = \"12\"\n        }\n        var expiration = parseInt(year + month + dt)\n        var optionName2 = name[0] + \"-\" + dt + mon + year\n\n        return {\n          optionName: name[0] + \"-\" + expiration,\n          optionName2: optionName2,\n          instrument: name[0],\n          expiration: expiration,\n          year: year,\n          month: month,\n          dt: dt,\n          strikePrice: parseFloat(name[2]),\n          callOrPut: name[3]\n        }\n      }\n\n      function parseOrderBook (data) {\n        var orderBookData = []\n\n        for (var i in data) {\n          var optionName = convertOptionName(data[i].instrument_name)\n\n          if (typeof orderBookData[optionName.optionName] == \"undefined\") {\n            orderBookData[optionName.optionName] = {\n              optionName: optionName.optionName,\n              optionName2: optionName.optionName2,\n              instrument: optionName.instrument,\n              expiration: optionName.expiration,\n              year: optionName.year,\n              month: optionName.month,\n              dt: optionName.dt,\n              prices: [],\n              arrPrices: []\n            }\n          }\n\n          if (typeof orderBookData[optionName.optionName].prices[optionName.strikePrice] == \"undefined\") {\n            orderBookData[optionName.optionName].prices[optionName.strikePrice] = {\n              strikePrice: optionName.strikePrice,\n              bidC: optionName.callOrPut == \"C\" ? data[i].bid_price : null,\n              askC: optionName.callOrPut == \"C\" ? data[i].ask_price : null,\n              bidP: optionName.callOrPut == \"P\" ? data[i].bid_price : null,\n              askP: optionName.callOrPut == \"P\" ? data[i].ask_price : null\n            }\n          } else {\n            var price = orderBookData[optionName.optionName].prices[optionName.strikePrice]\n            if (price.bidC == null) {\n              price.bidC = optionName.callOrPut == \"C\" ? data[i].bid_price : null\n            }\n            if (price.askC == null) {\n              price.askC = optionName.callOrPut == \"C\" ? data[i].ask_price : null\n            }\n            if (price.bidP == null) {\n              price.bidP = optionName.callOrPut == \"P\" ? data[i].bid_price : null\n            }\n            if (price.askP == null) {\n              price.askP = optionName.callOrPut == \"P\" ? data[i].ask_price : null\n            }\n          }\n        }\n\n        for (var i in orderBookData) {\n          for (var j in orderBookData[i].prices) {\n            orderBookData[i].arrPrices.push(orderBookData[i].prices[j])\n          }\n        }\n\n        var expirations = []\n\n        for (var i in orderBookData) {\n          expirations.push({\n            expiration: orderBookData[i].expiration,\n            optionName: orderBookData[i].optionName,\n            optionName2: orderBookData[i].optionName2\n          })\n        }\n\n        expirations.sort(function (a, b) {return a.expiration - b.expiration})\n\n        return {\n          expirations: expirations,\n          orderBookData: orderBookData\n        }\n      }\n\n      function showOptions (expirations) {\n        var optionsHtml = \"\"\n\n        for (var i in expirations) {\n          optionsHtml += '<div class=\"item\" data-value=\"' + expirations[i].optionName + '\">' + expirations[i].optionName2 + '</div>'\n        }\n\n        $(\"#crypto_options\").empty()\n        $(\"#crypto_options\").html(optionsHtml)\n        $(\"#crypto_options_dashboard\").find(\".ui.dropdown\").dropdown(\"clear\")\n        $(\"#crypto_options_dashboard\").find(\".ui.dropdown\").dropdown({\n          autoFocus: false,\n          showOnFocus: false,\n          onChange: function (val) {\n            for (var i in window.subscriptionIds) {\n              unsubscribeIt(i)\n            }\n            window.subscriptionIds = []\n            showOrderBook(val, window.orderBookData.orderBookData)\n          }\n        })\n      }\n\n      function checkHb () {\n        if (new Date().getTime() - latestHb > interval) {\n          printMessage(\"Timeout... Refreshing...\")\n          if (typeof window.wsockOpened != \"undefined\" && window.wsockOpened) {\n            loaded = true\n          }\n          initCryptoOptionsWS()\n        }\n      }\n\n      function showOrderBook (optionName, orderBookData) {\n        if ($.fn.dataTable.isDataTable(\"#crypto_options_orderbook\")) {\n    \t\t\t$(\"#crypto_options_orderbook\").DataTable().clear().draw()\n\n          for (var i in orderBookData) {\n            if (orderBookData[i].optionName == optionName) {\n              for (var j in orderBookData[i].arrPrices) {\n                $(\"#crypto_options_orderbook\").DataTable().row.add([\n                  orderBookData[i].arrPrices[j].bidC != null ? orderBookData[i].arrPrices[j].bidC : \"\",\n                  orderBookData[i].arrPrices[j].askC != null ? orderBookData[i].arrPrices[j].askC : \"\",\n                  orderBookData[i].arrPrices[j].strikePrice,\n                  orderBookData[i].arrPrices[j].bidP != null ? orderBookData[i].arrPrices[j].bidP : \"\",\n                  orderBookData[i].arrPrices[j].askP != null ? orderBookData[i].arrPrices[j].askP : \"\",\n                  0,\n                  0,\n                  0,\n                  0\n                ]).draw(false)\n\n                subscribeIt(orderBookData[i].optionName2 + \"-\" + orderBookData[i].arrPrices[j].strikePrice + \"-\" + \"C\")\n                subscribeIt(orderBookData[i].optionName2 + \"-\" + orderBookData[i].arrPrices[j].strikePrice + \"-\" + \"P\")\n              }\n            }\n          }\n        }\n      }\n\n      function initCryptoOptionsWS () {\n        $(\"#disconnect_ws\").html(\"Loading...\")\n        $(\"#disconnect_ws\").addClass(\"disabled\")\n        $(\"#disconnect_ws\").addClass(\"loading\")\n\n        if (typeof window.wsock != \"undefined\" && typeof window.subscriptionIds != \"undefined\") {\n          for (var i in window.subscriptionIds) {\n            unsubscribeIt(i)\n          }\n        }\n\n        window.wsock = new WebSocket(\"wss://test.deribit.com/ws/api/v2\")\n        window.wsockOpened = false\n\n        window.wsock.onmessage = function (e) {\n          var resData = JSON.parse(e.data)\n          if (orderBookId != null && typeof resData.id != \"undefined\" && orderBookId == resData.id) {\n            window.orderBookData = parseOrderBook(resData.result)\n            showOptions(window.orderBookData.expirations)\n            showOrderBook(window.orderBookData.expirations[0].optionName, window.orderBookData.orderBookData)\n            $(\"#disconnect_ws\").html(\"Disconnect\")\n            $(\"#disconnect_ws\").removeClass(\"loading\")\n            $(\"#disconnect_ws\").removeClass(\"disabled\")\n          } else if (typeof resData.params != \"undefined\" &&\n            typeof resData.params.data != \"undefined\" && typeof resData.params.data.instrument_name != \"undefined\" &&\n            typeof window.subscriptionIds[resData.params.data.instrument_name] != \"undefined\") {\n\n            latestHb = new Date().getTime()\n            var name = resData.params.data.instrument_name.split(\"-\")\n            var bid = (resData.params.data.best_bid_price != null && resData.params.data.best_bid_price != 0) ? resData.params.data.best_bid_price : \"\"\n            var ask = (resData.params.data.best_ask_price != null && resData.params.data.best_ask_price != 0) ? resData.params.data.best_ask_price : \"\"\n\n            var table = $(\"#crypto_options_orderbook\").DataTable()\n            var tb = $(\"#crypto_options_orderbook\").dataTable()\n\n            table.columns().eq(0).each(function (index) {\n              if (index == 2) {\n                var column = table.column(index).data()\n                for (var i in column) {\n                  var rowId = parseInt(i)\n\n                  var row = table.row(rowId).data()\n\n                  if (column[i] == parseFloat(name[2])) {\n                    if (name[3] == \"C\") {\n                      if (row[0] != null && row[0] != \"\" && bid != \"\") {\n                        tb.fnUpdate(bid - row[0], rowId, 5, false, false)\n                      } else {\n                        tb.fnUpdate(0, rowId, 5, false, false)\n                      }\n                      if (row[1] != null && row[1] != \"\" && ask != \"\") {\n                        tb.fnUpdate(ask - row[1], rowId, 6, false, false)\n                      } else {\n                        tb.fnUpdate(0, rowId, 6, false, false)\n                      }\n                      tb.fnUpdate(bid, rowId, 0, false, false)\n                      tb.fnUpdate(ask, rowId, 1, false, false)\n                    } else if (name[3] == \"P\") {\n                      if (row[3] != null && row[3] != \"\" && bid != \"\") {\n                        tb.fnUpdate(bid - row[3], rowId, 7, false, false)\n                      } else {\n                        tb.fnUpdate(0, rowId, 7, false, false)\n                      }\n                      if (row[4] != null && row[4] != \"\" && ask != \"\") {\n                        tb.fnUpdate(ask - row[4], rowId, 8, false, false)\n                      } else {\n                        tb.fnUpdate(0, rowId, 8, false, false)\n                      }\n                      tb.fnUpdate(bid, rowId, 3, false, false)\n                      tb.fnUpdate(ask, rowId, 4, false, false)\n                    }\n                    break\n                  }\n                }\n              }\n            })\n          }\n        }\n\n        window.wsock.onopen = function () {\n          latestHb = new Date().getTime()\n          window.wsockOpened = true\n          if (loaded) {\n            for (var i in window.subscriptionIds) {\n              subscribeIt(i)\n            }\n\n            $(\"#disconnect_ws\").html(\"Disconnect\")\n            $(\"#disconnect_ws\").removeClass(\"loading\")\n            $(\"#disconnect_ws\").removeClass(\"disabled\")\n          } else {\n            getOrderBook(\"BTC\")\n          }\n        }\n      }\n\n      function disconnectCryptoOptionsWS () {\n        if (typeof window.wsockOpened != \"undefined\" && window.wsockOpened) {\n          $(\"#disconnect_ws\").html(\"Disconnected\")\n          $(\"#disconnect_ws\").addClass(\"disabled\")\n\n          for (var i in window.subscriptionIds) {\n            unsubscribeIt(i)\n          }\n\n          if (typeof window.wsTimer != \"undefined\") {\n            clearInterval(window.wsTimer)\n          }\n          window.wsock.close()\n          delete window.wsock\n          delete window.wsockOpened\n          delete window.wsTimer\n        }\n      }\n\n      function getOrderBook (currency) {\n        if (typeof window.wsockOpened != \"undefined\" && window.wsockOpened) {\n          $(\"#disconnect_ws\").html(\"Loading...\")\n          $(\"#disconnect_ws\").addClass(\"disabled\")\n          $(\"#disconnect_ws\").addClass(\"loading\")\n\n          for (var i in window.subscriptionIds) {\n            unsubscribeIt(i)\n          }\n          window.subscriptionIds = []\n\n          orderBookId = new Date().getTime()\n\n          var msg = {\n            jsonrpc: \"2.0\",\n            id: orderBookId,\n            method: \"public/get_book_summary_by_currency\",\n            params: {\n              currency: currency,\n              kind: \"option\"\n            }\n          }\n\n          window.wsock.send(JSON.stringify(msg))\n        }\n      }\n\n      function subscribeIt (instrument) {\n        if (typeof window.wsockOpened != \"undefined\" && window.wsockOpened) {\n          window.subscriptionIds[instrument] = new Date().getTime()\n\n          var msg = {\n            jsonrpc: \"2.0\",\n            id: window.subscriptionIds[instrument],\n            method: \"public/subscribe\",\n            params: {\n              channels: [\n                \"ticker.\" + instrument + \".raw\" // \"deribit_price_index.btc_usd\"\n              ]\n            }\n          }\n\n          window.wsock.send(JSON.stringify(msg))\n        }\n      }\n\n      function unsubscribeIt (instrument) {\n        if (typeof window.wsockOpened != \"undefined\" && window.wsockOpened) {\n          var msg = {\n            jsonrpc: \"2.0\",\n            id: new Date().getTime(),\n            method: \"public/unsubscribe\",\n            params: {\n              channels: [\n                \"ticker.\" + instrument + \".raw\" // \"deribit_price_index.btc_usd\"\n              ]\n            }\n          }\n\n          window.wsock.send(JSON.stringify(msg))\n        }\n      }\n\n      if (typeof $(\"#crypto_options_dashboard\").html() == \"undefined\") {\n        var panel = '<div class=\"ui modal\" id=\"crypto_options_dashboard\">' +\n          '<i class=\"close icon\"></i>' +\n          '<div class=\"content\">' +\n            '<div class=\"ui button\" id=\"get_btc\">BTC</div>' +\n            '<div class=\"ui button\" id=\"get_eth\">ETH</div>' +\n            '<div class=\"ui selection dropdown\" style=\"width:200px\">' +\n              '<input type=\"hidden\" name=\"crypto_option\">' +\n              '<i class=\"dropdown icon\"></i>' +\n              '<div class=\"default text\" id=\"current_crypto_option\">Options</div>' +\n              '<div class=\"menu\" id=\"crypto_options\">' +\n              '</div>' +\n            '</div>' +\n          '</div>' +\n          '<div class=\"content\">' +\n            '<div class=\"description\">' +\n              '<table id=\"crypto_options_orderbook\" class=\"cell-border\" cellspacing=\"0\">' +\n        \t\t\t'</table>' +\n            '</div>' +\n          '</div>' +\n          '<div class=\"actions\">' +\n            '<div class=\"ui button\" id=\"disconnect_ws\">Disconnect</div>' +\n          '</div>' +\n        '</div>'\n\n        $(\"#reserved_zone\").append(panel)\n        window.subscriptionIds = []\n      } else {\n        loaded = true\n      }\n\n      if (!$.fn.dataTable.isDataTable(\"#crypto_options_orderbook\")) {\n  \t\t\t$(\"#crypto_options_orderbook\").DataTable({\n  \t\t\t\tdata: [],\n  \t\t\t\tcolumns: [\n  \t\t\t\t\t{title: \"Bid(C)\",\n              render: function (data, type, row) {\n  \t\t\t\t\t\t\tif (row[5] == 0) {\n                  return '<p style = \"color:#222222\" >' + data + '</p>'\n                } else if (row[5] > 0) {\n  \t\t\t\t\t\t\t\treturn '<p style = \"color:#21BA45\" >' + data + '</p>'\n  \t\t\t\t\t\t\t} else {\n  \t\t\t\t\t\t\t\treturn '<p style = \"color:#DB2828\" >' + data + '</p>'\n  \t\t\t\t\t\t\t}\n  \t\t\t\t\t\t}\n            },\n  \t\t\t\t\t{title: \"Ask(C)\",\n              render: function (data, type, row) {\n                if (row[6] == 0) {\n                  return '<p style = \"color:#222222\" >' + data + '</p>'\n                } else if (row[6] > 0) {\n                  return '<p style = \"color:#21BA45\" >' + data + '</p>'\n                } else {\n                  return '<p style = \"color:#DB2828\" >' + data + '</p>'\n                }\n              }\n            },\n            {title: \"Strike Price\"},\n  \t\t\t\t\t{title: \"Bid(P)\",\n              render: function (data, type, row) {\n                if (row[7] == 0) {\n                  return '<p style = \"color:#222222\" >' + data + '</p>'\n                } else if (row[7] > 0) {\n                  return '<p style = \"color:#21BA45\" >' + data + '</p>'\n                } else {\n                  return '<p style = \"color:#DB2828\" >' + data + '</p>'\n                }\n              }\n            },\n  \t\t\t\t\t{title: \"Ask(P)\",\n              render: function (data, type, row) {\n                if (row[8] == 0) {\n                  return '<p style = \"color:#222222\" >' + data + '</p>'\n                } else if (row[8] > 0) {\n                  return '<p style = \"color:#21BA45\" >' + data + '</p>'\n                } else {\n                  return '<p style = \"color:#DB2828\" >' + data + '</p>'\n                }\n              }\n            },\n            {title: \"Diff(BC)\"},\n            {title: \"Diff(AC)\"},\n            {title: \"Diff(BP)\"},\n            {title: \"Diff(AP)\"}\n  \t\t\t\t],\n          ordering: false,\n          searching: false,\n          bPaginate: false,\n          bLengthChange: false,\n          bFilter: false,\n          bInfo: false,\n          scrollY: '50vh',\n          scrollCollapse: true,\n          paging: false,\n          columnDefs: [\n            {width: \"20%\", targets: 0, className: \"dt-body-right\"},\n            {width: \"20%\", targets: 1, className: \"dt-body-right\"},\n            {width: \"20%\", targets: 2, className: \"dt-body-center\"},\n            {width: \"20%\", targets: 3, className: \"dt-body-right\"},\n            {width: \"20%\", targets: 4, className: \"dt-body-right\"},\n            {width: \"20%\", targets: [0, 1, 2, 3, 4], className: \"dt-head-center\"},\n            {targets: [5, 6, 7, 8], visible: false}\n          ]\n  \t\t\t})\n  \t\t}\n\n      $(\"#get_btc\").on(\"click\", function () {\n        getOrderBook(\"BTC\")\n      })\n      $(\"#get_eth\").on(\"click\", function () {\n        getOrderBook(\"ETH\")\n      })\n      $(\"#disconnect_ws\").on(\"click\", function () {\n        disconnectCryptoOptionsWS()\n      })\n\n      initCryptoOptionsWS()\n\n      $(\"#crypto_options_dashboard\").modal(\"show\")\n\n      if (typeof window.wsTimer != \"undefined\") {\n        clearInterval(window.wsTimer)\n      }\n      window.wsTimer = setInterval(function () {\n        checkHb()\n      }, interval)\n\t\t},\nfunction (context) { // Deinit()\n\t\t},\nfunction (context) { // OnTick()\n\t\t})\n"
  },
  {
    "path": "EA/Plugin-for-Deribit/usage.txt",
    "content": "You can use this EA to get crypto options' streaming quotes. Crypto options are much more complex than Forex or CFD. So, this plugin is for reference only.\n"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_approve.js",
    "content": "registerEA(\n\t\t\"decentralized_exchange_eos_approve\",\n\t\t\"A decentralized exchange plugin to approve a proposal for exchanging digital assets via EOS platform(v1.0)\",\n\t\t[{ // parameters\n\t\t\tname: \"proposalName\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"proposer\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"approver\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar proposalName = getEAParameter(context, \"proposalName\")\n\t\t\tvar proposer = getEAParameter(context, \"proposer\")\n\t\t\tvar approver = getEAParameter(context, \"approver\")\n\n\t\t\tif (proposalName == null || proposalName == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposal name should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (proposer == null || proposer == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposer should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (approver == null || approver == \"\") {\n\t\t\t\tpopupErrorMessage(\"The approver should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await window.eos_api.transact({\n\t\t\t\t\t\tactions: [{\n\t\t\t\t\t\t\taccount: \"eosio.msig\",\n\t\t\t\t\t\t\tname: \"approve\",\n\t\t\t\t\t\t\tauthorization: [{\n\t\t\t\t\t\t\t\tactor: approver,\n\t\t\t\t\t\t\t\tpermission: \"active\"\n\t\t\t\t\t\t\t}],\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tproposer: proposer,\n\t\t\t\t\t\t\t\tproposal_name: proposalName,\n\t\t\t\t\t\t\t\tlevel: {\n\t\t\t\t\t\t\t\t\tactor: approver,\n\t\t\t\t\t\t\t\t\tpermission: \"active\",\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t}, {\n\t\t\t\t\t\tblocksBehind: 3,\n\t\t\t\t\t\texpireSeconds: 30,\n\t\t\t\t\t\tbroadcast: true,\n\t\t\t\t\t\tsign: true\n\t\t\t\t\t})\n\n\t\t\t\t\tpopupMessage(\"Approved!\\n\\n\" + JSON.stringify(result, null, 2))\n\t\t\t\t} catch (e) {\n\t\t\t\t\tpopupErrorMessage(\"Caught exception: \" + e)\n\n\t        if (e instanceof window.eosjs_jsonrpc.RpcError) {\n\t\t\t\t\t\tpopupErrorMessage(JSON.stringify(e.json, null, 2))\n\t\t\t\t\t}\n\t      }\n\t\t\t})()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_cancel.js",
    "content": "registerEA(\n\t\t\"decentralized_exchange_eos_cancel\",\n\t\t\"A decentralized exchange plugin to cancel a proposal for exchanging digital assets via EOS platform(v1.0)\",\n\t\t[{ // parameters\n\t\t\tname: \"proposalName\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"proposer\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"canceler\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar proposalName = getEAParameter(context, \"proposalName\")\n\t\t\tvar proposer = getEAParameter(context, \"proposer\")\n\t\t\tvar canceler = getEAParameter(context, \"canceler\")\n\n\t\t\tif (proposalName == null || proposalName == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposal name should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (proposer == null || proposer == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposer should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (canceler == null || canceler == \"\") {\n\t\t\t\tpopupErrorMessage(\"The canceler should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await window.eos_api.transact({\n\t\t\t\t\t\tactions: [{\n\t\t\t\t\t\t\taccount: \"eosio.msig\",\n\t\t\t\t\t\t\tname: \"cancel\",\n\t\t\t\t\t\t\tauthorization: [{\n\t\t\t\t\t\t\t\tactor: canceler,\n\t\t\t\t\t\t\t\tpermission: \"active\"\n\t\t\t\t\t\t\t}],\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tproposer: proposer,\n\t\t\t\t\t\t\t\tproposal_name: proposalName,\n\t\t\t\t\t\t\t\tcanceler: canceler\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t}, {\n\t\t\t\t\t\tblocksBehind: 3,\n\t\t\t\t\t\texpireSeconds: 30,\n\t\t\t\t\t\tbroadcast: true,\n\t\t\t\t\t\tsign: true\n\t\t\t\t\t})\n\n\t\t\t\t\tpopupMessage(\"Canceled!\\n\\n\" + JSON.stringify(result, null, 2))\n\t\t\t\t} catch (e) {\n\t\t\t\t\tpopupErrorMessage(\"Caught exception: \" + e)\n\n\t        if (e instanceof window.eosjs_jsonrpc.RpcError) {\n\t\t\t\t\t\tpopupErrorMessage(JSON.stringify(e.json, null, 2))\n\t\t\t\t\t}\n\t      }\n\t\t\t})()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_exec.js",
    "content": "registerEA(\n\t\t\"decentralized_exchange_eos_exec\",\n\t\t\"A decentralized exchange plugin to execute a transaction of exchanging digital assets via EOS platform(v1.0)\",\n\t\t[{ // parameters\n\t\t\tname: \"proposalName\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"proposer\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"executor\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar proposalName = getEAParameter(context, \"proposalName\")\n\t\t\tvar proposer = getEAParameter(context, \"proposer\")\n\t\t\tvar executor = getEAParameter(context, \"executor\")\n\n\t\t\tif (proposalName == null || proposalName == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposal name should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (proposer == null || proposer == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposer should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (executor == null || executor == \"\") {\n\t\t\t\tpopupErrorMessage(\"The executor should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await window.eos_api.transact({\n\t\t\t\t\t\tactions: [{\n\t\t\t\t\t\t\taccount: \"eosio.msig\",\n\t\t\t\t\t\t\tname: \"exec\",\n\t\t\t\t\t\t\tauthorization: [{\n\t\t\t\t\t\t\t\tactor: executor,\n\t\t\t\t\t\t\t\tpermission: \"active\"\n\t\t\t\t\t\t\t}],\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tproposer: proposer,\n\t\t\t\t\t\t\t\tproposal_name: proposalName,\n\t\t\t\t\t\t\t\texecuter: executor\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t}, {\n\t\t\t\t\t\tblocksBehind: 3,\n\t\t\t\t\t\texpireSeconds: 30,\n\t\t\t\t\t\tbroadcast: true,\n\t\t\t\t\t\tsign: true\n\t\t\t\t\t})\n\n\t\t\t\t\tpopupMessage(\"Transaction pushed!\\n\\n\" + JSON.stringify(result, null, 2))\n\t\t\t\t} catch (e) {\n\t\t\t\t\tpopupErrorMessage(\"Caught exception: \" + e)\n\n\t        if (e instanceof window.eosjs_jsonrpc.RpcError) {\n\t\t\t\t\t\tpopupErrorMessage(JSON.stringify(e.json, null, 2))\n\t\t\t\t\t}\n\t      }\n\t\t\t})()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_propose.js",
    "content": "registerEA(\n\t\t\"decentralized_exchange_eos_propose\",\n\t\t\"A decentralized exchange plugin to propose for exchanging digital assets via EOS platform(v1.01)\",\n\t\t[{ // parameters\n\t\t\tname: \"proposalName\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"asset\",\n\t\t\tvalue: \"eosio.token\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"proposer\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"exchange\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"escrow\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"amount\",\n\t\t\tvalue: 0,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [0, null]\n\t\t}, {\n\t\t\tname: \"currency\",\n\t\t\tvalue: \"SYS\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"memo\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar proposalName = getEAParameter(context, \"proposalName\")\n\t\t\tvar asset = getEAParameter(context, \"asset\")\n\t\t\tvar proposer = getEAParameter(context, \"proposer\")\n\t\t\tvar exchange = getEAParameter(context, \"exchange\")\n\t\t\tvar escrow = getEAParameter(context, \"escrow\")\n\t\t\tvar amount = getEAParameter(context, \"amount\")\n\t\t\tvar currency = getEAParameter(context, \"currency\")\n\t\t\tvar memo = getEAParameter(context, \"memo\")\n\n\t\t\tif (proposalName == null || proposalName == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposal name should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (proposer == null || proposer == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposer should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (exchange == null || exchange == \"\") {\n\t\t\t\tpopupErrorMessage(\"The exchange should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (escrow == null || escrow == \"\") {\n\t\t\t\tpopupErrorMessage(\"The escrow account should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (amount <= 0) {\n\t\t\t\tpopupErrorMessage(\"The amount should be greater than zero.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (memo == null) {\n\t\t\t\tmemo = \"\"\n\t\t\t}\n\n\t\t\tconst actions = [{\n\t\t\t\taccount: asset,\n\t\t\t\tname: \"transfer\",\n\t\t\t\tauthorization: [{\n\t\t\t\t\tactor: escrow,\n\t\t\t\t\tpermission: \"active\",\n\t\t\t\t}],\n\t\t\t\tdata: {\n\t\t\t\t\tfrom: escrow,\n\t\t\t\t\tto: exchange,\n\t\t\t\t\tquantity: Math.floor(amount) + \".0000 \" + currency,\n\t\t\t\t\tmemo: memo\n\t\t\t\t}\n\t\t\t}];\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t  const serialized_actions = await window.eos_api.serializeActions(actions)\n\n\t\t\t\t\tconst proposeInput = {\n\t\t\t\t\t\tproposer: proposer,\n\t\t\t\t\t\tproposal_name: proposalName,\n\t\t\t\t\t\t// We make the threshold be 1(not 2) to simplify the process, because multi-sig requires that all approvers are online, which is not that realistic.\n\t\t\t\t\t\trequested: [{\n\t\t\t\t\t\t\tactor: exchange,\n\t\t\t\t\t\t\tpermission: \"active\"\n\t\t\t\t\t\t}],\n\t\t\t\t\t\ttrx: {\n\t\t\t\t\t\t\texpiration: new Date(new Date().getTime() + 3600000).toISOString().slice(0,19),\n\t\t\t\t\t\t\tref_block_num: 0,\n\t\t\t\t\t\t\tref_block_prefix: 0,\n\t\t\t\t\t\t\tmax_net_usage_words: 0,\n\t\t\t\t\t\t\tmax_cpu_usage_ms: 0,\n\t\t\t\t\t\t\tdelay_sec: 0,\n\t\t\t\t\t\t\tcontext_free_actions: [],\n\t\t\t\t\t\t\tactions: serialized_actions,\n\t\t\t\t\t\t\ttransaction_extensions: []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst result = await window.eos_api.transact({\n\t\t\t\t\t\tactions: [{\n\t\t\t\t\t\t\taccount: \"eosio.msig\",\n\t\t\t\t\t\t\tname: \"propose\",\n\t\t\t\t\t\t\tauthorization: [{\n\t\t\t\t\t\t\t\tactor: proposer,\n\t\t\t\t\t\t\t\tpermission: \"active\"\n\t\t\t\t\t\t\t}],\n\t\t\t\t\t\t\tdata: proposeInput\n\t\t\t\t\t\t}]\n\t\t\t\t\t}, {\n\t\t\t\t\t\tblocksBehind: 3,\n\t\t\t\t\t\texpireSeconds: 30,\n\t\t\t\t\t\tbroadcast: true,\n\t\t\t\t\t\tsign: true\n\t\t\t\t\t})\n\n\t\t\t\t\tpopupMessage(\"Proposed!\\n\\n\" + JSON.stringify(result, null, 2))\n\t\t\t\t} catch (e) {\n\t\t\t\t\tpopupErrorMessage(\"Caught exception: \" + e)\n\n\t        if (e instanceof window.eosjs_jsonrpc.RpcError) {\n\t\t\t\t\t\tpopupErrorMessage(JSON.stringify(e.json, null, 2))\n\t\t\t\t\t}\n\t      }\n\t\t\t})()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_unapprove.js",
    "content": "registerEA(\n\t\t\"decentralized_exchange_eos_unapprove\",\n\t\t\"A decentralized exchange plugin to unapprove a proposal for exchanging digital assets via EOS platform(v1.0)\",\n\t\t[{ // parameters\n\t\t\tname: \"proposalName\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"proposer\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"actor\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar proposalName = getEAParameter(context, \"proposalName\")\n\t\t\tvar proposer = getEAParameter(context, \"proposer\")\n\t\t\tvar actor = getEAParameter(context, \"actor\")\n\n\t\t\tif (proposalName == null || proposalName == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposal name should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (proposer == null || proposer == \"\") {\n\t\t\t\tpopupErrorMessage(\"The proposer should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (actor == null || actor == \"\") {\n\t\t\t\tpopupErrorMessage(\"The actor should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await window.eos_api.transact({\n\t\t\t\t\t\tactions: [{\n\t\t\t\t\t\t\taccount: \"eosio.msig\",\n\t\t\t\t\t\t\tname: \"unapprove\",\n\t\t\t\t\t\t\tauthorization: [{\n\t\t\t\t\t\t\t\tactor: actor,\n\t\t\t\t\t\t\t\tpermission: \"active\"\n\t\t\t\t\t\t\t}],\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tproposer: proposer,\n\t\t\t\t\t\t\t\tproposal_name: proposalName,\n\t\t\t\t\t\t\t\tlevel: {\n\t\t\t\t\t\t\t\t\tactor: actor,\n\t\t\t\t\t\t\t\t\tpermission: \"active\",\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t}, {\n\t\t\t\t\t\tblocksBehind: 3,\n\t\t\t\t\t\texpireSeconds: 30,\n\t\t\t\t\t\tbroadcast: true,\n\t\t\t\t\t\tsign: true\n\t\t\t\t\t})\n\n\t\t\t\t\tpopupMessage(\"Unapproved!\\n\\n\" + JSON.stringify(result, null, 2))\n\t\t\t\t} catch (e) {\n\t\t\t\t\tpopupErrorMessage(\"Caught exception: \" + e)\n\n\t        if (e instanceof window.eosjs_jsonrpc.RpcError) {\n\t\t\t\t\t\tpopupErrorMessage(JSON.stringify(e.json, null, 2))\n\t\t\t\t\t}\n\t      }\n\t\t\t})()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/payment_gateway_eos.js",
    "content": "registerEA(\n\t\t\"payment_gateway_eos\",\n\t\t\"A payment gateway plugin to make you fund(deposit or withdraw) via EOS platform(v1.03)\",\n\t\t[{ // parameters\n\t\t\tname: \"asset\",\n\t\t\tvalue: \"eosio.token\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"from\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"to\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"amount\",\n\t\t\tvalue: 0,\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\t\trange: [0, null]\n\t\t}, {\n\t\t\tname: \"currency\",\n\t\t\tvalue: \"SYS\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"memo\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar asset = getEAParameter(context, \"asset\")\n\t\t\tvar from = getEAParameter(context, \"from\")\n\t\t\tvar to = getEAParameter(context, \"to\")\n\t\t\tvar amount = getEAParameter(context, \"amount\")\n\t\t\tvar currency = getEAParameter(context, \"currency\")\n\t\t\tvar memo = getEAParameter(context, \"memo\")\n\n\t\t\tif (from == null || from == \"\") {\n\t\t\t\tpopupErrorMessage(\"The sender should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (to == null || to == \"\") {\n\t\t\t\tpopupErrorMessage(\"The recipient should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (amount <= 0) {\n\t\t\t\tpopupErrorMessage(\"The amount should be greater than zero.\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (memo == null) {\n\t\t\t\tmemo = \"\"\n\t\t\t}\n\n\t    (async () => {\n\t      try {\n\t        const result = await window.eos_api.transact({\n\t          actions: [{\n\t              account: asset,\n\t              name: \"transfer\",\n\t              authorization: [{\n\t                  actor: from,\n\t                  permission: \"active\",\n\t              }],\n\t              data: {\n\t                  from: from,\n\t                  to: to,\n\t                  quantity: Math.floor(amount) + \".0000 \" + currency,\n\t                  memo: memo\n\t              }\n\t          }]\n\t        }, {\n\t          blocksBehind: 3,\n\t          expireSeconds: 30\n\t        })\n\n\t        popupMessage(\"Transaction pushed!\\n\\n\" + JSON.stringify(result, null, 2))\n\t      } catch (e) {\n\t\t\t\t\tpopupErrorMessage(\"Caught exception: \" + e)\n\n\t        if (e instanceof window.eosjs_jsonrpc.RpcError) {\n\t\t\t\t\t\tpopupErrorMessage(JSON.stringify(e.json, null, 2))\n\t\t\t\t\t}\n\t      }\n\t    })()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/payment_gateway_eos_lib_loader.js",
    "content": "registerEA(\n\t\t\"payment_gateway_eos_lib_loader\",\n\t\t\"A payment gateway plugin to load EOS libraries(v1.01)\",\n\t\t[{ // parameters\n\t\t\tname: \"privateKey\",\n\t\t\tvalue: \"\",\n\t\t\trequired: false,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"jsonRpcUrl\",\n\t\t\tvalue: \"https://nodes.get-scatter.com\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"jssig\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/eosjs-jssig.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"jsonrpc\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/eosjs-jsonrpc.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"api\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/eosjs-api.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar defaultPrivateKey = getEAParameter(context, \"privateKey\")\n\t\t\tvar jsonRpcUrl = getEAParameter(context, \"jsonRpcUrl\")\n\t\t\tvar jssig = getEAParameter(context, \"jssig\")\n\t\t\tvar jsonrpc = getEAParameter(context, \"jsonrpc\")\n\t\t\tvar api = getEAParameter(context, \"api\")\n\n\t\t\tif (defaultPrivateKey == null || defaultPrivateKey == \"\") {\n\t\t\t\tpopupErrorMessage(\"The private key should not be empty.\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar tags = document.getElementsByTagName(\"script\")\n\t\t\tfor (var i = tags.length - 1; i >= 0; i--) {\n\t\t\t\tif (tags[i] && tags[i].getAttribute(\"src\") != null && (tags[i].getAttribute(\"src\") == jssig || tags[i].getAttribute(\"src\") == jsonrpc || tags[i].getAttribute(\"src\") == api)) {\n\t\t\t\t\ttags[i].parentNode.removeChild(tags[i])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar script1 = document.createElement(\"script\")\n\t    document.body.appendChild(script1)\n\t    script1.onload = function () {\n\t      var script2 = document.createElement(\"script\")\n\t      document.body.appendChild(script2)\n\t      script2.onload = function () {\n\t        var script3 = document.createElement(\"script\")\n\t        document.body.appendChild(script3)\n\t        script3.onload = function () {\n\t\t\t\t\t\twindow.eosjs_jsonrpc = eosjs_jsonrpc\n\t\t\t\t\t\tvar eos_rpc = new eosjs_jsonrpc.JsonRpc(jsonRpcUrl)\n\t\t\t\t\t  var eos_signatureProvider = new eosjs_jssig.JsSignatureProvider([defaultPrivateKey])\n\t\t\t\t\t  window.eos_api = new eosjs_api.Api({rpc: eos_rpc, signatureProvider: eos_signatureProvider})\n\t\t\t\t\t}\n\t        script3.onerror = function () {}\n\t        script3.async = true\n\t        script3.src = jssig\n\t      }\n\t      script2.onerror = function () {}\n\t      script2.async = true\n\t      script2.src = jsonrpc\n\t    }\n\t    script1.onerror = function () {}\n\t    script1.async = true\n\t    script1.src = api\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/payment_gateway_eos_scatter.js",
    "content": "registerEA(\n\t\t\"payment_gateway_eos_scatter\",\n\t\t\"A payment gateway plugin to load the libraries of EOS and Scatter(v1.0)\",\n\t\t[{ // parameters\n\t\t\tname: \"jsonRpcUrl\",\n\t\t\tvalue: \"https://nodes.get-scatter.com\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"chainId\",\n\t\t\tvalue: \"aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"scatterCore\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/scatterjs-core.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"scatterEos\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/scatterjs-plugin-eosjs2.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"jsonrpc\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/eosjs-jsonrpc.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}, {\n\t\t\tname: \"api\",\n\t\t\tvalue: \"https://www.fintechee.com/js/eos/eosjs-api.min.js\",\n\t\t\trequired: true,\n\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\trange: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar jsonRpcUrl = getEAParameter(context, \"jsonRpcUrl\")\n\t\t\tvar chainId = getEAParameter(context, \"chainId\")\n\t\t\tvar scatterCore = getEAParameter(context, \"scatterCore\")\n\t\t\tvar scatterEos = getEAParameter(context, \"scatterEos\")\n\t\t\tvar jsonrpc = getEAParameter(context, \"jsonrpc\")\n\t\t\tvar api = getEAParameter(context, \"api\")\n\n\t\t\tvar tags = document.getElementsByTagName(\"script\")\n\t\t\tfor (var i = tags.length - 1; i >= 0; i--) {\n\t\t\t\tif (tags[i] && tags[i].getAttribute(\"src\") != null &&\n\t\t\t\t\t(tags[i].getAttribute(\"src\") == scatterCore || tags[i].getAttribute(\"src\") == scatterEos || tags[i].getAttribute(\"src\") == jsonrpc || tags[i].getAttribute(\"src\") == api)) {\n\n\t\t\t\t\ttags[i].parentNode.removeChild(tags[i])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar script1 = document.createElement(\"script\")\n\t    document.body.appendChild(script1)\n\t    script1.onload = function () {\n\t      var script2 = document.createElement(\"script\")\n\t      document.body.appendChild(script2)\n\t      script2.onload = function () {\n\t        var script3 = document.createElement(\"script\")\n\t        document.body.appendChild(script3)\n\t        script3.onload = function () {\n\t\t\t\t\t\tvar script4 = document.createElement(\"script\")\n\t\t        document.body.appendChild(script4)\n\t\t        script4.onload = function () {\n\t\t\t\t\t\t\tvar parsedJsonRpcUrl = jsonRpcUrl.split(\"://\")\n\t\t\t\t\t\t\tvar parsedJsonRpcUrl2 = parsedJsonRpcUrl[1].split(\":\")\n\t\t\t\t\t\t\tconst network = ScatterJS.Network.fromJson({\n\t\t\t\t\t\t\t\tblockchain: \"eos\",\n\t\t\t\t\t\t\t\tprotocol: parsedJsonRpcUrl[0],\n\t\t\t\t\t\t\t\thost: parsedJsonRpcUrl2[0],\n\t\t\t\t\t\t\t\tport: parsedJsonRpcUrl2.length == 1 ? 443 : parseInt(parsedJsonRpcUrl2[1]),\n\t\t\t\t\t\t\t\tchainId: chainId\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tScatterJS.plugins(new ScatterEOS())\n\t\t\t\t\t\t\tScatterJS.scatter.connect(\"www.fintechee.com\", {network}).then(function (connected) {\n\t\t\t\t\t\t\t\tif(!connected) {\n\t\t\t\t\t\t\t\t\tpopupErrorMessage(\"Failed to connect to your Scatter APP.\")\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tconst scatter = ScatterJS.scatter\n\n\t\t\t\t\t\t\t\twindow.eosjs_jsonrpc = eosjs_jsonrpc\n\t\t\t\t\t\t\t\tvar eos_rpc = new eosjs_jsonrpc.JsonRpc(jsonRpcUrl)\n\n\t\t\t\t\t\t\t\twindow.eos_api = scatter.eos(network, eosjs_api.Api, {rpc: eos_rpc});\n\n\t\t\t\t\t\t\t\t(async function () {\n\t\t\t\t\t\t\t\t\tif (scatter.identity) {\n\t\t\t\t\t\t\t\t\t\tscatter.logout()\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tawait scatter.login()\n\t\t\t\t\t\t\t\t\twindow.scatter = scatter\n\n\t\t\t\t\t\t\t\t\tpopupMessage(\"Connected to Scatter successfully!\")\n\t\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t\t\twindow.ScatterJS = null\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t        script4.onerror = function () {}\n\t\t        script4.async = true\n\t\t        script4.src = scatterEos\n\t\t\t\t\t}\n\t        script3.onerror = function () {}\n\t        script3.async = true\n\t        script3.src = scatterCore\n\t      }\n\t      script2.onerror = function () {}\n\t      script2.async = true\n\t      script2.src = jsonrpc\n\t    }\n\t    script1.onerror = function () {}\n\t    script1.async = true\n\t    script1.src = api\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t\twindow.scatter.logout()\n\t\t\twindow.scatter = null\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-EOS/usage.txt",
    "content": "This folder contains programs that are used for integrating with the EOS blockchain. These programs provide excellent examples for developers who want to understand how the payment gateway works, and they also demonstrate how to interact with a crypto wallet.\n\nFurthermore, it is possible to extend these plugins to support a different blockchain, if needed.\n\n"
  },
  {
    "path": "EA/Plugin-for-FXCM/README.md",
    "content": "## Developing. Will be coming soon.\n"
  },
  {
    "path": "EA/Plugin-for-MQL/README.md",
    "content": "# Expert-Advisor-Cpp-Compiler\n\nThis is a Nodejs package to help Fintechee's users compile C/C++/MQL source codes(to make the expert advisors runnable on browser). It will be installed on your local PC. So, network is not required to compile your C/C++/MQL source files.\n\nTo know more details about Fintechee, please access our official website: https://www.fintechee.com or our main Github repo: https://github.com/fintechee/Expert-Advisor-Studio\n\n![Fintechee C/C++/MQL compiler](https://github.com/fintechee/Expert-Advisor-Cpp-Compiler/blob/main/cpp.png)\n![Fintechee C/C++/MQL compiler](https://raw.githubusercontent.com/fintechee/Expert-Advisor-Cpp-Compiler/main/cppcompiler.png)\n\n## Prerequisite\nEmscripten is required to compile C/C++/MQL files.\nSo, you need to install it in advance.\nhttps://emscripten.org/docs/getting_started/downloads.html#installation-instructions\n\n## Usage\n1. Installation\n\nPlease access this repo: https://github.com/fintechees/Expert-Advisor-Cpp-Compiler\n\n- Download the git repo, and then extract the zip file.\n- cd the directory\n- npm i\n\n2. Run\n\n- node app.js\n- Access https://www.fintechee.com/web-trader/\n- Click the \"Console\" on the menubar(on the left of the page).\n- Choose \"C/C++\" tab on the panel.\n- Open your C/C++ file and then click \"Generate Indicator\" or \"Generate EA\". C/C++ source codes and a JSON string will be generated. You can modify your original source codes by the generated codes. The generated parts are used to define the meta information of your program, such as the variables and data output and can be helpful to make your original codes compilable.\n- Click \"Compile Indicator\" or \"Compile EA\" after you finish modifying your original codes.\n- Use plugin_for_mql to load the output js(and WebAssembly) that is generated by the \"Compile\" step. The generated JSON string will be used as the parameter of the plugins.\n\nPlease access this page to know more details: https://www.fintechee.com/compatible-with-mql/\n\nThe tool in the page: https://www.fintechee.com/compatible-with-mql/ is an alternative generator to the \"Generate Indicator\" or \"Generate EA\" function.\n\n3. Output files\n\n- The output files(js and WebAssembly) will be stored in the sub-directory: ./static\n- you can access ./static via http://127.0.0.1:3000/js/[your_output_js_file_name] (/js refers to ./static)\n\n## Tutorials\nThe tutorials will be coming soon.\n\n## License\n\nMIT\n"
  },
  {
    "path": "EA/Plugin-for-MQL/mqlea2fintechee.h",
    "content": "#include <stdio.h>\n#include <stdarg.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n#include <map>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <float.h>\n#include <unistd.h>\n#include <iomanip>\n#include <ctime>\n#include <cmath>\n#include <chrono>\n#include <emscripten.h>\nusing namespace std;\n\ntypedef time_t datetime; // Please note that time_t can't handle dates beyond Y2038\ntypedef int color;\n\nenum ENUM_TIMEFRAMES {\n  PERIOD_CURRENT = 0,\n  PERIOD_M1 = 1,\n  PERIOD_M5 = 5,\n  PERIOD_M15 = 15,\n  PERIOD_M30 = 30,\n  PERIOD_H1 = 60,\n  PERIOD_H4 = 240,\n  PERIOD_D1 = 1440,\n  PERIOD_W1 = 10080,\n  PERIOD_MN1 = 43200\n};\nenum ENUM_APPLIED_PRICE {\n  PRICE_CLOSE = 0,\n  PRICE_OPEN = 1,\n  PRICE_HIGH = 2,\n  PRICE_LOW = 3,\n  PRICE_MEDIAN = 4,\n  PRICE_TYPICAL = 5,\n  PRICE_WEIGHTED = 6\n};\nenum ENUM_MA_METHOD {\n  MODE_SMA = 0,\n  MODE_EMA = 1,\n  MODE_SMMA = 2,\n  MODE_LWMA = 3\n};\nenum ENUM_INIT_RETCODE {\n  INIT_SUCCEEDED = 0,\n  INIT_FAILED = -1,\n  INIT_PARAMETERS_INCORRECT = -1\n};\n\nconst int OP_BUY = 0;\nconst int OP_SELL = 1;\nconst int OP_BUYLIMIT = 2;\nconst int OP_SELLLIMIT = 3;\nconst int OP_BUYSTOP = 4;\nconst int OP_SELLSTOP = 5;\n\nconst int MODE_MAIN = 0;\nconst int MODE_SIGNAL = 1;\nconst int MODE_PLUSDI = 1;\nconst int MODE_MINUSDI = 2;\nconst int MODE_UPPER = 1;\nconst int MODE_LOWER = 2;\nconst int MODE_GATORJAW = 1;\nconst int MODE_GATORTEETH = 2;\nconst int MODE_GATORLIPS = 3;\nconst int MODE_TENKANSEN = 1;\nconst int MODE_KIJUNSEN = 2;\nconst int MODE_SENKOUSPANA = 3;\nconst int MODE_SENKOUSPANB = 4;\nconst int MODE_CHIKOUSPAN = 5;\nconst int MODE_OPEN = 0;\nconst int MODE_LOW = 1;\nconst int MODE_HIGH = 2;\nconst int MODE_CLOSE = 3;\nconst int MODE_VOLUME = 4;\nconst int MODE_TIME = 5;\nconst int MODE_BID = 9;\nconst int MODE_ASK = 10;\nconst int MODE_POINT = 11;\nconst int MODE_DIGITS = 12;\nconst int MODE_SPREAD = 13;\nconst int MODE_SWAPLONG = 18;\nconst int MODE_SWAPSHORT = 19;\nconst int MODE_TRADEALLOWED = 22;\nconst int MODE_MINLOT = 23;\nconst int MODE_LOTSTEP = 24;\nconst int MODE_MAXLOT = 25;\n\n// MQL has no these enumerations.\nconst int INDI_OHLC = 0;\nconst int INDI_ADX = 1;\nconst int INDI_ALLIGATOR = 2;\nconst int INDI_BANDS = 3;\nconst int INDI_ENVELOPES = 4;\nconst int INDI_FRACTALS = 5;\nconst int INDI_ICHIMOKU = 6;\nconst int INDI_MACD = 7;\nconst int INDI_RVI = 8;\nconst int INDI_STOCHASTIC = 9;\n\n// MQL may define different values.\nconst int SELECT_BY_POS = 1;\nconst int SELECT_BY_TICKET = 2;\nconst int MODE_TRADES = 1;\nconst int MODE_HISTORY = 2;\n\nconst int MODE_ASCEND = 1;\nconst int MODE_DESCEND = 2;\n\nconst int TIME_DATE = 4;\nconst int TIME_MINUTES = 2;\nconst int TIME_SECONDS = 1;\n\nconst int Green = 0;\nconst int Red = 0;\nconst int Violet = 0;\nconst int White = 0;\nconst int Yellow = 0;\nconst int Blue = 0;\nconst int FireBrick = 0;\nconst int Pink = 0;\nconst int Lime = 0;\n\nconst int EMPTY = -1;\nconst int EMPTY_VALUE = 0x7FFFFFFF;\nconst int CLR_NONE = -1;\nconst int clrNONE = -1;\nconst int CHARTS_MAX = 100;\nconst int INVALID_HANDLE = -1;\nconst int WHOLE_ARRAY = 0;\nconst int WRONG_VALUE = -1;\n\nenum ENUM_OBJECT {\n  OBJ_ARROW_CHECK = 1,\n  OBJ_TREND = 2\n};\n\nenum ENUM_OBJECT_PROPERTY {\n  OBJPROP_TIME1 = 0,\n  OBJPROP_PRICE1 = 1,\n  OBJPROP_TIME2 = 2,\n  OBJPROP_PRICE2 = 3\n};\n\nconst char* convertTimeFrame (int timeframe) {\n  if (PERIOD_M1 == timeframe) {\n    return \"M1\";\n  } else if (PERIOD_M5 == timeframe) {\n    return \"M5\";\n  } else if (PERIOD_M15 == timeframe) {\n    return \"M15\";\n  } else if (PERIOD_M30 == timeframe) {\n    return \"M30\";\n  } else if (PERIOD_H1 == timeframe) {\n    return \"H1\";\n  } else if (PERIOD_H4 == timeframe) {\n    return \"H4\";\n  } else if (PERIOD_D1 == timeframe) {\n    return \"D\";\n  } else if (PERIOD_W1 == timeframe) {\n    return \"W\";\n  } else if (PERIOD_MN1 == timeframe) {\n    return \"M\";\n  } else {\n    return \"0\";\n  }\n}\nconst char* convertMode (int mode, int indi) {\n  if (MODE_SIGNAL == mode && (indi == INDI_MACD || indi == INDI_RVI || indi == INDI_STOCHASTIC)) {\n    return \"signal\";\n  } else if (MODE_PLUSDI == mode && indi == INDI_ADX) {\n    return \"plusDi\";\n  } else if (MODE_MINUSDI == mode && indi == INDI_ADX) {\n    return \"minusDi\";\n  } else if (MODE_UPPER == mode && (indi == INDI_BANDS || indi == INDI_ENVELOPES)) {\n    return \"upper\";\n  } else if (MODE_LOWER == mode && (indi == INDI_BANDS || indi == INDI_ENVELOPES)) {\n    return \"lower\";\n  } else if (MODE_UPPER == mode && indi == INDI_FRACTALS) {\n    return \"fractalsUp\";\n  } else if (MODE_LOWER == mode && indi == INDI_FRACTALS) {\n    return \"fractalsDown\";\n  } else if (MODE_GATORJAW == mode && indi == INDI_ALLIGATOR) {\n    return \"jaws\";\n  } else if (MODE_GATORTEETH == mode && indi == INDI_ALLIGATOR) {\n    return \"teeth\";\n  } else if (MODE_GATORLIPS == mode && indi == INDI_ALLIGATOR) {\n    return \"lips\";\n  } else if (MODE_TENKANSEN == mode && indi == INDI_ICHIMOKU) {\n    return \"tenkan\";\n  } else if (MODE_KIJUNSEN == mode && indi == INDI_ICHIMOKU) {\n    return \"kijun\";\n  } else if (MODE_SENKOUSPANA == mode && indi == INDI_ICHIMOKU) {\n    return \"spana\";\n  } else if (MODE_SENKOUSPANB == mode && indi == INDI_ICHIMOKU) {\n    return \"spanb\";\n  } else if (MODE_CHIKOUSPAN == mode && indi == INDI_ICHIMOKU) {\n    return \"chikou\";\n  } else if (MODE_OPEN == mode && indi == INDI_OHLC) {\n    return \"Open\";\n  } else if (MODE_LOW == mode && indi == INDI_OHLC) {\n    return \"Low\";\n  } else if (MODE_HIGH == mode && indi == INDI_OHLC) {\n    return \"High\";\n  } else if (MODE_CLOSE == mode && indi == INDI_OHLC) {\n    return \"Close\";\n  } else if (MODE_VOLUME == mode && indi == INDI_OHLC) {\n    return \"Volume\";\n  } else if (MODE_TIME == mode && indi == INDI_OHLC) {\n    return \"Time\";\n  } else {\n    return \"main\";\n  }\n}\nconst char* convertMAMethod (int ma_method) {\n  if (MODE_EMA == ma_method) {\n    return \"ema\";\n  } else if (MODE_SMMA == ma_method) {\n    return \"smma\";\n  } else if (MODE_LWMA == ma_method) {\n    return \"lwma\";\n  } else {\n    return \"sma\";\n  }\n}\nconst char* convertCmd (int cmd) {\n  if (OP_BUY == cmd) {\n    return \"BUY\";\n  } else if (OP_SELL == cmd) {\n    return \"SELL\";\n  } else if (OP_BUYLIMIT == cmd) {\n    return \"BUY LIMIT\";\n  } else if (OP_SELLLIMIT == cmd) {\n    return \"SELL LIMIT\";\n  } else if (OP_BUYSTOP == cmd) {\n    return \"BUY STOP\";\n  } else {\n    return \"SELL STOP\";\n  }\n}\n\nvoid (*jPrint) (int, const char*);\nlong (*jChartClose) (int, long);\nlong (*jChartID) (int);\nlong (*jChartOpen) (int, const char*, const char*);\nint (*jChartPeriod) (int, long);\nconst char* (*jChartSymbol) (int, long);\nint (*jPeriod) (int);\nconst char* (*jSymbol) (int);\ndouble (*jAccountBalance) (int);\nconst char* (*jAccountCompany) (int);\nconst char* (*jAccountCurrency) (int);\ndouble (*jAccountEquity) (int);\ndouble (*jAccountFreeMargin) (int);\ndouble (*jAccountMargin) (int);\ndouble (*jAccountProfit) (int);\nint (*jOrdersTotal) (int);\nint (*jOrdersHistoryTotal) (int);\nint (*jOrderSelect) (int, int, int, int);\ndouble (*jOrderOpenPrice) (int);\nint (*jOrderType) (int);\ndouble (*jOrderTakeProfit) (int);\ndouble (*jOrderStopLoss) (int);\ndouble (*jOrderLots) (int);\ndouble (*jOrderProfit) (int);\nconst char* (*jOrderSymbol) (int);\nint (*jOrderTicket) (int);\nint (*jOrderMagicNumber) (int);\ndatetime (*jOrderOpenTime) (int);\nconst char* (*jOrderComment) (int);\ndatetime (*jOrderExpiration) (int);\nvoid (*jOrderPrint) (int);\nint (*jiTimeInit) (int, const char*, const char*);\ndatetime (*jiTime) (int, int, int);\nint (*jiOpenInit) (int, const char*, const char*);\ndouble (*jiOpen) (int, int, int);\nint (*jiHighInit) (int, const char*, const char*);\ndouble (*jiHigh) (int, int, int);\nint (*jiLowInit) (int, const char*, const char*);\ndouble (*jiLow) (int, int, int);\nint (*jiCloseInit) (int, const char*, const char*);\ndouble (*jiClose) (int, int, int);\nint (*jiVolumeInit) (int, const char*, const char*);\nlong (*jiVolume) (int, int, int);\nint (*jiHighest) (int, int, const char*, int, int);\nint (*jiLowest) (int, int, const char*, int, int);\nint (*jiACInit) (int, const char*, const char*);\ndouble (*jiAC) (int, int, int);\nint (*jiADXInit) (int, const char*, const char*, int, int);\ndouble (*jiADX) (int, int, const char*, int);\nint (*jiAlligatorInit) (int, const char*, const char*, int, int, int, int, int, int, const char*, int);\ndouble (*jiAlligator) (int, int, int, int, int, const char*, int);\nint (*jiAOInit) (int, const char*, const char*);\ndouble (*jiAO) (int, int, int);\nint (*jiATRInit) (int, const char*, const char*, int);\ndouble (*jiATR) (int, int, int);\nint (*jiBearsPowerInit) (int, const char*, const char*, int, int);\ndouble (*jiBearsPower) (int, int, int);\nint (*jiBandsInit) (int, const char*, const char*, int, double, int, int);\ndouble (*jiBands) (int, int, int, const char*, int);\ndouble (*jiBandsOnArray) (int, double*, int, int, double, int, const char*, int);\nint (*jiBullsPowerInit) (int, const char*, const char*, int, int);\ndouble (*jiBullsPower) (int, int, int);\nint (*jiCCIInit) (int, const char*, const char*, int, int);\ndouble (*jiCCI) (int, int, int);\ndouble (*jiCCIOnArray) (int, double*, int, int, int);\nint (*jiCustomInit) (int, const char*, const char*, const char*, const char*);\ndouble (*jiCustom) (int, int, const char*, int);\nint (*jiDeMarkerInit) (int, const char*, const char*, int);\ndouble (*jiDeMarker) (int, int, int);\nint (*jiEnvelopesInit) (int, const char*, const char*, int, const char*, int, int, double);\ndouble (*jiEnvelopes) (int, int, int, const char*, int);\ndouble (*jiEnvelopesOnArray) (int, double*, int, int, const char*, int, double, const char*, int);\nint (*jiFractalsInit) (int, const char*, const char*);\ndouble (*jiFractals) (int, int, const char*, int);\nint (*jiIchimokuInit) (int, const char*, const char*, int, int, int);\ndouble (*jiIchimoku) (int, int, int, const char*, int);\nint (*jiMAInit) (int, const char*, const char*, int, int, int, int);\ndouble (*jiMA) (int, int, int, const char*, int);\ndouble (*jiMAOnArray) (int, double*, int, int, int, const char*, int);\nint (*jiMACDInit) (int, const char*, const char*, int, int, int, int);\ndouble (*jiMACD) (int, int, const char*, int);\nint (*jiMFIInit) (int, const char*, const char*, int);\ndouble (*jiMFI) (int, int, int);\nint (*jiMomentumInit) (int, const char*, const char*, int, int);\ndouble (*jiMomentum) (int, int, int);\ndouble (*jiMomentumOnArray) (int, double*, int, int, int);\nint (*jiRSIInit) (int, const char*, const char*, int, int);\ndouble (*jiRSI) (int, int, int);\ndouble (*jiRSIOnArray) (int, double*, int, int, int);\nint (*jiRVIInit) (int, const char*, const char*, int);\ndouble (*jiRVI) (int, int, const char*, int);\nint (*jiSARInit) (int, const char*, const char*, double, double);\ndouble (*jiSAR) (int, int, int);\nint (*jiStochasticInit) (int, const char*, const char*, int, int, int, const char*);\ndouble (*jiStochastic) (int, int, const char*, int);\nint (*jiWPRInit) (int, const char*, const char*, int);\ndouble (*jiWPR) (int, int, int);\nint (*jObjectCreate) (int, long, const char*, int, datetime, double, datetime, double);\nint (*jObjectDelete) (int, const char*);\ndouble (*jObjectGet) (int, const char*, int);\nint (*jObjectSet) (int, const char*, int, double);\nint (*jIsTesting) ();\ndouble (*jMarketInfo) (int, const char*, int);\nint (*jCreateNeuralNetwork) (int, const char*, const char*);\ndouble (*jActivateNeuralNetwork) (int, const char*, double*, int);\n\n// Deprecated\nEM_JS(bool, jSCompareL, (int uid, const char* str, long l), {\n  try {\n    var obj = window.mqlEAsBuffer[uid + \"\"];\n    var UTF8ToString = window.mqlEAs[obj.name].module.UTF8ToString;\n    var s = UTF8ToString(str);\n    return parseInt(s) >= l;\n  } catch (e) {\n    return false;\n  }\n});\n\nEM_JS(int, jOrderSend, (int uid, const char* symbol, const char* cmd, double volume, double price, int slippage, double stoploss, double takeprofit, const char* comment, int magic, datetime expiration, int arrow_color), {\n   return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      var UTF8ToString = window.mqlEAs[obj.name].module.UTF8ToString;\n\n      var symbolName = UTF8ToString(symbol);\n      const orderType = UTF8ToString(cmd);\n      const cmmnt = UTF8ToString(comment);\n      if (symbolName == \"\") {\n        symbolName = obj.symbolName;\n      }\n      obj.lock = true;\n      document.addEventListener(\"customevent\", function (e) {\n        window.mqlEAsBuffer[uid + \"\"].lock = false;\n        wakeUp(parseInt(e.detail));\n\t\t\t}, {once: true});\n      sendOrder(obj.brokerName, obj.accountId, symbolName, orderType, price, slippage, volume, takeprofit, stoploss, cmmnt, magic, expiration);\n    } catch (e) {\n      printErrorMessage(e.message);\n      var event = new CustomEvent(\"customevent\", {detail: -1});\n  \t\tdocument.dispatchEvent(event);\n    }\n  });\n});\n\nEM_JS(int, jOrderModify, (int uid, int ticket, double price, double stoploss, double takeprofit, datetime expiration, int arrow_color), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      obj.lock = true;\n\n      var orderOrTrade = getOrderOrTradeById(obj.context, ticket + \"\");\n      var type = orderOrTrade.type;\n\n      if (type == \"P\") {\n        document.addEventListener(\"customevent\", function (e) {\n          window.mqlEAsBuffer[uid + \"\"].lock = false;\n          if (e.detail != null) {\n            wakeUp(1);\n          } else {\n            wakeUp(0);\n          }\n  \t\t\t}, {once: true});\n        modifyOrder(obj.brokerName, obj.accountId, ticket + \"\", getSymbolName(orderOrTrade), getOrderType(orderOrTrade), price, 0, getLots(orderOrTrade),\n          takeprofit, stoploss, getComment(orderOrTrade), getMagicNumber(orderOrTrade), getExpiration(orderOrTrade));\n      } else if (type == \"T\") {\n        document.addEventListener(\"customevent\", function (e) {\n          window.mqlEAsBuffer[uid + \"\"].lock = false;\n          if (e.detail != null) {\n            wakeUp(1);\n          } else {\n            wakeUp(0);\n          }\n  \t\t\t}, {once: true});\n        modifyTpSlOfTrade(obj.brokerName, obj.accountId, ticket + \"\", takeprofit, stoploss);\n      } else {\n        throw new Error(\"Failed to modify the order.\");\n      }\n    } catch (e) {\n      printErrorMessage(e.message);\n      var event = new CustomEvent(\"customevent\", {detail: null});\n  \t\tdocument.dispatchEvent(event);\n    }\n  });\n});\n\nEM_JS(int, jOrderClose, (int uid, int ticket, double lots, double price, int slippage, int arrow_color), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      obj.lock = true;\n      document.addEventListener(\"customevent\", function (e) {\n        window.mqlEAsBuffer[uid + \"\"].lock = false;\n        if (e.detail != null) {\n          wakeUp(1);\n        } else {\n          wakeUp(0);\n        }\n\t\t\t}, {once: true});\n      closeTrade(obj.brokerName, obj.accountId, ticket + \"\", price, slippage);\n    } catch (e) {\n      printErrorMessage(e.message);\n      var event = new CustomEvent(\"customevent\", {detail: null});\n  \t\tdocument.dispatchEvent(event);\n    }\n  });\n});\n\nEM_JS(int, jOrderDelete, (int uid, int ticket, int arrow_color), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      obj.lock = true;\n      document.addEventListener(\"customevent\", function (e) {\n        window.mqlEAsBuffer[uid + \"\"].lock = false;\n        if (e.detail != null) {\n          wakeUp(1);\n        } else {\n          wakeUp(0);\n        }\n\t\t\t}, {once: true});\n      cancelOrder(obj.brokerName, obj.accountId, ticket + \"\");\n    } catch (e) {\n      printErrorMessage(e.message);\n      var event = new CustomEvent(\"customevent\", {detail: null});\n  \t\tdocument.dispatchEvent(event);\n    }\n  });\n});\n\nEM_JS(bool, jVeriSig, (int uid, const char* fintechee_data, const char* fintechee_signature, const char* fintechee_public_key), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    if (typeof veriSig == \"undefined\") {\n      wakeUp(false);\n      return;\n    }\n\n    var obj = window.mqlEAsBuffer[uid + \"\"];\n    var UTF8ToString = window.mqlEAs[obj.name].module.UTF8ToString;\n\n    const data = UTF8ToString(fintechee_data);\n    const signature = UTF8ToString(fintechee_signature);\n    const public_key = UTF8ToString(fintechee_public_key);\n\n    veriSig(true, data, signature, public_key)\n    .then(function (res) {\n      if (res) {\n        wakeUp(res);\n      } else {\n        printErrorMessage(\"Signature verification failed.\");\n        wakeUp(res);\n      }\n    })\n    .catch(function (e) {\n      printErrorMessage(e.message);\n      wakeUp(false);\n    })\n  });\n});\n\nEM_JS(void, jPreventCleanUp, (int uid), {\n  try {\n    window.mqlEAsBuffer[uid + \"\"].bPreventCleanUp = true;\n  } catch (e) {\n    printErrorMessage(e.message);\n  }\n});\n\nEM_JS(bool, jBuildCNN, (int uid, const char* name, int inputNum, int hiddenNum), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);\n      if (nnName == \"\") {\n        printErrorMessage(\"Please enter the name of your CNN model.\");\n        wakeUp(false);\n        return;\n      }\n\n      if (typeof window.buildCnn == \"undefined\") {\n        printErrorMessage(\"Please run the plugin to load your CNN model first.\");\n        wakeUp(false);\n      } else {\n        window.buildCnn(inputNum, inputNum, hiddenNum, inputNum).then(function (tfModel) {\n          obj.neuralNetworks[nnName] = {\n            cnn: tfModel\n          };\n          wakeUp(true);\n        })\n        .catch(function (e) {\n          printErrorMessage(e.message);\n          wakeUp(false);\n        })\n      }\n    } catch (e) {\n      printErrorMessage(e.message);\n      wakeUp(false);\n    }\n  });\n});\n\nEM_JS(bool, jTrainCNN, (int uid, const char* name, double* dataInput, double* dataOutput, long trainingSetNum, int inputNum, long iterations, int batchSize, bool bMonitor), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);\n      if (nnName == \"\") {\n        printErrorMessage(\"Please enter the name of your CNN model.\");\n        wakeUp(false);\n        return;\n      }\n\n      if (typeof obj.neuralNetworks[nnName] != \"undefined\" && typeof obj.neuralNetworks[nnName].cnn != \"undefined\") {\n        if (typeof window.trainCnn == \"undefined\") {\n          printErrorMessage(\"Please run the plugin to load your CNN model first.\");\n          wakeUp(false);\n        } else {\n          var nByteDouble = 8;\n          var trainingSetI = new Array(trainingSetNum * inputNum);\n          for (var i = 0; i < trainingSetI.length; i++) {\n            trainingSetI[i] = window.mqlEAs[obj.name].module.getValue(dataInput + i * nByteDouble, \"double\");\n          }\n          var trainingSetO = new Array(trainingSetNum * 2);\n          for (var i = 0; i < trainingSetO.length; i++) {\n            trainingSetO[i] = window.mqlEAs[obj.name].module.getValue(dataOutput + i * nByteDouble, \"double\");\n          }\n\n          var tensorSet = {\n            input: window.tf.tensor3d(trainingSetI, [trainingSetNum, inputNum, 1]),\n            output: window.tf.tensor2d(trainingSetO, [trainingSetNum, 2])\n          };\n\n          printMessage(\"Start training!\");\n\n          window.trainCnn(obj.neuralNetworks[nnName].cnn, tensorSet, iterations, batchSize, bMonitor).then(function () {\n            printMessage(\"Training is done!\");\n            wakeUp(true);\n          })\n          .catch(function (e) {\n            printErrorMessage(e.message);\n            wakeUp(false);\n          })\n        }\n      } else {\n        printErrorMessage(\"The specific CNN model doesn't exist.\");\n        wakeUp(false);\n      }\n    } catch (e) {\n      printErrorMessage(e.message);\n      wakeUp(false);\n    }\n  });\n});\n\nEM_JS(double, jRunCNN, (int uid, const char* name, double* dataInput, int inputNum), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);\n      if (nnName == \"\") {\n        printErrorMessage(\"Please enter the name of your CNN model.\");\n        wakeUp(-1);\n        return;\n      }\n\n      if (typeof obj.neuralNetworks[nnName] != \"undefined\" && typeof obj.neuralNetworks[nnName].cnn != \"undefined\") {\n        if (typeof window.tf == \"undefined\") {\n          printErrorMessage(\"Please run the plugin to load your CNN model first.\");\n          wakeUp(-1);\n        } else {\n          var nByteDouble = 8;\n          var trainingSetI = new Array(inputNum);\n          for (var i = 0; i < trainingSetI.length; i++) {\n            trainingSetI[i] = window.mqlEAs[obj.name].module.getValue(dataInput + i * nByteDouble, \"double\");\n          }\n\n          wakeUp(window.runCnn(obj.neuralNetworks[nnName].cnn, trainingSetI, inputNum));\n        }\n      } else {\n        printErrorMessage(\"The specific CNN model doesn't exist.\");\n        wakeUp(-1);\n      }\n    } catch (e) {\n      printErrorMessage(e.message);\n      wakeUp(-1);\n    }\n  });\n});\n\nEM_JS(bool, jSaveCNN, (int uid, const char* name), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);\n      if (nnName == \"\") {\n        printErrorMessage(\"Please enter the name of your CNN model.\");\n        wakeUp(false);\n        return;\n      }\n\n      if (typeof obj.neuralNetworks[nnName] != \"undefined\" && typeof obj.neuralNetworks[nnName].cnn != \"undefined\") {\n        if (typeof window.tf == \"undefined\") {\n          printErrorMessage(\"Please run the plugin to load your CNN model first.\");\n          wakeUp(false);\n        } else {\n          window.saveCnn(obj.neuralNetworks[nnName].cnn, nnName).then(function () {\n            wakeUp(true);\n          })\n          .catch(function (msg) {\n            wakeUp(false);\n          })\n        }\n      } else {\n        printErrorMessage(\"The specific CNN model doesn't exist.\");\n        wakeUp(false);\n      }\n    } catch (e) {\n      printErrorMessage(e.message);\n      wakeUp(false);\n    }\n  });\n});\n\nEM_JS(bool, jLoadCNN, (int uid, const char* name), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    try {\n      var obj = window.mqlEAsBuffer[uid + \"\"];\n      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);\n      if (nnName == \"\") {\n        printErrorMessage(\"Please enter the name of your CNN model.\");\n        wakeUp(false);\n        return;\n      }\n\n      if (typeof window.tf == \"undefined\") {\n        printErrorMessage(\"Please run the plugin to load your CNN model first.\");\n        wakeUp(false);\n      } else {\n        window.loadCnn(nnName).then(function (tfModel) {\n          if (typeof tfModel != \"undefined\") {\n            obj.neuralNetworks[nnName] = {\n              cnn: tfModel\n            };\n            wakeUp(true);\n          } else {\n            printErrorMessage(\"The specific CNN model doesn't exist.\");\n            wakeUp(false);\n          }\n        })\n        .catch(function (msg) {\n          wakeUp(false);\n        })\n      }\n    } catch (e) {\n      printErrorMessage(e.message);\n      wakeUp(false);\n    }\n  });\n});\n\nvoid Sleep (int milliseconds) {\n  sleep(milliseconds / 1000);\n}\nint GetLastError () {\n  return 0;\n}\nstring ErrorDescription (int code) {\n  return \"\";\n}\nbool IsStopped () {\n  return false;\n}\nbool IsTradeAllowed () {\n  return true;\n}\nbool IsTradeAllowed (const string symbol, datetime tested_time) {\n  return true;\n}\nbool RefreshRates () {\n  return true;\n}\ndouble MathAbs (double val) {\n  return abs(val);\n}\ndouble MathArccos (double val) {\n  return acos(val);\n}\ndouble MathArcsin (double val) {\n  return asin(val);\n}\ndouble MathArctan (double val) {\n  return atan(val);\n}\ndouble MathCeil (double val) {\n  return ceil(val);\n}\ndouble MathCos (double val) {\n  return cos(val);\n}\ndouble MathExp (double val) {\n  return exp(val);\n}\ndouble MathFloor (double val) {\n  return floor(val);\n}\ndouble MathLog (double val) {\n  return log(val);\n}\ndouble MathLog10 (double val) {\n  return log10(val);\n}\ndouble MathMax (double a, double b) {\n  return max(a, b);\n}\ndouble MathMin (double a, double b) {\n  return min(a, b);\n}\ndouble MathMod (double a, double b) {\n  return fmod(a, b);\n}\ndouble MathPow (double base, double exponent) {\n  return pow(base, exponent);\n}\nint MathRand () {\n  return rand();\n}\ndouble MathRound (double val) {\n  return round(val);\n}\ndouble MathSin (double val) {\n  return sin(val);\n}\ndouble MathSqrt (double val) {\n  return sqrt(val);\n}\nvoid MathSrand (int seed) {\n  srand(seed);\n}\ndouble MathTan (double val) {\n  return tan(val);\n}\nint StringLen (const string string_value) {\n  return string_value.length();\n}\nint StringReplace (string str, const string find, const string replacement) {\n  if(find.empty()) {\n    return 0;\n  }\n  size_t start_pos = 0;\n  int count = 0;\n  while((start_pos = str.find(find, start_pos)) != string::npos) {\n    str.replace(start_pos, find.length(), replacement);\n    start_pos += replacement.length();\n    count++;\n  }\n  return count;\n}\nstring StringSubstr (const string string_value, int start_pos, int length) {\n  if (start_pos < 0 || start_pos >= string_value.length() || length <= 0 || start_pos + length > string_value.length()) {\n    return \"\";\n  }\n  return string_value.substr(start_pos, length);\n}\nbool StringToLower (string string_var) {\n  transform(string_var.begin(), string_var.end(), string_var.begin(), [](unsigned char c){ return tolower(c);});\n  return true;\n}\nbool StringToUpper (string string_var) {\n  transform(string_var.begin(), string_var.end(), string_var.begin(), [](unsigned char c){ return toupper(c);});\n  return true;\n}\nstring StringTrimLeft(const string text) {\n  string s = text;\n  s.erase(s.begin(), find_if(s.begin(), s.end(), [](int c) {return !isspace(c);}));\n  return s;\n}\nstring StringTrimRight(const string text) {\n  string s = text;\n  s.erase(find_if(s.rbegin(), s.rend(), [](int c) {return !isspace(c);}).base(), s.end());\n  return s;\n}\nstring DoubleToString (double value, int dijits) {\n  stringstream stream;\n  stream << fixed << setprecision(dijits) << value;\n  return stream.str();\n}\nstring DoubleToString (double value) {\n  return DoubleToString(value, 8);\n}\nstring DoubleToStr (double value, int dijits) {\n  return DoubleToString(value, dijits);\n}\nstring DoubleToStr (double value) {\n  return DoubleToString(value, 8);\n}\nstring IntegerToString (long number, int str_len, unsigned short fill_symbol) {\n  return to_string(number);\n}\nstring ShortToString (unsigned short symbol_code) {\n  return to_string(symbol_code);\n}\nstring TimeToString (datetime value, int mode) {\n  time_t tim = value;\n  tm * ptm = localtime(&tim);\n  if (mode == 7 || mode == 5) {\n    char buffer[20];\n    strftime(buffer, 20, \"%Y.%m.%d %H:%M:%S\", ptm);\n    return string(buffer);\n  } else if (mode == 4) {\n    char buffer[11];\n    strftime(buffer, 11, \"%Y.%m.%d\", ptm);\n    return string(buffer);\n  } else if (mode == 3 || mode == 1) {\n    char buffer[9];\n    strftime(buffer, 9, \"%H:%M:%S\", ptm);\n    return string(buffer);\n  } else if (mode == 2) {\n    char buffer[6];\n    strftime(buffer, 6, \"%H:%M\", ptm);\n    return string(buffer);\n  } else {\n    char buffer[17];\n    strftime(buffer, 17, \"%Y.%m.%d %H:%M\", ptm);\n    return string(buffer);\n  }\n}\nstring TimeToString (datetime value) {\n  return TimeToString(value, 5);\n}\nstring TimeToStr (datetime value, int mode) {\n  return TimeToString(value, mode);\n}\nstring TimeToStr (datetime value) {\n  return TimeToString(value, 5);\n}\ndouble NormalizeDouble (double value, int digits) {\n  return (round(value * pow(10, digits))) / pow(10, digits);\n}\ndouble StringToDouble (const string value) {\n  return stod(value);\n}\ndouble StrToDouble (const string value) {\n  return StringToDouble(value);\n}\nint StringToInteger (const string value) {\n  return stoi(value);\n}\nint StrToInteger (const string value) {\n  return StringToInteger(value);\n}\ndatetime StringToTime (const string value) {\n  struct tm tm;\n  if (value.length() == 19) {\n    strptime(value.c_str(), \"%Y.%m.%d %H:%M:%S\", &tm);\n    return mktime(&tm);\n  } else if (value.length() == 10) {\n    strptime(value.c_str(), \"%Y.%m.%d\", &tm);\n    return mktime(&tm);\n  } else if (value.length() == 16) {\n    strptime(value.c_str(), \"%Y.%m.%d %H:%M\", &tm);\n    return mktime(&tm);\n  } else {\n    return 0;\n  }\n}\ndatetime StrToTime (const string value) {\n  return StringToTime(value);\n}\nint StringCompare (const string str1, const string str2, bool case_sensitive = true) {\n  if (case_sensitive) {\n    return strcmp(str1.c_str(), str2.c_str());\n  } else {\n    return strcasecmp(str1.c_str(), str2.c_str());\n  }\n}\ndatetime TimeCurrent () {\n  return chrono::system_clock::to_time_t(chrono::system_clock::now());\n}\ndatetime TimeGMT () {\n  return TimeCurrent();\n}\ndatetime CurTime () {\n  return TimeCurrent();\n}\nint Day () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mday;\n}\nint DayOfWeek () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_wday;\n}\nint DayOfYear () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_yday + 1;\n}\nint Hour () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_hour;\n}\nint Minute () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_min;\n}\nint Month () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mon + 1;\n}\nint Seconds () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_sec;\n}\nint TimeDay (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mday;\n}\nint TimeDayOfWeek (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_wday;\n}\nint TimeDayOfYear (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_yday + 1;\n}\nint TimeHour (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_hour;\n}\nint TimeMinute (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_min;\n}\nint TimeMonth (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mon + 1;\n}\nint TimeSeconds (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_sec;\n}\nint TimeYear (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_year + 1900;\n}\nint Year () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_year + 1900;\n}\nint ArrayCopy (char* dst_array, const char* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (char)));\n    return count;\n  }\n}\nint ArrayCopy (short* dst_array, const short* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (short)));\n    return count;\n  }\n}\nint ArrayCopy (int* dst_array, const int* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (int)));\n    return count;\n  }\n}\nint ArrayCopy (long* dst_array, const long* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (long)));\n    return count;\n  }\n}\nint ArrayCopy (float* dst_array, const float* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (float)));\n    return count;\n  }\n}\nint ArrayCopy (double* dst_array, const double* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (double)));\n    return count;\n  }\n}\nint ArrayCopy (bool* dst_array, const bool* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (bool)));\n    return count;\n  }\n}\nvoid ArrayFree (void* array) {\n  free(array);\n}\nvoid ArrayInitialize (char* array, char value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (short* array, short value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (int* array, int value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (long* array, long value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (float* array, float value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (double* array, double value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (bool* array, bool value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayFill (char* array, int start, int count, char value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (short* array, int start, int count, short value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (int* array, int start, int count, int value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (long* array, int start, int count, long value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (float* array, int start, int count, float value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (double* array, int start, int count, double value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (bool* array, int start, int count, bool value) {\n  ArrayInitialize(array, value, count);\n}\nint ArrayMaximum (const short* array, int count, int start) {\n  if (count > 0) {\n    short high = SHRT_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const int* array, int count, int start) {\n  if (count > 0) {\n    int high = INT_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const long* array, int count, int start) {\n  if (count > 0) {\n    long high = LONG_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const float* array, int count, int start) {\n  if (count > 0) {\n    float high = FLT_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const double* array, int count, int start) {\n  if (count > 0) {\n    double high = DBL_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const short* array, int count, int start) {\n  if (count > 0) {\n    short low = SHRT_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const int* array, int count, int start) {\n  if (count > 0) {\n    int low = INT_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const long* array, int count, int start) {\n  if (count > 0) {\n    long low = LONG_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const float* array, int count, int start) {\n  if (count > 0) {\n    float low = FLT_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const double* array, int count, int start) {\n  if (count > 0) {\n    double low = DBL_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (char** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (char));\n    char* newArr = (char*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (short** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (short));\n    short* newArr = (short*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (int** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (int));\n    int* newArr = (int*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (long** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (long));\n    long* newArr = (long*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (float** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (float));\n    float* newArr = (float*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (double** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (double));\n    double* newArr = (double*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (bool** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (bool));\n    bool* newArr = (bool*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (char** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (short** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (int** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (long** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (float** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (double** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (bool** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nbool ArraySort (char* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<char>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (short* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<short>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (int* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<int>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (long* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<long>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (float* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<float>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (double* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<double>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nint ArrayBsearch (const char* array, char value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const short* array, short value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const int* array, int value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const long* array, long value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const float* array, float value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const double* array, double value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\n\nstruct Parameter {\n  char paramType;\n  int paramInt;\n  double paramDouble;\n  bool paramBool;\n  string paramString;\n};\n\nstruct GlobalVar {\n  datetime time;\n  double value;\n};\n\nstruct ParamHandleItem {\n  bool bInit = true;\n  vector<struct Parameter> paramList;\n  map<string, int> handleList;\n  map<string, struct GlobalVar> globalVarList;\n};\n\nmap<int, struct ParamHandleItem> paramHandleList;\nint iFintecheeUID;\nint Bars;\ndouble Ask;\ndouble Bid;\ndouble Point;\nint Digits;\n\nint OnInit (void);\n\nvoid OnDeinit (const int);\n\nvoid OnTick (void);\n\nvoid setParam (int uid, const struct Parameter & parameter) {\n  if (paramHandleList.find(uid) != paramHandleList.end()) {\n    paramHandleList[uid].paramList.push_back(parameter);\n  } else {\n    struct ParamHandleItem item;\n    item.paramList.push_back(parameter);\n    paramHandleList[uid] = item;\n  }\n}\n\ndatetime setGlobalVar (int uid, const string name, double value) {\n  struct GlobalVar globalVar;\n  globalVar.time = TimeCurrent();\n\n  if (paramHandleList.find(uid) != paramHandleList.end()) {\n    datetime time = paramHandleList[uid].globalVarList.count(name) > 0 ? paramHandleList[uid].globalVarList[name].time : globalVar.time;\n    paramHandleList[uid].globalVarList[name] = globalVar;\n    return time;\n  } else {\n    struct ParamHandleItem item;\n    item.globalVarList[name] = globalVar;\n    paramHandleList[uid] = item;\n    return globalVar.time;\n  }\n}\n\nbool checkGlobalVar (int uid, const string name) {\n  if (paramHandleList.find(uid) != paramHandleList.end()) {\n    return paramHandleList[uid].globalVarList.count(name) > 0;\n  } else {\n    return false;\n  }\n}\n\ndouble getGlobalVar (int uid, const string name) {\n  if (paramHandleList.find(uid) != paramHandleList.end()) {\n    return paramHandleList[uid].globalVarList.count(name) > 0 ? paramHandleList[uid].globalVarList[name].value : 0;\n  } else {\n    return 0;\n  }\n}\n\nbool delGlobalVar (int uid, const string name) {\n  if (paramHandleList.find(uid) != paramHandleList.end()) {\n    if (paramHandleList[uid].globalVarList.count(name) > 0) {\n      paramHandleList[uid].globalVarList.erase(name);\n      return true;\n    } else {\n      return false;\n    }\n  } else {\n    return false;\n  }\n}\n\nextern \"C\" {\n\nEMSCRIPTEN_KEEPALIVE\nvoid setParamInt (int uid, int param) {\n  struct Parameter parameter;\n  parameter.paramType = 'i';\n  parameter.paramInt = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setParamDouble (int uid, double param) {\n  struct Parameter parameter;\n  parameter.paramType = 'd';\n  parameter.paramDouble = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setParamBool (int uid, bool param) {\n  struct Parameter parameter;\n  parameter.paramType = 'b';\n  parameter.paramBool = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setParamString (int uid, const char* param) {\n  struct Parameter parameter;\n  parameter.paramType = 's';\n  parameter.paramString = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjPrint (void (*f) (int, const char*)) {\n  jPrint = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartClose (long (*f) (int, long)) {\n  jChartClose = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartID (long (*f) (int)) {\n  jChartID = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartOpen (long (*f) (int, const char*, const char*)) {\n  jChartOpen = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartPeriod (int (*f) (int, long)) {\n  jChartPeriod = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartSymbol (const char* (*f) (int, long)) {\n  jChartSymbol = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjPeriod (int (*f) (int)) {\n  jPeriod = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjSymbol (const char* (*f) (int)) {\n  jSymbol = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountBalance (double (*f) (int)) {\n  jAccountBalance = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountCompany (const char* (*f) (int)) {\n  jAccountCompany = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountCurrency (const char* (*f) (int)) {\n  jAccountCurrency = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountEquity (double (*f) (int)) {\n  jAccountEquity = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountFreeMargin (double (*f) (int)) {\n  jAccountFreeMargin = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountMargin (double (*f) (int)) {\n  jAccountMargin = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjAccountProfit (double (*f) (int)) {\n  jAccountProfit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrdersTotal (int (*f) (int)) {\n  jOrdersTotal = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrdersHistoryTotal (int (*f) (int)) {\n  jOrdersHistoryTotal = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderSelect (int (*f) (int, int, int, int)) {\n  jOrderSelect = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderOpenPrice (double (*f) (int)) {\n  jOrderOpenPrice = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderType (int (*f) (int)) {\n  jOrderType = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderTakeProfit (double (*f) (int)) {\n  jOrderTakeProfit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderStopLoss (double (*f) (int)) {\n  jOrderStopLoss = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderLots (double (*f) (int)) {\n  jOrderLots = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderProfit (double (*f) (int)) {\n  jOrderProfit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderSymbol (const char* (*f) (int)) {\n  jOrderSymbol = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderTicket (int (*f) (int)) {\n  jOrderTicket = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderMagicNumber (int (*f) (int)) {\n  jOrderMagicNumber = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderOpenTime (datetime (*f) (int)) {\n  jOrderOpenTime = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderComment (const char* (*f) (int)) {\n  jOrderComment = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderExpiration (datetime (*f) (int)) {\n  jOrderExpiration = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjOrderPrint (void (*f) (int)) {\n  jOrderPrint = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiTimeInit (int (*f) (int, const char*, const char*)) {\n  jiTimeInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiTime (datetime (*f) (int, int, int)) {\n  jiTime = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiOpenInit (int (*f) (int, const char*, const char*)) {\n  jiOpenInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiOpen (double (*f) (int, int, int)) {\n  jiOpen = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiHighInit (int (*f) (int, const char*, const char*)) {\n  jiHighInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiHigh (double (*f) (int, int, int)) {\n  jiHigh = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiLowInit (int (*f) (int, const char*, const char*)) {\n  jiLowInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiLow (double (*f) (int, int, int)) {\n  jiLow = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCloseInit (int (*f) (int, const char*, const char*)) {\n  jiCloseInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiClose (double (*f) (int, int, int)) {\n  jiClose = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiVolumeInit (int (*f) (int, const char*, const char*)) {\n  jiVolumeInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiVolume (long (*f) (int, int, int)) {\n  jiVolume = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiHighest (int (*f) (int, int, const char*, int, int)) {\n  jiHighest = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiLowest (int (*f) (int, int, const char*, int, int)) {\n  jiLowest = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiACInit (int (*f) (int, const char*, const char*)) {\n  jiACInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAC (double (*f) (int, int, int)) {\n  jiAC = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiADXInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiADXInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiADX (double (*f) (int, int, const char*, int)) {\n  jiADX = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAlligatorInit (int (*f) (int, const char*, const char*, int, int, int, int, int, int, const char*, int)) {\n  jiAlligatorInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAlligator (double (*f) (int, int, int, int, int, const char*, int)) {\n  jiAlligator = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAOInit (int (*f) (int, const char*, const char*)) {\n  jiAOInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAO (double (*f) (int, int, int)) {\n  jiAO = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiATRInit (int (*f) (int, const char*, const char*, int)) {\n  jiATRInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiATR (double (*f) (int, int, int)) {\n  jiATR = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBearsPowerInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiBearsPowerInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBearsPower (double (*f) (int, int, int)) {\n  jiBearsPower = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBandsInit (int (*f) (int, const char*, const char*, int, double, int, int)) {\n  jiBandsInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBands (double (*f) (int, int, int, const char*, int)) {\n  jiBands = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBandsOnArray (double (*f) (int, double*, int, int, double, int, const char*, int)) {\n  jiBandsOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBullsPowerInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiBullsPowerInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBullsPower (double (*f) (int, int, int)) {\n  jiBullsPower = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCCIInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiCCIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCCI (double (*f) (int, int, int)) {\n  jiCCI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCCIOnArray (double (*f) (int, double*, int, int, int)) {\n  jiCCIOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCustomInit (int (*f) (int, const char*, const char*, const char*, const char*)) {\n  jiCustomInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCustom (double (*f) (int, int, const char*, int)) {\n  jiCustom = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiDeMarkerInit (int (*f) (int, const char*, const char*, int)) {\n  jiDeMarkerInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiDeMarker (double (*f) (int, int, int)) {\n  jiDeMarker = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiEnvelopesInit (int (*f) (int, const char*, const char*, int, const char*, int, int, double)) {\n  jiEnvelopesInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiEnvelopes (double (*f) (int, int, int, const char*, int)) {\n  jiEnvelopes = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiEnvelopesOnArray (double (*f) (int, double*, int, int, const char*, int, double, const char*, int)) {\n  jiEnvelopesOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiFractalsInit (int (*f) (int, const char*, const char*)) {\n  jiFractalsInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiFractals (double (*f) (int, int, const char*, int)) {\n  jiFractals = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiIchimokuInit (int (*f) (int, const char*, const char*, int, int, int)) {\n  jiIchimokuInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiIchimoku (double (*f) (int, int, int, const char*, int)) {\n  jiIchimoku = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMAInit (int (*f) (int, const char*, const char*, int, int, int, int)) {\n  jiMAInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMA (double (*f) (int, int, int, const char*, int)) {\n  jiMA = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMAOnArray (double (*f) (int, double*, int, int, int, const char*, int)) {\n  jiMAOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMACDInit (int (*f) (int, const char*, const char*, int, int, int, int)) {\n  jiMACDInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMACD (double (*f) (int, int, const char*, int)) {\n  jiMACD = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMFIInit (int (*f) (int, const char*, const char*, int)) {\n  jiMFIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMFI (double (*f) (int, int, int)) {\n  jiMFI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMomentumInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiMomentumInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMomentum (double (*f) (int, int, int)) {\n  jiMomentum = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMomentumOnArray (double (*f) (int, double*, int, int, int)) {\n  jiMomentumOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRSIInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiRSIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRSI (double (*f) (int, int, int)) {\n  jiRSI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRSIOnArray (double (*f) (int, double*, int, int, int)) {\n  jiRSIOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRVIInit (int (*f) (int, const char*, const char*, int)) {\n  jiRVIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRVI (double (*f) (int, int, const char*, int)) {\n  jiRVI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiSARInit (int (*f) (int, const char*, const char*, double, double)) {\n  jiSARInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiSAR (double (*f) (int, int, int)) {\n  jiSAR = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiStochasticInit (int (*f) (int, const char*, const char*, int, int, int, const char*)) {\n  jiStochasticInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiStochastic (double (*f) (int, int, const char*, int)) {\n  jiStochastic = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiWPRInit (int (*f) (int, const char*, const char*, int)) {\n  jiWPRInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiWPR (double (*f) (int, int, int)) {\n  jiWPR = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjObjectCreate (int (*f) (int, long, const char*, int, datetime, double, datetime, double)) {\n  jObjectCreate = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjObjectDelete (int (*f) (int, const char*)) {\n  jObjectDelete = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjObjectGet (double (*f) (int, const char*, int)) {\n  jObjectGet = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjObjectSet (int (*f) (int, const char*, int, double)) {\n  jObjectSet = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjIsTesting (int (*f) ()) {\n  jIsTesting = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjMarketInfo (double (*f) (int, const char*, int)) {\n  jMarketInfo = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjCreateNeuralNetwork (int (*f) (int, const char*, const char*)) {\n  jCreateNeuralNetwork = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjActivateNeuralNetwork (double (*f) (int, const char*, double*, int)) {\n  jActivateNeuralNetwork = f;\n}\n\n}\n\nbool ChartClose (long chart_id) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  long id = jChartClose(iFintecheeUID, chart_id);\n  if (id != -1) {\n    for (auto const& [key, val] : paramHandleList[iFintecheeUID].handleList) {\n      if (val == id) {\n        paramHandleList[iFintecheeUID].handleList.erase(key);\n        return true;\n      }\n    }\n  }\n  return false;\n}\nbool ChartClose () {\n  return ChartClose(0);\n}\n\nlong ChartID () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jChartID(iFintecheeUID);\n}\n\nlong ChartOpen (const string symbol, int timeframe) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jChartOpen(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return handle;\n  } else {\n    return 0;\n  }\n}\nlong ChartOpen (long symbol, int timeframe) {\n  return ChartOpen(\"\", timeframe);\n}\n\nENUM_TIMEFRAMES ChartPeriod (long chart_id) {\n  if (paramHandleList[iFintecheeUID].bInit) return PERIOD_CURRENT;\n  return (ENUM_TIMEFRAMES)jChartPeriod(iFintecheeUID, chart_id);\n}\nENUM_TIMEFRAMES ChartPeriod () {\n  return ChartPeriod(0);\n}\n\nstring ChartSymbol (long chart_id) {\n  if (paramHandleList[iFintecheeUID].bInit) return \"\";\n  string symbol(jChartSymbol(iFintecheeUID, chart_id));\n  return symbol;\n}\nstring ChartSymbol () {\n  return ChartSymbol(0);\n}\n\nENUM_TIMEFRAMES Period () {\n  return (ENUM_TIMEFRAMES)jPeriod(iFintecheeUID);\n}\n\nstring Symbol () {\n  string symbol(jSymbol(iFintecheeUID));\n  return symbol;\n}\n\ndouble AccountBalance () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jAccountBalance(iFintecheeUID);\n}\n\nstring AccountCompany () {\n  if (paramHandleList[iFintecheeUID].bInit) return \"\";\n  string company(jAccountCompany(iFintecheeUID));\n  return company;\n}\n\nstring AccountCurrency () {\n  if (paramHandleList[iFintecheeUID].bInit) return \"\";\n  string currency(jAccountCurrency(iFintecheeUID));\n  return currency;\n}\n\ndouble AccountEquity () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jAccountEquity(iFintecheeUID);\n}\n\ndouble AccountFreeMargin () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jAccountFreeMargin(iFintecheeUID);\n}\n\ndouble AccountMargin () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jAccountMargin(iFintecheeUID);\n}\n\ndouble AccountProfit () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jAccountProfit(iFintecheeUID);\n}\n\nint OrdersTotal () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrdersTotal(iFintecheeUID);\n}\n\nint OrdersHistoryTotal () {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrdersHistoryTotal(iFintecheeUID);\n}\nint HistoryTotal () {\n  return OrdersHistoryTotal();\n}\n\nbool OrderSelect(int index, int select, int pool) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  return jOrderSelect(iFintecheeUID, index, select, pool) == 1;\n}\n\nbool OrderSelect(int index, int select) {\n  return OrderSelect(index, select, MODE_TRADES) == 1;\n}\n\ndouble OrderOpenPrice() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderOpenPrice(iFintecheeUID);\n}\n\nint OrderType() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderType(iFintecheeUID);\n}\n\ndouble OrderTakeProfit() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderTakeProfit(iFintecheeUID);\n}\n\ndouble OrderStopLoss() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderStopLoss(iFintecheeUID);\n}\n\ndouble OrderLots() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderLots(iFintecheeUID);\n}\n\ndouble OrderProfit() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderProfit(iFintecheeUID);\n}\n\nstring OrderSymbol() {\n  if (paramHandleList[iFintecheeUID].bInit) return \"\";\n  string symbol(jOrderSymbol(iFintecheeUID));\n  return symbol;\n}\n\nint OrderTicket() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderTicket(iFintecheeUID);\n}\n\nint OrderMagicNumber() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderMagicNumber(iFintecheeUID);\n}\n\ndatetime OrderOpenTime() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderOpenTime(iFintecheeUID);\n}\n\nstring OrderComment() {\n  if (paramHandleList[iFintecheeUID].bInit) return \"\";\n  string comment(jOrderComment(iFintecheeUID));\n  return comment;\n}\n\ndatetime OrderExpiration() {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderExpiration(iFintecheeUID);\n}\n\nvoid OrderPrint() {\n  if (paramHandleList[iFintecheeUID].bInit) return;\n  jOrderPrint(iFintecheeUID);\n}\n\ntemplate <class Type, class... Types>\nvoid Print (const Type & arg, const Types &... args) {\n  stringstream s;\n  s << arg;\n  ((s << args), ..., (s << endl));\n  jPrint(iFintecheeUID, s.str().c_str());\n}\n\n// todo\ntemplate <class Type, class... Types>\nvoid Comment (const Type & arg, const Types &... args) {\n  stringstream s;\n  s << arg;\n  ((s << args), ..., (s << endl));\n  jPrint(iFintecheeUID, s.str().c_str());\n}\n\n// todo\ntemplate <class Type, class... Types>\nvoid Alert (const Type & arg, const Types &... args) {\n  stringstream s;\n  s << arg;\n  ((s << args), ..., (s << endl));\n  jPrint(iFintecheeUID, s.str().c_str());\n}\n\nbool PlaySound (const string name) {\n  Print(\"Playing: \", name);\n  return true;\n}\n\ndatetime iTime (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiTime(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndatetime iTime (long symbol, int timeframe, int shift) {\n  return iTime(\"\", timeframe, shift);\n}\ndouble iOpen (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiOpenInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiOpen(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iOpen (long symbol, int timeframe, int shift) {\n  return iOpen(\"\", timeframe, shift);\n}\ndouble iHigh (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiHighInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiHigh(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iHigh (long symbol, int timeframe, int shift) {\n  return iHigh(\"\", timeframe, shift);\n}\ndouble iLow (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiLowInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiLow(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iLow (long symbol, int timeframe, int shift) {\n  return iLow(\"\", timeframe, shift);\n}\ndouble iClose (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiCloseInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiClose(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iClose (long symbol, int timeframe, int shift) {\n  return iClose(\"\", timeframe, shift);\n}\nlong iVolume (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiVolumeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiVolume(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\nlong iVolume (long symbol, int timeframe, int shift) {\n  return iVolume(\"\", timeframe, shift);\n}\nint iHighest (const string symbol, int timeframe, int type, int count, int start) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiHighest(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start);\n  }\n}\nint iHighest (long symbol, int timeframe, int type, int count, int start) {\n  return iHighest(\"\", timeframe, type, count, start);\n}\nint Highest (const string symbol, int timeframe, int type, int count, int start) {\n  return iHighest (symbol, timeframe, type, count, start);\n}\nint Highest (long symbol, int timeframe, int type, int count, int start) {\n  return iHighest(\"\", timeframe, type, count, start);\n}\nint iLowest (const string symbol, int timeframe, int type, int count, int start) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiLowest(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start);\n  }\n}\nint iLowest (long symbol, int timeframe, int type, int count, int start) {\n  return iLowest(\"\", timeframe, type, count, start);\n}\nint Lowest (const string symbol, int timeframe, int type, int count, int start) {\n  return iLowest (symbol, timeframe, type, count, start);\n}\nint Lowest (long symbol, int timeframe, int type, int count, int start) {\n  return iLowest(\"\", timeframe, type, count, start);\n}\n\ndouble iAC (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iAC_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiACInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiAC(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iAC (long symbol, int timeframe, int shift) {\n  return iAC(\"\", timeframe, shift);\n}\n\ndouble iADX (const string symbol, int timeframe, int period, int applied_price, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iADX_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiADXInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiADX(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_ADX), shift);\n  }\n}\ndouble iADX (long symbol, int timeframe, int period, int applied_price, int mode, int shift) {\n  return iADX(\"\", timeframe, period, applied_price, mode, shift);\n}\n\ndouble iAlligator (\n  const string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift,\n  int ma_method, int applied_price, int mode, int shift) {\n\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iAlligator_\") + symbol + string(\"_\") + string(tf) + string(\"_\") +\n    to_string(jaw_period) + string(\"_\") + to_string(jaw_shift) + string(\"_\") + to_string(teeth_period) + string(\"_\") + to_string(teeth_shift) + string(\"_\") + to_string(lips_period) + string(\"_\") + to_string(lips_shift) + string(\"_\") + to_string(ma_method) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiAlligatorInit(iFintecheeUID, symbol.c_str(), tf, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, convertMAMethod(ma_method), applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiAlligator(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], jaw_shift, teeth_shift, lips_shift, convertMode(mode, INDI_ALLIGATOR), shift);\n  }\n}\ndouble iAlligator (\n  long symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift,\n  int ma_method, int applied_price, int mode, int shift) {\n  return iAlligator(\"\", timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price, mode, shift);\n}\n\ndouble iAO (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iAO_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiAOInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiAO(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iAO (long symbol, int timeframe, int shift) {\n  return iAO(\"\", timeframe, shift);\n}\n\ndouble iATR (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iATR_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiATRInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiATR(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iATR (long symbol, int timeframe, int period, int shift) {\n  return iATR(\"\", timeframe, period, shift);\n}\n\ndouble iBearsPower (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iBearsPower_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiBearsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiBearsPower(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iBearsPower (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iBearsPower(\"\", timeframe, period, applied_price, shift);\n}\n\ndouble iBands (const string symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iBands_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(deviation) + string(\"_\") + to_string(bands_shift) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiBandsInit(iFintecheeUID, symbol.c_str(), tf, period, deviation, bands_shift, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiBands(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], bands_shift, convertMode(mode, INDI_BANDS), shift);\n  }\n}\ndouble iBands (long symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) {\n  return iBands(\"\", timeframe, period, deviation, bands_shift, applied_price, mode, shift);\n}\ndouble iBandsOnArray (double* array, int total, int period, double deviation, int bands_shift, int mode, int shift) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jiBandsOnArray(iFintecheeUID, array, total, period, deviation, bands_shift, convertMode(mode, INDI_BANDS), shift);\n}\n\ndouble iBullsPower (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iBullsPower_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiBullsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiBullsPower(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iBullsPower (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iBullsPower(\"\", timeframe, period, applied_price, shift);\n}\n\ndouble iCCI (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iCCI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiCCIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiCCI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iCCI (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iCCI(\"\", timeframe, period, applied_price, shift);\n}\ndouble iCCIOnArray (double* array, int total, int period, int shift) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jiCCIOnArray(iFintecheeUID, array, total, period, shift);\n}\n\ntemplate<class...Ts>\ndouble iCustom (const string symbol, int timeframe, const string name, Ts&&... args) {\n  const char* tf = convertTimeFrame(timeframe);\n  stringstream s;\n  const char* mode;\n  int shift;\n  int length = sizeof...(args);\n\n  int i = 0;\n  auto loop = [&] (auto && input) {\n    if (i >= 0 && i < length - 2) {\n      s << input << \"|||\";\n    } else if (i == length - 2) {\n      mode = (const char*)input;\n    } else if (i == length - 1) {\n      shift = (int)input;\n    }\n    i++;\n  };\n\n  (loop(args), ...);\n\n  string strID = string(\"iCustom_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + name + string(\"_\") + s.str();\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiCustomInit(iFintecheeUID, symbol.c_str(), tf, name.c_str(), s.str().c_str());\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiCustom(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], mode, shift);\n  }\n}\ntemplate<class...Ts>\ndouble iCustom (long symbol, int timeframe, const string name, Ts&&... args) {\n  return iCustom(\"\", timeframe, name, args...);\n}\n\ndouble iDeMarker (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iDeMarker_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiDeMarkerInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiDeMarker(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iDeMarker (long symbol, int timeframe, int period, int shift) {\n  return iDeMarker(\"\", timeframe, period, shift);\n}\n\ndouble iEnvelopes (const string symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iEnvelopes_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(ma_period) + string(\"_\") + to_string(ma_method) + string(\"_\") + to_string(ma_shift) + string(\"_\") + to_string(applied_price) + string(\"_\") + to_string(deviation);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiEnvelopesInit(iFintecheeUID, symbol.c_str(), tf, ma_period, convertMAMethod(ma_method), ma_shift, applied_price, deviation);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiEnvelopes(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], ma_shift, convertMode(mode, INDI_ENVELOPES), shift);\n  }\n}\ndouble iEnvelopes (long symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) {\n  return iEnvelopes(\"\", timeframe, ma_period, ma_method, ma_shift, applied_price, deviation, mode, shift);\n}\ndouble iEnvelopesOnArray (double* array, int total, int ma_period, int ma_method, int ma_shift, double deviation, int mode, int shift) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jiEnvelopesOnArray(iFintecheeUID, array, total, ma_period, convertMAMethod(ma_method), ma_shift, deviation, convertMode(mode, INDI_ENVELOPES), shift);\n}\n\ndouble iFractals (const string symbol, int timeframe, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iFractals_\") + symbol + string(\"_\") + string(tf);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiFractalsInit(iFintecheeUID, symbol.c_str(), tf);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiFractals(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_FRACTALS), shift);\n  }\n}\ndouble iFractals (long symbol, int timeframe, int mode, int shift) {\n  return iFractals(\"\", timeframe, mode, shift);\n}\n\ndouble iIchimoku (const string symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iIchimoku_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(tenkan_sen) + string(\"_\") + to_string(kijun_sen) + string(\"_\") + to_string(senkou_span_b);\n  if (paramHandleList[iFintecheeUID].bInit) {\n   int handle = jiIchimokuInit(iFintecheeUID, symbol.c_str(), tf, tenkan_sen, kijun_sen, senkou_span_b);\n   paramHandleList[iFintecheeUID].handleList[strID] = handle;\n   return 0;\n  } else {\n   if (mode == MODE_TENKANSEN) {\n     return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift);\n   } else if (mode == MODE_KIJUNSEN) {\n     return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift);\n   } else if (mode == MODE_SENKOUSPANA) {\n     return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift);\n   } else if (mode == MODE_SENKOUSPANB) {\n     return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift);\n   } else {\n     return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], -kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift);\n   }\n  }\n}\ndouble iIchimoku (long symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) {\n  return iIchimoku(\"\", timeframe, tenkan_sen, kijun_sen, senkou_span_b, mode, shift);\n}\n\ndouble iMA (const string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMA_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(ma_period) + string(\"_\") + to_string(ma_shift) + string(\"_\") + to_string(ma_method) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiMAInit(iFintecheeUID, symbol.c_str(), tf, ma_period, ma_shift, ma_method, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiMA(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], ma_shift, convertMAMethod(ma_method), shift);\n  }\n}\ndouble iMA (long symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) {\n  return iMA(\"\", timeframe, ma_period, ma_shift, ma_method, applied_price, shift);\n}\ndouble iMAOnArray (double* array, int total, int ma_period, int ma_shift, int ma_method, int shift) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jiMAOnArray(iFintecheeUID, array, total, ma_period, ma_shift, convertMAMethod(ma_method), shift);\n}\n\ndouble iMACD (const string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMACD_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(fast_ema_period) + string(\"_\") + to_string(slow_ema_period) + string(\"_\") + to_string(signal_period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiMACDInit(iFintecheeUID, symbol.c_str(), tf, fast_ema_period, slow_ema_period, signal_period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiMACD(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_MACD), shift);\n  }\n}\ndouble iMACD (long symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) {\n  return iMACD(\"\", timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, mode, shift);\n}\n\ndouble iMFI (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMFI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiMFIInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiMFI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iMFI (long symbol, int timeframe, int period, int shift) {\n  return iMFI(\"\", timeframe, period, shift);\n}\n\ndouble iMomentum (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMomentum_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiMomentumInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiMomentum(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iMomentum (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iMomentum(\"\", timeframe, period, applied_price, shift);\n}\ndouble iMomentumOnArray (double* array, int total, int period, int shift) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jiMomentumOnArray(iFintecheeUID, array, total, period, shift);\n}\n\ndouble iRSI (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iRSI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiRSIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiRSI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iRSI (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iRSI(\"\", timeframe, period, applied_price, shift);\n}\ndouble iRSIOnArray (double* array, int total, int period, int shift) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jiRSIOnArray(iFintecheeUID, array, total, period, shift);\n}\n\ndouble iRVI (const string symbol, int timeframe, int period, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iRVI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiRVIInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiRVI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_RVI), shift);\n  }\n}\ndouble iRVI (long symbol, int timeframe, int period, int mode, int shift) {\n  return iRVI(\"\", timeframe, period, mode, shift);\n}\n\ndouble iSAR (const string symbol, int timeframe, double step, double maximum, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iSAR_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(step) + string(\"_\") + to_string(maximum);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiSARInit(iFintecheeUID, symbol.c_str(), tf, step, maximum);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiSAR(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iSAR (long symbol, int timeframe, double step, double maximum, int shift) {\n  return iSAR(\"\", timeframe, step, maximum, shift);\n}\n\ndouble iStochastic (const string symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iStochastic_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(Kperiod) + string(\"_\") + to_string(Dperiod) + string(\"_\") + to_string(slowing) + string(\"_\") + to_string(method);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiStochasticInit(iFintecheeUID, symbol.c_str(), tf, Kperiod, Dperiod, slowing, convertMAMethod(method));\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiStochastic(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_STOCHASTIC), shift);\n  }\n}\ndouble iStochastic (long symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) {\n  return iStochastic(\"\", timeframe, Kperiod, Dperiod, slowing, method, price_field, mode, shift);\n}\n\ndouble iWPR (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iWPR_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramHandleList[iFintecheeUID].bInit) {\n    int handle = jiWPRInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramHandleList[iFintecheeUID].handleList[strID] = handle;\n    return 0;\n  } else {\n    return jiWPR(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift);\n  }\n}\ndouble iWPR (long symbol, int timeframe, int period, int shift) {\n  return iWPR(\"\", timeframe, period, shift);\n}\n\nbool ObjectCreate (long chart_id, const string object_name, ENUM_OBJECT object_type, int sub_window, datetime time, double price, datetime time2 = 0, double price2 = 0) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  if (object_type == OBJ_ARROW_CHECK || object_type == OBJ_TREND) {\n    return jObjectCreate(iFintecheeUID, chart_id, object_name.c_str(), object_type, time, price, time2, price2) == 1;\n  } else {\n    return false;\n  }\n}\n\nbool ObjectDelete (const string object_name) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  return jObjectDelete(iFintecheeUID, object_name.c_str()) == 1;\n}\nbool ObjectDelete (long chart_id, const string object_name) {\n  return ObjectDelete(object_name);\n}\n\ndouble ObjectGet (const string object_name, int property_index) {\n  if (paramHandleList[iFintecheeUID].bInit) return 0;\n  return jObjectGet(iFintecheeUID, object_name.c_str(), property_index);\n}\n\nbool ObjectSet (const string object_name, int property_index, double value) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  return jObjectSet(iFintecheeUID, object_name.c_str(), property_index, value) == 1;\n}\n\nint OrderSend (const string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, const string comment, int magic, datetime expiration, int arrow_color) {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return jOrderSend(iFintecheeUID, symbol.c_str(), convertCmd(cmd), volume, price, slippage, stoploss, takeprofit, comment.c_str(), magic, expiration, arrow_color);\n}\nint OrderSend (long symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, const string comment, int magic, datetime expiration, int arrow_color) {\n  if (paramHandleList[iFintecheeUID].bInit) return -1;\n  return OrderSend(\"\", cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color);\n}\n\nbool OrderModify (int ticket, double price, double stoploss, double takeprofit, datetime expiration, int arrow_color) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  return jOrderModify (iFintecheeUID, ticket, price, stoploss, takeprofit, expiration, arrow_color) == 1;\n}\n\nbool OrderClose(int ticket, double lots, double price, int slippage, int arrow_color) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  return jOrderClose(iFintecheeUID, ticket, lots, price, slippage, arrow_color) == 1;\n}\n\nbool OrderDelete(int ticket, int arrow_color) {\n  if (paramHandleList[iFintecheeUID].bInit) return false;\n  return jOrderDelete(iFintecheeUID, ticket, arrow_color) == 1;\n}\nbool OrderDelete(int ticket) {\n  return OrderDelete(ticket, CLR_NONE);\n}\n\n// todo, check whether the logic about the return value is the same as MQL4\ndatetime GlobalVariableSet (const string name, double value) {\n  return setGlobalVar(iFintecheeUID, name, value);\n}\n\nbool GlobalVariableCheck (const string name) {\n  return checkGlobalVar(iFintecheeUID, name);\n}\n\ndouble GlobalVariableGet (const string name) {\n  return getGlobalVar(iFintecheeUID, name);\n}\n\nbool GlobalVariableDel (const string name) {\n  return delGlobalVar(iFintecheeUID, name);\n}\n\nbool IsTesting () {\n  return jIsTesting() == 1;\n}\n\ndouble MarketInfo (const string symbol, int type) {\n  if (symbol == \"\") {\n    if (type == MODE_BID) {\n      return Bid;\n    } else if (type == MODE_ASK) {\n      return Ask;\n    } else if (type == MODE_POINT) {\n      return Point;\n    } else if (type == MODE_DIGITS) {\n      return Digits;\n    } else {\n      return jMarketInfo(iFintecheeUID, symbol.c_str(), type);\n    }\n  } else {\n    return jMarketInfo(iFintecheeUID, symbol.c_str(), type);\n  }\n}\ndouble MarketInfo (long symbol, int type) {\n  return MarketInfo(\"\", type);\n}\n\n// Not compatible with MQL\n// Deprecated\nbool SCompareL (const string str, long l) {\n  return jSCompareL(iFintecheeUID, str.c_str(), l);\n}\n\n// Not compatible with MQL\nbool VeriSig (const string fintechee_data, const string fintechee_signature, const string fintechee_public_key, const string application_public_key) {\n  string data = fintechee_data;\n  string signature = fintechee_signature;\n  string publicKey = fintechee_public_key;\n  string appPublicKey = application_public_key;\n  data.erase(std::remove(data.begin(), data.end(), '\\n'), data.end());\n  signature.erase(std::remove(signature.begin(), signature.end(), '\\n'), signature.end());\n  publicKey.erase(std::remove(publicKey.begin(), publicKey.end(), '\\n'), publicKey.end());\n  appPublicKey.erase(std::remove(appPublicKey.begin(), appPublicKey.end(), '\\n'), appPublicKey.end());\n  data = StringTrimLeft(StringTrimRight(data));\n  signature = StringTrimLeft(StringTrimRight(signature));\n  publicKey = StringTrimLeft(StringTrimRight(publicKey));\n  appPublicKey = StringTrimLeft(StringTrimRight(appPublicKey));\n\n  int dataLen = StringLen(data);\n  int signatureLen = StringLen(signature);\n  int publicKeyLen = StringLen(publicKey);\n  int appPublicKeyLen = StringLen(appPublicKey);\n  if (dataLen == 0 || signatureLen == 0 || publicKeyLen == 0 || appPublicKeyLen == 0) return false;\n  if (publicKeyLen != appPublicKeyLen) return false;\n  if (StringCompare(publicKey, appPublicKey) != 0) return false;\n  bool res = jVeriSig(iFintecheeUID, data.c_str(), signature.c_str(), publicKey.c_str());\n\n  if (res) {\n    std::vector<string> arr;\n    std::stringstream ss(data);\n\n    string s;\n    while (std::getline(ss, s, ',')) {\n      arr.push_back(s);\n    }\n\n    if (0 < arr.size()) {\n      if (std::stoll(arr[0]) >= TimeCurrent()) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\n// Not compatible with MQL\n// Uses Synaptic\nbool CreateNeuralNetwork (const string nnName, const string nnJson) {\n  return jCreateNeuralNetwork(iFintecheeUID, nnName.c_str(), nnJson.c_str()) == 1;\n}\n\n// Not compatible with MQL\n// Uses Synaptic\ndouble ActivateNeuralNetwork (const string nnName, double* input, int inputNum) {\n  return jActivateNeuralNetwork(iFintecheeUID, nnName.c_str(), input, inputNum);\n}\n\n// Not compatible with MQL\n// If you use neural network(Synaptic or Tensorflow), please call PreventCleanUp at the beginning of OnInit\nvoid PreventCleanUp () {\n  jPreventCleanUp(iFintecheeUID);\n}\n\n// Not compatible with MQL\n// Uses Tensorflow\nbool BuildCNN (const string nnName, int inputNum, int hiddenNum) {\n  return jBuildCNN(iFintecheeUID, nnName.c_str(), inputNum, hiddenNum);\n}\n\n// Not compatible with MQL\n// Uses Tensorflow\nbool TrainCNN (const string nnName, double* dataInput, double* dataOutput, long trainingSetNum, int inputNum, long iterations, int batchSize, bool bMonitor) {\n  return jTrainCNN(iFintecheeUID, nnName.c_str(), dataInput, dataOutput, trainingSetNum, inputNum, iterations, batchSize, bMonitor);\n}\n\n// Not compatible with MQL\n// Uses Tensorflow\ndouble RunCNN (const string nnName, double* dataInput, int inputNum) {\n  return jRunCNN(iFintecheeUID, nnName.c_str(), dataInput, inputNum);\n}\n\n// Not compatible with MQL\n// Uses Tensorflow\nbool SaveCNN (const string nnName) {\n  return jSaveCNN(iFintecheeUID, nnName.c_str());\n}\n\n// Not compatible with MQL\n// Uses Tensorflow\nbool LoadCNN (const string nnName) {\n  return jLoadCNN(iFintecheeUID, nnName.c_str());\n}\n"
  },
  {
    "path": "EA/Plugin-for-MQL/mqlindi2fintechee.h",
    "content": "#include <stdio.h>\n#include <stdarg.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n#include <map>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <float.h>\n#include <unistd.h>\n#include <iomanip>\n#include <ctime>\n#include <cmath>\n#include <chrono>\n#include <emscripten.h>\nusing namespace std;\n\ntypedef time_t datetime; // Please note that time_t can't handle dates beyond Y2038\ntypedef int color;\n\nenum ENUM_TIMEFRAMES {\n  PERIOD_CURRENT = 0,\n  PERIOD_M1 = 1,\n  PERIOD_M5 = 5,\n  PERIOD_M15 = 15,\n  PERIOD_M30 = 30,\n  PERIOD_H1 = 60,\n  PERIOD_H4 = 240,\n  PERIOD_D1 = 1440,\n  PERIOD_W1 = 10080,\n  PERIOD_MN1 = 43200\n};\nenum ENUM_APPLIED_PRICE {\n  PRICE_CLOSE = 0,\n  PRICE_OPEN = 1,\n  PRICE_HIGH = 2,\n  PRICE_LOW = 3,\n  PRICE_MEDIAN = 4,\n  PRICE_TYPICAL = 5,\n  PRICE_WEIGHTED = 6\n};\nenum ENUM_MA_METHOD {\n  MODE_SMA = 0,\n  MODE_EMA = 1,\n  MODE_SMMA = 2,\n  MODE_LWMA = 3\n};\nenum ENUM_INIT_RETCODE {\n  INIT_SUCCEEDED = 0,\n  INIT_FAILED = -1,\n  INIT_PARAMETERS_INCORRECT = -1\n};\n\nconst int MODE_MAIN = 0;\nconst int MODE_SIGNAL = 1;\nconst int MODE_PLUSDI = 1;\nconst int MODE_MINUSDI = 2;\nconst int MODE_UPPER = 1;\nconst int MODE_LOWER = 2;\nconst int MODE_GATORJAW = 1;\nconst int MODE_GATORTEETH = 2;\nconst int MODE_GATORLIPS = 3;\nconst int MODE_TENKANSEN = 1;\nconst int MODE_KIJUNSEN = 2;\nconst int MODE_SENKOUSPANA = 3;\nconst int MODE_SENKOUSPANB = 4;\nconst int MODE_CHIKOUSPAN = 5;\nconst int MODE_OPEN = 0;\nconst int MODE_LOW = 1;\nconst int MODE_HIGH = 2;\nconst int MODE_CLOSE = 3;\nconst int MODE_VOLUME = 4;\nconst int MODE_TIME = 5;\nconst int MODE_BID = 9;\nconst int MODE_ASK = 10;\nconst int MODE_POINT = 11;\nconst int MODE_DIGITS = 12;\nconst int MODE_SPREAD = 13;\nconst int MODE_SWAPLONG = 18;\nconst int MODE_SWAPSHORT = 19;\nconst int MODE_TRADEALLOWED = 22;\nconst int MODE_MINLOT = 23;\nconst int MODE_LOTSTEP = 24;\nconst int MODE_MAXLOT = 25;\n\n// MQL has no these enumerations.\nconst int INDI_OHLC = 0;\nconst int INDI_ADX = 1;\nconst int INDI_ALLIGATOR = 2;\nconst int INDI_BANDS = 3;\nconst int INDI_ENVELOPES = 4;\nconst int INDI_FRACTALS = 5;\nconst int INDI_ICHIMOKU = 6;\nconst int INDI_MACD = 7;\nconst int INDI_RVI = 8;\nconst int INDI_STOCHASTIC = 9;\n\nconst int MODE_ASCEND = 1;\nconst int MODE_DESCEND = 2;\n\nconst int TIME_DATE = 4;\nconst int TIME_MINUTES = 2;\nconst int TIME_SECONDS = 1;\n\nconst int Green = 0;\nconst int Red = 0;\nconst int Violet = 0;\nconst int White = 0;\nconst int Yellow = 0;\nconst int Blue = 0;\nconst int FireBrick = 0;\nconst int Pink = 0;\nconst int Lime = 0;\n\nconst int EMPTY = -1;\nconst int EMPTY_VALUE = 0x7FFFFFFF;\nconst int CLR_NONE = -1;\nconst int clrNONE = -1;\nconst int CHARTS_MAX = 100;\nconst int INVALID_HANDLE = -1;\nconst int WHOLE_ARRAY = 0;\nconst int WRONG_VALUE = -1;\n\nenum ENUM_OBJECT {\n  OBJ_ARROW_CHECK = 1\n};\n\nconst char* convertTimeFrame (int timeframe) {\n  if (PERIOD_M1 == timeframe) {\n    return \"M1\";\n  } else if (PERIOD_M5 == timeframe) {\n    return \"M5\";\n  } else if (PERIOD_M15 == timeframe) {\n    return \"M15\";\n  } else if (PERIOD_M30 == timeframe) {\n    return \"M30\";\n  } else if (PERIOD_H1 == timeframe) {\n    return \"H1\";\n  } else if (PERIOD_H4 == timeframe) {\n    return \"H4\";\n  } else if (PERIOD_D1 == timeframe) {\n    return \"D\";\n  } else if (PERIOD_W1 == timeframe) {\n    return \"W\";\n  } else if (PERIOD_MN1 == timeframe) {\n    return \"M\";\n  } else {\n    return \"0\";\n  }\n}\nconst char* convertMode (int mode, int indi) {\n  if (MODE_SIGNAL == mode && (indi == INDI_MACD || indi == INDI_RVI || indi == INDI_STOCHASTIC)) {\n    return \"signal\";\n  } else if (MODE_PLUSDI == mode && indi == INDI_ADX) {\n    return \"plusDi\";\n  } else if (MODE_MINUSDI == mode && indi == INDI_ADX) {\n    return \"minusDi\";\n  } else if (MODE_UPPER == mode && (indi == INDI_BANDS || indi == INDI_ENVELOPES)) {\n    return \"upper\";\n  } else if (MODE_LOWER == mode && (indi == INDI_BANDS || indi == INDI_ENVELOPES)) {\n    return \"lower\";\n  } else if (MODE_UPPER == mode && indi == INDI_FRACTALS) {\n    return \"fractalsUp\";\n  } else if (MODE_LOWER == mode && indi == INDI_FRACTALS) {\n    return \"fractalsDown\";\n  } else if (MODE_GATORJAW == mode && indi == INDI_ALLIGATOR) {\n    return \"jaws\";\n  } else if (MODE_GATORTEETH == mode && indi == INDI_ALLIGATOR) {\n    return \"teeth\";\n  } else if (MODE_GATORLIPS == mode && indi == INDI_ALLIGATOR) {\n    return \"lips\";\n  } else if (MODE_TENKANSEN == mode && indi == INDI_ICHIMOKU) {\n    return \"tenkan\";\n  } else if (MODE_KIJUNSEN == mode && indi == INDI_ICHIMOKU) {\n    return \"kijun\";\n  } else if (MODE_SENKOUSPANA == mode && indi == INDI_ICHIMOKU) {\n    return \"spana\";\n  } else if (MODE_SENKOUSPANB == mode && indi == INDI_ICHIMOKU) {\n    return \"spanb\";\n  } else if (MODE_CHIKOUSPAN == mode && indi == INDI_ICHIMOKU) {\n    return \"chikou\";\n  } else if (MODE_OPEN == mode && indi == INDI_OHLC) {\n    return \"Open\";\n  } else if (MODE_LOW == mode && indi == INDI_OHLC) {\n    return \"Low\";\n  } else if (MODE_HIGH == mode && indi == INDI_OHLC) {\n    return \"High\";\n  } else if (MODE_CLOSE == mode && indi == INDI_OHLC) {\n    return \"Close\";\n  } else if (MODE_VOLUME == mode && indi == INDI_OHLC) {\n    return \"Volume\";\n  } else if (MODE_TIME == mode && indi == INDI_OHLC) {\n    return \"Time\";\n  } else {\n    return \"main\";\n  }\n}\nconst char* convertMAMethod (int ma_method) {\n  if (MODE_EMA == ma_method) {\n    return \"ema\";\n  } else if (MODE_SMMA == ma_method) {\n    return \"smma\";\n  } else if (MODE_LWMA == ma_method) {\n    return \"lwma\";\n  } else {\n    return \"sma\";\n  }\n}\n\nvoid (*jPrint) (int, const char*);\nvoid (*jSetIndexShift) (int, int, int);\nlong (*jChartID) (int);\nint (*jChartPeriod) (int, long);\nconst char* (*jChartSymbol) (int, long);\nint (*jPeriod) (int);\nconst char* (*jSymbol) (int);\nint (*jiTimeInit) (int, const char*, const char*);\ndatetime (*jiTime) (int, int, int);\nint (*jiOpenInit) (int, const char*, const char*);\ndouble (*jiOpen) (int, int, int);\nint (*jiHighInit) (int, const char*, const char*);\ndouble (*jiHigh) (int, int, int);\nint (*jiLowInit) (int, const char*, const char*);\ndouble (*jiLow) (int, int, int);\nint (*jiCloseInit) (int, const char*, const char*);\ndouble (*jiClose) (int, int, int);\nint (*jiVolumeInit) (int, const char*, const char*);\nlong (*jiVolume) (int, int, int);\nint (*jiHighest) (int, int, const char*, int, int);\nint (*jiLowest) (int, int, const char*, int, int);\nint (*jiACInit) (int, const char*, const char*);\ndouble (*jiAC) (int, int, int);\nint (*jiADXInit) (int, const char*, const char*, int, int);\ndouble (*jiADX) (int, int, const char*, int);\nint (*jiAlligatorInit) (int, const char*, const char*, int, int, int, int, int, int, const char*, int);\ndouble (*jiAlligator) (int, int, int, int, int, const char*, int);\nint (*jiAOInit) (int, const char*, const char*);\ndouble (*jiAO) (int, int, int);\nint (*jiATRInit) (int, const char*, const char*, int);\ndouble (*jiATR) (int, int, int);\nint (*jiBearsPowerInit) (int, const char*, const char*, int, int);\ndouble (*jiBearsPower) (int, int, int);\nint (*jiBandsInit) (int, const char*, const char*, int, double, int, int);\ndouble (*jiBands) (int, int, int, const char*, int);\ndouble (*jiBandsOnArray) (int, double*, int, int, double, int, const char*, int);\nint (*jiBullsPowerInit) (int, const char*, const char*, int, int);\ndouble (*jiBullsPower) (int, int, int);\nint (*jiCCIInit) (int, const char*, const char*, int, int);\ndouble (*jiCCI) (int, int, int);\ndouble (*jiCCIOnArray) (int, double*, int, int, int);\nint (*jiCustomInit) (int, const char*, const char*, const char*, const char*);\ndouble (*jiCustom) (int, int, const char*, int);\nint (*jiDeMarkerInit) (int, const char*, const char*, int);\ndouble (*jiDeMarker) (int, int, int);\nint (*jiEnvelopesInit) (int, const char*, const char*, int, const char*, int, int, double);\ndouble (*jiEnvelopes) (int, int, int, const char*, int);\ndouble (*jiEnvelopesOnArray) (int, double*, int, int, const char*, int, double, const char*, int);\nint (*jiFractalsInit) (int, const char*, const char*);\ndouble (*jiFractals) (int, int, const char*, int);\nint (*jiIchimokuInit) (int, const char*, const char*, int, int, int);\ndouble (*jiIchimoku) (int, int, int, const char*, int);\nint (*jiMAInit) (int, const char*, const char*, int, int, int, int);\ndouble (*jiMA) (int, int, int, const char*, int);\ndouble (*jiMAOnArray) (int, double*, int, int, int, const char*, int);\nint (*jiMACDInit) (int, const char*, const char*, int, int, int, int);\ndouble (*jiMACD) (int, int, const char*, int);\nint (*jiMFIInit) (int, const char*, const char*, int);\ndouble (*jiMFI) (int, int, int);\nint (*jiMomentumInit) (int, const char*, const char*, int, int);\ndouble (*jiMomentum) (int, int, int);\ndouble (*jiMomentumOnArray) (int, double*, int, int, int);\nint (*jiRSIInit) (int, const char*, const char*, int, int);\ndouble (*jiRSI) (int, int, int);\ndouble (*jiRSIOnArray) (int, double*, int, int, int);\nint (*jiRVIInit) (int, const char*, const char*, int);\ndouble (*jiRVI) (int, int, const char*, int);\nint (*jiSARInit) (int, const char*, const char*, double, double);\ndouble (*jiSAR) (int, int, int);\nint (*jiStochasticInit) (int, const char*, const char*, int, int, int, const char*);\ndouble (*jiStochastic) (int, int, const char*, int);\nint (*jiWPRInit) (int, const char*, const char*, int);\ndouble (*jiWPR) (int, int, int);\ndouble (*jMarketInfo) (int, const char*, int);\n\n// Deprecated\nEM_JS(bool, jSCompareL, (int uid, const char* str, long l), {\n  try {\n    var obj = window.mqlIndicatorsBuffer[uid + \"\"];\n    var UTF8ToString = window.mqlIndicators[obj.name].module.UTF8ToString;\n    var s = UTF8ToString(str);\n    return parseInt(s) >= l;\n  } catch (e) {\n    return false;\n  }\n});\n\nEM_JS(bool, jVeriSig, (int uid, const char* fintechee_data, const char* fintechee_signature, const char* fintechee_public_key), {\n  return Asyncify.handleSleep(function (wakeUp) {\n    if (typeof veriSig == \"undefined\") {\n      wakeUp(false);\n      return;\n    }\n\n    var obj = window.mqlIndicatorsBuffer[uid + \"\"];\n    var UTF8ToString = window.mqlIndicators[obj.name].module.UTF8ToString;\n\n    const data = UTF8ToString(fintechee_data);\n    const signature = UTF8ToString(fintechee_signature);\n    const public_key = UTF8ToString(fintechee_public_key);\n\n    veriSig(false, data, signature, public_key)\n    .then(function (res) {\n      if (res) {\n        wakeUp(res);\n      } else {\n        printErrorMessage(\"Signature verification failed.\");\n        wakeUp(res);\n      }\n    })\n    .catch(function (e) {\n      printErrorMessage(e.message);\n      wakeUp(false);\n    })\n  });\n});\n\nvoid Sleep (int milliseconds) {\n  sleep(milliseconds / 1000);\n}\nint GetLastError () {\n  return 0;\n}\nstring ErrorDescription (int code) {\n  return \"\";\n}\nbool IsStopped () {\n  return false;\n}\nbool RefreshRates () {\n  return true;\n}\ndouble MathAbs (double val) {\n  return abs(val);\n}\ndouble MathArccos (double val) {\n  return acos(val);\n}\ndouble MathArcsin (double val) {\n  return asin(val);\n}\ndouble MathArctan (double val) {\n  return atan(val);\n}\ndouble MathCeil (double val) {\n  return ceil(val);\n}\ndouble MathCos (double val) {\n  return cos(val);\n}\ndouble MathExp (double val) {\n  return exp(val);\n}\ndouble MathFloor (double val) {\n  return floor(val);\n}\ndouble MathLog (double val) {\n  return log(val);\n}\ndouble MathLog10 (double val) {\n  return log10(val);\n}\ndouble MathMax (double a, double b) {\n  return max(a, b);\n}\ndouble MathMin (double a, double b) {\n  return min(a, b);\n}\ndouble MathMod (double a, double b) {\n  return fmod(a, b);\n}\ndouble MathPow (double base, double exponent) {\n  return pow(base, exponent);\n}\nint MathRand () {\n  return rand();\n}\ndouble MathRound (double val) {\n  return round(val);\n}\ndouble MathSin (double val) {\n  return sin(val);\n}\ndouble MathSqrt (double val) {\n  return sqrt(val);\n}\nvoid MathSrand (int seed) {\n  srand(seed);\n}\ndouble MathTan (double val) {\n  return tan(val);\n}\nint StringLen (const string string_value) {\n  return string_value.length();\n}\nint StringReplace (string str, const string find, const string replacement) {\n  if(find.empty()) {\n    return 0;\n  }\n  size_t start_pos = 0;\n  int count = 0;\n  while((start_pos = str.find(find, start_pos)) != string::npos) {\n    str.replace(start_pos, find.length(), replacement);\n    start_pos += replacement.length();\n    count++;\n  }\n  return count;\n}\nstring StringSubstr (const string string_value, int start_pos, int length) {\n  if (start_pos < 0 || start_pos >= string_value.length() || length <= 0 || start_pos + length > string_value.length()) {\n    return \"\";\n  }\n  return string_value.substr(start_pos, length);\n}\nbool StringToLower (string string_var) {\n  transform(string_var.begin(), string_var.end(), string_var.begin(), [](unsigned char c){ return tolower(c);});\n  return true;\n}\nbool StringToUpper (string string_var) {\n  transform(string_var.begin(), string_var.end(), string_var.begin(), [](unsigned char c){ return toupper(c);});\n  return true;\n}\nstring StringTrimLeft(const string text) {\n  string s = text;\n  s.erase(s.begin(), find_if(s.begin(), s.end(), [](int c) {return !isspace(c);}));\n  return s;\n}\nstring StringTrimRight(const string text) {\n  string s = text;\n  s.erase(find_if(s.rbegin(), s.rend(), [](int c) {return !isspace(c);}).base(), s.end());\n  return s;\n}\nstring DoubleToString (double value, int dijits) {\n  stringstream stream;\n  stream << fixed << setprecision(dijits) << value;\n  return stream.str();\n}\nstring DoubleToString (double value) {\n  return DoubleToString(value, 8);\n}\nstring DoubleToStr (double value, int dijits) {\n  return DoubleToString(value, dijits);\n}\nstring DoubleToStr (double value) {\n  return DoubleToString(value, 8);\n}\nstring IntegerToString (long number, int str_len, unsigned short fill_symbol) {\n  return to_string(number);\n}\nstring ShortToString (unsigned short symbol_code) {\n  return to_string(symbol_code);\n}\nstring TimeToString (datetime value, int mode) {\n  time_t tim = value;\n  tm * ptm = localtime(&tim);\n  if (mode == 7 || mode == 5) {\n    char buffer[20];\n    strftime(buffer, 20, \"%Y.%m.%d %H:%M:%S\", ptm);\n    return string(buffer);\n  } else if (mode == 4) {\n    char buffer[11];\n    strftime(buffer, 11, \"%Y.%m.%d\", ptm);\n    return string(buffer);\n  } else if (mode == 3 || mode == 1) {\n    char buffer[9];\n    strftime(buffer, 9, \"%H:%M:%S\", ptm);\n    return string(buffer);\n  } else if (mode == 2) {\n    char buffer[6];\n    strftime(buffer, 6, \"%H:%M\", ptm);\n    return string(buffer);\n  } else {\n    char buffer[17];\n    strftime(buffer, 17, \"%Y.%m.%d %H:%M\", ptm);\n    return string(buffer);\n  }\n}\nstring TimeToString (datetime value) {\n  return TimeToString(value, 5);\n}\nstring TimeToStr (datetime value, int mode) {\n  return TimeToString(value, mode);\n}\nstring TimeToStr (datetime value) {\n  return TimeToString(value, 5);\n}\ndouble NormalizeDouble (double value, int digits) {\n  return (round(value * pow(10, digits))) / pow(10, digits);\n}\ndouble StringToDouble (const string value) {\n  return stod(value);\n}\ndouble StrToDouble (const string value) {\n  return StringToDouble(value);\n}\nint StringToInteger (const string value) {\n  return stoi(value);\n}\nint StrToInteger (const string value) {\n  return StringToInteger(value);\n}\ndatetime StringToTime (const string value) {\n  struct tm tm;\n  if (value.length() == 19) {\n    strptime(value.c_str(), \"%Y.%m.%d %H:%M:%S\", &tm);\n    return mktime(&tm);\n  } else if (value.length() == 10) {\n    strptime(value.c_str(), \"%Y.%m.%d\", &tm);\n    return mktime(&tm);\n  } else if (value.length() == 16) {\n    strptime(value.c_str(), \"%Y.%m.%d %H:%M\", &tm);\n    return mktime(&tm);\n  } else {\n    return 0;\n  }\n}\ndatetime StrToTime (const string value) {\n  return StringToTime(value);\n}\nint StringCompare (const string str1, const string str2, bool case_sensitive = true) {\n  if (case_sensitive) {\n    return strcmp(str1.c_str(), str2.c_str());\n  } else {\n    return strcasecmp(str1.c_str(), str2.c_str());\n  }\n}\ndatetime TimeCurrent () {\n  return chrono::system_clock::to_time_t(chrono::system_clock::now());\n}\ndatetime TimeGMT () {\n  return TimeCurrent();\n}\ndatetime CurTime () {\n  return TimeCurrent();\n}\nint Day () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mday;\n}\nint DayOfWeek () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_wday;\n}\nint DayOfYear () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_yday + 1;\n}\nint Hour () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_hour;\n}\nint Minute () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_min;\n}\nint Month () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mon + 1;\n}\nint Seconds () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_sec;\n}\nint TimeDay (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mday;\n}\nint TimeDayOfWeek (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_wday;\n}\nint TimeDayOfYear (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_yday + 1;\n}\nint TimeHour (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_hour;\n}\nint TimeMinute (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_min;\n}\nint TimeMonth (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_mon + 1;\n}\nint TimeSeconds (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_sec;\n}\nint TimeYear (datetime ltime) {\n  time_t theTime = ltime;\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_year + 1900;\n}\nint Year () {\n  time_t theTime = time(NULL);\n  struct tm *aTime = localtime(&theTime);\n  return aTime->tm_year + 1900;\n}\nint ArrayCopy (char* dst_array, const char* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (char)));\n    return count;\n  }\n}\nint ArrayCopy (short* dst_array, const short* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (short)));\n    return count;\n  }\n}\nint ArrayCopy (int* dst_array, const int* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (int)));\n    return count;\n  }\n}\nint ArrayCopy (long* dst_array, const long* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (long)));\n    return count;\n  }\n}\nint ArrayCopy (float* dst_array, const float* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (float)));\n    return count;\n  }\n}\nint ArrayCopy (double* dst_array, const double* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (double)));\n    return count;\n  }\n}\nint ArrayCopy (bool* dst_array, const bool* src_array, int dst_start, int src_start, int count) {\n  if (count <= 0) {\n    return 0;\n  } else {\n    memcpy(dst_array, src_array, count * (sizeof (bool)));\n    return count;\n  }\n}\nvoid ArrayFree (void* array) {\n  free(array);\n}\nvoid ArrayInitialize (char* array, char value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (short* array, short value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (int* array, int value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (long* array, long value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (float* array, float value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (double* array, double value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayInitialize (bool* array, bool value, int count) {\n  if (count > 0) {\n    for (int i = 0; i < count; i++) {\n      array[i] = value;\n    }\n  }\n}\nvoid ArrayFill (char* array, int start, int count, char value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (short* array, int start, int count, short value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (int* array, int start, int count, int value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (long* array, int start, int count, long value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (float* array, int start, int count, float value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (double* array, int start, int count, double value) {\n  ArrayInitialize(array, value, count);\n}\nvoid ArrayFill (bool* array, int start, int count, bool value) {\n  ArrayInitialize(array, value, count);\n}\nint ArrayMaximum (const short* array, int count, int start) {\n  if (count > 0) {\n    short high = SHRT_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const int* array, int count, int start) {\n  if (count > 0) {\n    int high = INT_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const long* array, int count, int start) {\n  if (count > 0) {\n    long high = LONG_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const float* array, int count, int start) {\n  if (count > 0) {\n    float high = FLT_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMaximum (const double* array, int count, int start) {\n  if (count > 0) {\n    double high = DBL_MIN;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] > high) {\n        high = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const short* array, int count, int start) {\n  if (count > 0) {\n    short low = SHRT_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const int* array, int count, int start) {\n  if (count > 0) {\n    int low = INT_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const long* array, int count, int start) {\n  if (count > 0) {\n    long low = LONG_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const float* array, int count, int start) {\n  if (count > 0) {\n    float low = FLT_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayMinimum (const double* array, int count, int start) {\n  if (count > 0) {\n    double low = DBL_MAX;\n    int index = -1;\n    for (int i = 0; i < count; i++) {\n      if (array[i] < low) {\n        low = array[i];\n        index = i;\n      }\n    }\n    return index;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (char** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (char));\n    char* newArr = (char*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (short** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (short));\n    short* newArr = (short*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (int** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (int));\n    int* newArr = (int*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (long** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (long));\n    long* newArr = (long*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (float** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (float));\n    float* newArr = (float*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (double** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (double));\n    double* newArr = (double*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (bool** array, int new_size, int reserve_size) {\n  if (new_size > 0) {\n    int size = new_size * (sizeof (bool));\n    bool* newArr = (bool*)malloc(size);\n    if (*array != NULL) {\n      memcpy(newArr, *array, size);\n      free(*array);\n    }\n    *array = newArr;\n    return new_size;\n  } else {\n    return -1;\n  }\n}\nint ArrayResize (char** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (short** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (int** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (long** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (float** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (double** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nint ArrayResize (bool** array, int new_size) {\n  return ArrayResize(array, new_size, 0);\n}\nbool ArraySort (char* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<char>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (short* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<short>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (int* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<int>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (long* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<long>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (float* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<float>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nbool ArraySort (double* array, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      sort(array, array + count, greater<double>());\n    } else {\n      sort(array, array + count);\n    }\n    return true;\n  } else {\n    return false;\n  }\n}\nint ArrayBsearch (const char* array, char value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const short* array, short value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const int* array, int value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const long* array, long value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const float* array, float value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\nint ArrayBsearch (const double* array, double value, int count, int start, int direction) {\n  if (count > 0) {\n    if (direction == MODE_DESCEND) {\n      for (int i = count - 1; i >= 0; i--) {\n        if (array[i] <= value) {\n          return i;\n        }\n      }\n      return 0;\n    } else {\n      for (int i = 0; i < count; i++) {\n        if (array[i] >= value) {\n          return i;\n        }\n      }\n      return count - 1;\n    }\n  } else {\n    return -1;\n  }\n}\n\nstruct Parameter {\n  char paramType;\n  int paramInt;\n  double paramDouble;\n  bool paramBool;\n  string paramString;\n};\n\nstruct DataInput {\n  int length;\n  double* buffer;\n};\n\nstruct DataOutput {\n  int length;\n  double* buffer;\n};\n\nstruct GlobalVar {\n  datetime time;\n  double value;\n};\n\nstruct ParamInputOutputItem {\n  vector<struct Parameter> paramList;\n  vector<struct DataInput> dataInputList;\n  vector<struct DataOutput> dataOutputList;\n  map<string, int> handleList;\n  map<string, struct GlobalVar> globalVarList;\n};\n\nmap<int, struct ParamInputOutputItem> paramInputOutputList;\nint iFintecheeUID;\nint Bars;\ndouble Point;\nint Digits;\n\nvoid setParam (int uid, const struct Parameter & parameter) {\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    paramInputOutputList[uid].paramList.push_back(parameter);\n  } else {\n    struct ParamInputOutputItem item;\n    item.paramList.push_back(parameter);\n    paramInputOutputList[uid] = item;\n  }\n}\n\ndatetime setGlobalVar (int uid, const string name, double value) {\n  struct GlobalVar globalVar;\n  globalVar.time = TimeCurrent();\n\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    datetime time = paramInputOutputList[uid].globalVarList.count(name) > 0 ? paramInputOutputList[uid].globalVarList[name].time : globalVar.time;\n    paramInputOutputList[uid].globalVarList[name] = globalVar;\n    return time;\n  } else {\n    struct ParamInputOutputItem item;\n    item.globalVarList[name] = globalVar;\n    paramInputOutputList[uid] = item;\n    return globalVar.time;\n  }\n}\n\nbool checkGlobalVar (int uid, const string name) {\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    return paramInputOutputList[uid].globalVarList.count(name) > 0;\n  } else {\n    return false;\n  }\n}\n\ndouble getGlobalVar (int uid, const string name) {\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    return paramInputOutputList[uid].globalVarList.count(name) > 0 ? paramInputOutputList[uid].globalVarList[name].value : 0;\n  } else {\n    return 0;\n  }\n}\n\nbool delGlobalVar (int uid, const string name) {\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    if (paramInputOutputList[uid].globalVarList.count(name) > 0) {\n      paramInputOutputList[uid].globalVarList.erase(name);\n      return true;\n    } else {\n      return false;\n    }\n  } else {\n    return false;\n  }\n}\n\nextern \"C\" {\n\nEMSCRIPTEN_KEEPALIVE\nvoid setParamInt (int uid, int param) {\n  struct Parameter parameter;\n  parameter.paramType = 'i';\n  parameter.paramInt = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setParamDouble (int uid, double param) {\n  struct Parameter parameter;\n  parameter.paramType = 'd';\n  parameter.paramDouble = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setParamBool (int uid, bool param) {\n  struct Parameter parameter;\n  parameter.paramType = 'b';\n  parameter.paramBool = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setParamString (int uid, const char* param) {\n  struct Parameter parameter;\n  parameter.paramType = 's';\n  parameter.paramString = param;\n  setParam(uid, parameter);\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setDataInput (int uid, int length, double* buffer) {\n  struct DataInput dataInput;\n  dataInput.length = length;\n  dataInput.buffer = buffer;\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    paramInputOutputList[uid].dataInputList.push_back(dataInput);\n  } else {\n    struct ParamInputOutputItem item;\n    item.dataInputList.push_back(dataInput);\n    paramInputOutputList[uid] = item;\n  }\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setDataOutput (int uid, int length, double* buffer) {\n  struct DataOutput dataOutput;\n  dataOutput.length = length;\n  dataOutput.buffer = buffer;\n  if (paramInputOutputList.find(uid) != paramInputOutputList.end()) {\n    paramInputOutputList[uid].dataOutputList.push_back(dataOutput);\n  } else {\n    struct ParamInputOutputItem item;\n    item.dataOutputList.push_back(dataOutput);\n    paramInputOutputList[uid] = item;\n  }\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjPrint (void (*f) (int, const char*)) {\n  jPrint = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjSetIndexShift (void (*f) (int, int, int)) {\n  jSetIndexShift = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartID (long (*f) (int)) {\n  jChartID = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartPeriod (int (*f) (int, long)) {\n  jChartPeriod = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjChartSymbol (const char* (*f) (int, long)) {\n  jChartSymbol = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjPeriod (int (*f) (int)) {\n  jPeriod = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjSymbol (const char* (*f) (int)) {\n  jSymbol = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiTimeInit (int (*f) (int, const char*, const char*)) {\n  jiTimeInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiTime (datetime (*f) (int, int, int)) {\n  jiTime = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiOpenInit (int (*f) (int, const char*, const char*)) {\n  jiOpenInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiOpen (double (*f) (int, int, int)) {\n  jiOpen = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiHighInit (int (*f) (int, const char*, const char*)) {\n  jiHighInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiHigh (double (*f) (int, int, int)) {\n  jiHigh = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiLowInit (int (*f) (int, const char*, const char*)) {\n  jiLowInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiLow (double (*f) (int, int, int)) {\n  jiLow = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCloseInit (int (*f) (int, const char*, const char*)) {\n  jiCloseInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiClose (double (*f) (int, int, int)) {\n  jiClose = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiVolumeInit (int (*f) (int, const char*, const char*)) {\n  jiVolumeInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiVolume (long (*f) (int, int, int)) {\n  jiVolume = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiHighest (int (*f) (int, int, const char*, int, int)) {\n  jiHighest = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiLowest (int (*f) (int, int, const char*, int, int)) {\n  jiLowest = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiACInit (int (*f) (int, const char*, const char*)) {\n  jiACInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAC (double (*f) (int, int, int)) {\n  jiAC = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiADXInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiADXInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiADX (double (*f) (int, int, const char*, int)) {\n  jiADX = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAlligatorInit (int (*f) (int, const char*, const char*, int, int, int, int, int, int, const char*, int)) {\n  jiAlligatorInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAlligator (double (*f) (int, int, int, int, int, const char*, int)) {\n  jiAlligator = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAOInit (int (*f) (int, const char*, const char*)) {\n  jiAOInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiAO (double (*f) (int, int, int)) {\n  jiAO = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiATRInit (int (*f) (int, const char*, const char*, int)) {\n  jiATRInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiATR (double (*f) (int, int, int)) {\n  jiATR = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBearsPowerInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiBearsPowerInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBearsPower (double (*f) (int, int, int)) {\n  jiBearsPower = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBandsInit (int (*f) (int, const char*, const char*, int, double, int, int)) {\n  jiBandsInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBands (double (*f) (int, int, int, const char*, int)) {\n  jiBands = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBandsOnArray (double (*f) (int, double*, int, int, double, int, const char*, int)) {\n  jiBandsOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBullsPowerInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiBullsPowerInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiBullsPower (double (*f) (int, int, int)) {\n  jiBullsPower = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCCIInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiCCIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCCI (double (*f) (int, int, int)) {\n  jiCCI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCCIOnArray (double (*f) (int, double*, int, int, int)) {\n  jiCCIOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCustomInit (int (*f) (int, const char*, const char*, const char*, const char*)) {\n  jiCustomInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiCustom (double (*f) (int, int, const char*, int)) {\n  jiCustom = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiDeMarkerInit (int (*f) (int, const char*, const char*, int)) {\n  jiDeMarkerInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiDeMarker (double (*f) (int, int, int)) {\n  jiDeMarker = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiEnvelopesInit (int (*f) (int, const char*, const char*, int, const char*, int, int, double)) {\n  jiEnvelopesInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiEnvelopes (double (*f) (int, int, int, const char*, int)) {\n  jiEnvelopes = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiEnvelopesOnArray (double (*f) (int, double*, int, int, const char*, int, double, const char*, int)) {\n  jiEnvelopesOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiFractalsInit (int (*f) (int, const char*, const char*)) {\n  jiFractalsInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiFractals (double (*f) (int, int, const char*, int)) {\n  jiFractals = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiIchimokuInit (int (*f) (int, const char*, const char*, int, int, int)) {\n  jiIchimokuInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiIchimoku (double (*f) (int, int, int, const char*, int)) {\n  jiIchimoku = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMAInit (int (*f) (int, const char*, const char*, int, int, int, int)) {\n  jiMAInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMA (double (*f) (int, int, int, const char*, int)) {\n  jiMA = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMAOnArray (double (*f) (int, double*, int, int, int, const char*, int)) {\n  jiMAOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMACDInit (int (*f) (int, const char*, const char*, int, int, int, int)) {\n  jiMACDInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMACD (double (*f) (int, int, const char*, int)) {\n  jiMACD = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMFIInit (int (*f) (int, const char*, const char*, int)) {\n  jiMFIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMFI (double (*f) (int, int, int)) {\n  jiMFI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMomentumInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiMomentumInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMomentum (double (*f) (int, int, int)) {\n  jiMomentum = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiMomentumOnArray (double (*f) (int, double*, int, int, int)) {\n  jiMomentumOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRSIInit (int (*f) (int, const char*, const char*, int, int)) {\n  jiRSIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRSI (double (*f) (int, int, int)) {\n  jiRSI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRSIOnArray (double (*f) (int, double*, int, int, int)) {\n  jiRSIOnArray = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRVIInit (int (*f) (int, const char*, const char*, int)) {\n  jiRVIInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiRVI (double (*f) (int, int, const char*, int)) {\n  jiRVI = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiSARInit (int (*f) (int, const char*, const char*, double, double)) {\n  jiSARInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiSAR (double (*f) (int, int, int)) {\n  jiSAR = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiStochasticInit (int (*f) (int, const char*, const char*, int, int, int, const char*)) {\n  jiStochasticInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiStochastic (double (*f) (int, int, const char*, int)) {\n  jiStochastic = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiWPRInit (int (*f) (int, const char*, const char*, int)) {\n  jiWPRInit = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjiWPR (double (*f) (int, int, int)) {\n  jiWPR = f;\n}\nEMSCRIPTEN_KEEPALIVE\nvoid setjMarketInfo (double (*f) (int, const char*, int)) {\n  jMarketInfo = f;\n}\n\n}\n\ntemplate <class Type, class... Types>\nvoid Print (const Type & arg, const Types &... args) {\n  stringstream s;\n  s << arg;\n  ((s << args), ..., (s << endl));\n  jPrint(iFintecheeUID, s.str().c_str());\n}\n\n// todo\ntemplate <class Type, class... Types>\nvoid Comment (const Type & arg, const Types &... args) {\n  stringstream s;\n  s << arg;\n  ((s << args), ..., (s << endl));\n  jPrint(iFintecheeUID, s.str().c_str());\n}\n\n// todo\ntemplate <class Type, class... Types>\nvoid Alert (const Type & arg, const Types &... args) {\n  stringstream s;\n  s << arg;\n  ((s << args), ..., (s << endl));\n  jPrint(iFintecheeUID, s.str().c_str());\n}\n\nbool PlaySound (const string name) {\n  Print(\"Playing: \", name);\n  return true;\n}\n\nvoid SetIndexShift (int index, int shift) {\n  jSetIndexShift(iFintecheeUID, index, shift);\n}\n\nlong ChartID () {\n  return jChartID(iFintecheeUID);\n}\n\nENUM_TIMEFRAMES ChartPeriod (long chart_id) {\n  return (ENUM_TIMEFRAMES)jChartPeriod(iFintecheeUID, chart_id);\n}\nENUM_TIMEFRAMES ChartPeriod () {\n  return ChartPeriod(0);\n}\n\nstring ChartSymbol (long chart_id) {\n  string symbol(jChartSymbol(iFintecheeUID, chart_id));\n  return symbol;\n}\nstring ChartSymbol () {\n  return ChartSymbol(0);\n}\n\nENUM_TIMEFRAMES Period () {\n  return (ENUM_TIMEFRAMES)jPeriod(iFintecheeUID);\n}\n\nstring Symbol () {\n  string symbol(jSymbol(iFintecheeUID));\n  return symbol;\n}\n\ndatetime iTime (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiTime(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndatetime iTime (long symbol, int timeframe, int shift) {\n  return iTime(\"\", timeframe, shift);\n}\ndouble iOpen (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiOpenInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiOpen(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iOpen (long symbol, int timeframe, int shift) {\n  return iOpen(\"\", timeframe, shift);\n}\ndouble iHigh (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiHighInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiHigh(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iHigh (long symbol, int timeframe, int shift) {\n  return iHigh(\"\", timeframe, shift);\n}\ndouble iLow (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiLowInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiLow(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iLow (long symbol, int timeframe, int shift) {\n  return iLow(\"\", timeframe, shift);\n}\ndouble iClose (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiCloseInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiClose(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iClose (long symbol, int timeframe, int shift) {\n  return iClose(\"\", timeframe, shift);\n}\nlong iVolume (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiVolumeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiVolume(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\nlong iVolume (long symbol, int timeframe, int shift) {\n  return iVolume(\"\", timeframe, shift);\n}\nint iHighest (const string symbol, int timeframe, int type, int count, int start) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiHighest(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start);\n}\nint iHighest (long symbol, int timeframe, int type, int count, int start) {\n  return iHighest(\"\", timeframe, type, count, start);\n}\nint Highest (const string symbol, int timeframe, int type, int count, int start) {\n  return iHighest (symbol, timeframe, type, count, start);\n}\nint Highest (long symbol, int timeframe, int type, int count, int start) {\n  return iHighest(\"\", timeframe, type, count, start);\n}\nint iLowest (const string symbol, int timeframe, int type, int count, int start) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"Chart_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiLowest(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start);\n}\nint iLowest (long symbol, int timeframe, int type, int count, int start) {\n  return iLowest(\"\", timeframe, type, count, start);\n}\nint Lowest (const string symbol, int timeframe, int type, int count, int start) {\n  return iLowest (symbol, timeframe, type, count, start);\n}\nint Lowest (long symbol, int timeframe, int type, int count, int start) {\n  return iLowest(\"\", timeframe, type, count, start);\n}\n\ndouble iAC (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iAC_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiACInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiAC(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iAC (long symbol, int timeframe, int shift) {\n  return iAC(\"\", timeframe, shift);\n}\n\ndouble iADX (const string symbol, int timeframe, int period, int applied_price, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iADX_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiADXInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiADX(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_ADX), shift);\n}\ndouble iADX (long symbol, int timeframe, int period, int applied_price, int mode, int shift) {\n  return iADX(\"\", timeframe, period, applied_price, mode, shift);\n}\n\ndouble iAlligator (\n  const string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift,\n  int ma_method, int applied_price, int mode, int shift) {\n\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iAlligator_\") + symbol + string(\"_\") + string(tf) + string(\"_\") +\n    to_string(jaw_period) + string(\"_\") + to_string(jaw_shift) + string(\"_\") + to_string(teeth_period) + string(\"_\") + to_string(teeth_shift) + string(\"_\") + to_string(lips_period) + string(\"_\") + to_string(lips_shift) + string(\"_\") + to_string(ma_method) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiAlligatorInit(iFintecheeUID, symbol.c_str(), tf, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, convertMAMethod(ma_method), applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiAlligator(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], jaw_shift, teeth_shift, lips_shift, convertMode(mode, INDI_ALLIGATOR), shift);\n}\ndouble iAlligator (\n  long symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift,\n  int ma_method, int applied_price, int mode, int shift) {\n  return iAlligator(\"\", timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price, mode, shift);\n}\n\ndouble iAO (const string symbol, int timeframe, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iAO_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiAOInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiAO(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iAO (long symbol, int timeframe, int shift) {\n  return iAO(\"\", timeframe, shift);\n}\n\ndouble iATR (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iATR_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiATRInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiATR(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iATR (long symbol, int timeframe, int period, int shift) {\n  return iATR(\"\", timeframe, period, shift);\n}\n\ndouble iBearsPower (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iBearsPower_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiBearsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiBearsPower(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iBearsPower (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iBearsPower(\"\", timeframe, period, applied_price, shift);\n}\n\ndouble iBands (const string symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iBands_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(deviation) + string(\"_\") + to_string(bands_shift) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiBandsInit(iFintecheeUID, symbol.c_str(), tf, period, deviation, bands_shift, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiBands(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], bands_shift, convertMode(mode, INDI_BANDS), shift);\n}\ndouble iBands (long symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) {\n  return iBands(\"\", timeframe, period, deviation, bands_shift, applied_price, mode, shift);\n}\ndouble iBandsOnArray (double* array, int total, int period, double deviation, int bands_shift, int mode, int shift) {\n  return jiBandsOnArray(iFintecheeUID, array, total, period, deviation, bands_shift, convertMode(mode, INDI_BANDS), shift);\n}\n\ndouble iBullsPower (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iBullsPower_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiBullsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiBullsPower(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iBullsPower (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iBullsPower(\"\", timeframe, period, applied_price, shift);\n}\n\ndouble iCCI (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iCCI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiCCIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiCCI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iCCI (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iCCI(\"\", timeframe, period, applied_price, shift);\n}\ndouble iCCIOnArray (double* array, int total, int period, int shift) {\n  return jiCCIOnArray(iFintecheeUID, array, total, period, shift);\n}\n\ntemplate<class...Ts>\ndouble iCustom (const string symbol, int timeframe, const string name, Ts&&... args) {\n  const char* tf = convertTimeFrame(timeframe);\n  stringstream s;\n  const char* mode;\n  int shift;\n  int length = sizeof...(args);\n\n  int i = 0;\n  auto loop = [&] (auto && input) {\n    if (i >= 0 && i < length - 2) {\n      s << input << \"|||\";\n    } else if (i == length - 2) {\n      mode = (const char*)input;\n    } else if (i == length - 1) {\n      shift = (int)input;\n    }\n    i++;\n  };\n\n  (loop(args), ...);\n\n  string strID = string(\"iCustom_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + string(name) + string(\"_\") + s.str();\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiCustomInit(iFintecheeUID, symbol.c_str(), tf, name.c_str(), s.str().c_str());\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiCustom(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], mode, shift);\n}\ntemplate<class...Ts>\ndouble iCustom (long symbol, int timeframe, const string name, Ts&&... args) {\n  return iCustom(\"\", timeframe, name, args...);\n}\n\ndouble iDeMarker (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iDeMarker_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiDeMarkerInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiDeMarker(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iDeMarker (long symbol, int timeframe, int period, int shift) {\n  return iDeMarker(\"\", timeframe, period, shift);\n}\n\ndouble iEnvelopes (const string symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iEnvelopes_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(ma_period) + string(\"_\") + to_string(ma_method) + string(\"_\") + to_string(ma_shift) + string(\"_\") + to_string(applied_price) + string(\"_\") + to_string(deviation);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiEnvelopesInit(iFintecheeUID, symbol.c_str(), tf, ma_period, convertMAMethod(ma_method), ma_shift, applied_price, deviation);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiEnvelopes(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], ma_shift, convertMode(mode, INDI_ENVELOPES), shift);\n}\ndouble iEnvelopes (long symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) {\n  return iEnvelopes(\"\", timeframe, ma_period, ma_method, ma_shift, applied_price, deviation, mode, shift);\n}\ndouble iEnvelopesOnArray (double* array, int total, int ma_period, int ma_method, int ma_shift, double deviation, int mode, int shift) {\n  return jiEnvelopesOnArray(iFintecheeUID, array, total, ma_period, convertMAMethod(ma_method), ma_shift, deviation, convertMode(mode, INDI_ENVELOPES), shift);\n}\n\ndouble iFractals (const string symbol, int timeframe, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iFractals_\") + symbol + string(\"_\") + string(tf);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiFractalsInit(iFintecheeUID, symbol.c_str(), tf);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiFractals(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_FRACTALS), shift);\n}\ndouble iFractals (long symbol, int timeframe, int mode, int shift) {\n  return iFractals(\"\", timeframe, mode, shift);\n}\n\ndouble iIchimoku (const string symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iIchimoku_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(tenkan_sen) + string(\"_\") + to_string(kijun_sen) + string(\"_\") + to_string(senkou_span_b);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n   int handle = jiIchimokuInit(iFintecheeUID, symbol.c_str(), tf, tenkan_sen, kijun_sen, senkou_span_b);\n   paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  if (mode == MODE_TENKANSEN) {\n   return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift);\n  } else if (mode == MODE_KIJUNSEN) {\n   return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift);\n  } else if (mode == MODE_SENKOUSPANA) {\n   return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift);\n  } else if (mode == MODE_SENKOUSPANB) {\n   return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift);\n  } else {\n   return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], -kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift);\n  }\n}\ndouble iIchimoku (long symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) {\n  return iIchimoku(\"\", timeframe, tenkan_sen, kijun_sen, senkou_span_b, mode, shift);\n}\n\ndouble iMA (const string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMA_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(ma_period) + string(\"_\") + to_string(ma_shift) + string(\"_\") + to_string(ma_method) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiMAInit(iFintecheeUID, symbol.c_str(), tf, ma_period, ma_shift, ma_method, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiMA(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], ma_shift, convertMAMethod(ma_method), shift);\n}\ndouble iMA (long symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) {\n  return iMA(\"\", timeframe, ma_period, ma_shift, ma_method, applied_price, shift);\n}\ndouble iMAOnArray (double* array, int total, int ma_period, int ma_shift, int ma_method, int shift) {\n  return jiMAOnArray(iFintecheeUID, array, total, ma_period, ma_shift, convertMAMethod(ma_method), shift);\n}\n\ndouble iMACD (const string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMACD_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(fast_ema_period) + string(\"_\") + to_string(slow_ema_period) + string(\"_\") + to_string(signal_period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiMACDInit(iFintecheeUID, symbol.c_str(), tf, fast_ema_period, slow_ema_period, signal_period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiMACD(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_MACD), shift);\n}\ndouble iMACD (long symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) {\n  return iMACD(\"\", timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, mode, shift);\n}\n\ndouble iMFI (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMFI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiMFIInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiMFI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iMFI (long symbol, int timeframe, int period, int shift) {\n  return iMFI(\"\", timeframe, period, shift);\n}\n\ndouble iMomentum (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iMomentum_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiMomentumInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiMomentum(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iMomentum (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iMomentum(\"\", timeframe, period, applied_price, shift);\n}\ndouble iMomentumOnArray (double* array, int total, int period, int shift) {\n  return jiMomentumOnArray(iFintecheeUID, array, total, period, shift);\n}\n\ndouble iRSI (const string symbol, int timeframe, int period, int applied_price, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iRSI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period) + string(\"_\") + to_string(applied_price);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiRSIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiRSI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iRSI (long symbol, int timeframe, int period, int applied_price, int shift) {\n  return iRSI(\"\", timeframe, period, applied_price, shift);\n}\ndouble iRSIOnArray (double* array, int total, int period, int shift) {\n  return jiRSIOnArray(iFintecheeUID, array, total, period, shift);\n}\n\ndouble iRVI (const string symbol, int timeframe, int period, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iRVI_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiRVIInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiRVI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_RVI), shift);\n}\ndouble iRVI (long symbol, int timeframe, int period, int mode, int shift) {\n  return iRVI(\"\", timeframe, period, mode, shift);\n}\n\ndouble iSAR (const string symbol, int timeframe, double step, double maximum, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iSAR_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(step) + string(\"_\") + to_string(maximum);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiSARInit(iFintecheeUID, symbol.c_str(), tf, step, maximum);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiSAR(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iSAR (long symbol, int timeframe, double step, double maximum, int shift) {\n  return iSAR(\"\", timeframe, step, maximum, shift);\n}\n\ndouble iStochastic (const string symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iStochastic_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(Kperiod) + string(\"_\") + to_string(Dperiod) + string(\"_\") + to_string(slowing) + string(\"_\") + to_string(method);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiStochasticInit(iFintecheeUID, symbol.c_str(), tf, Kperiod, Dperiod, slowing, convertMAMethod(method));\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiStochastic(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_STOCHASTIC), shift);\n}\ndouble iStochastic (long symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) {\n  return iStochastic(\"\", timeframe, Kperiod, Dperiod, slowing, method, price_field, mode, shift);\n}\n\ndouble iWPR (const string symbol, int timeframe, int period, int shift) {\n  const char* tf = convertTimeFrame(timeframe);\n  string strID = string(\"iWPR_\") + symbol + string(\"_\") + string(tf) + string(\"_\") + to_string(period);\n  if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) {\n    int handle = jiWPRInit(iFintecheeUID, symbol.c_str(), tf, period);\n    paramInputOutputList[iFintecheeUID].handleList[strID] = handle;\n  }\n  return jiWPR(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift);\n}\ndouble iWPR (long symbol, int timeframe, int period, int shift) {\n  return iWPR(\"\", timeframe, period, shift);\n}\n\n// todo, check whether the logic about the return value is the same as MQL4\ndatetime GlobalVariableSet (const string name, double value) {\n  return setGlobalVar(iFintecheeUID, name, value);\n}\n\nbool GlobalVariableCheck (const string name) {\n  return checkGlobalVar(iFintecheeUID, name);\n}\n\ndouble GlobalVariableGet (const string name) {\n  return getGlobalVar(iFintecheeUID, name);\n}\n\nbool GlobalVariableDel (const string name) {\n  return delGlobalVar(iFintecheeUID, name);\n}\n\ndouble MarketInfo (const string symbol, int type) {\n  return jMarketInfo(iFintecheeUID, symbol.c_str(), type);\n}\ndouble MarketInfo (long symbol, int type) {\n  return MarketInfo(\"\", type);\n}\n\n// Not compatible with MQL\n// Deprecated\nbool SCompareL (const string str, long l) {\n  return jSCompareL(iFintecheeUID, str.c_str(), l);\n}\n\n// Not compatible with MQL\nbool VeriSig (const string fintechee_data, const string fintechee_signature, const string fintechee_public_key, const string application_public_key) {\n  string data = fintechee_data;\n  string signature = fintechee_signature;\n  string publicKey = fintechee_public_key;\n  string appPublicKey = application_public_key;\n  data.erase(std::remove(data.begin(), data.end(), '\\n'), data.end());\n  signature.erase(std::remove(signature.begin(), signature.end(), '\\n'), signature.end());\n  publicKey.erase(std::remove(publicKey.begin(), publicKey.end(), '\\n'), publicKey.end());\n  appPublicKey.erase(std::remove(appPublicKey.begin(), appPublicKey.end(), '\\n'), appPublicKey.end());\n  data = StringTrimLeft(StringTrimRight(data));\n  signature = StringTrimLeft(StringTrimRight(signature));\n  publicKey = StringTrimLeft(StringTrimRight(publicKey));\n  appPublicKey = StringTrimLeft(StringTrimRight(appPublicKey));\n\n  int dataLen = StringLen(data);\n  int signatureLen = StringLen(signature);\n  int publicKeyLen = StringLen(publicKey);\n  int appPublicKeyLen = StringLen(appPublicKey);\n  if (dataLen == 0 || signatureLen == 0 || publicKeyLen == 0 || appPublicKeyLen == 0) return false;\n  if (publicKeyLen != appPublicKeyLen) return false;\n  if (StringCompare(publicKey, appPublicKey) != 0) return false;\n  bool res = jVeriSig(iFintecheeUID, data.c_str(), signature.c_str(), publicKey.c_str());\n\n  if (res) {\n    std::vector<string> arr;\n    std::stringstream ss(data);\n\n    string s;\n    while (std::getline(ss, s, ',')) {\n      arr.push_back(s);\n    }\n\n    if (0 < arr.size()) {\n      if (std::stoll(arr[0]) >= TimeCurrent()) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "EA/Plugin-for-MQL/plugin_for_mql.js",
    "content": "registerEA(\n\t\t\"plugin_for_mql\",\n\t\t\"mql_plugin to make MQL-based programs runnable on Fintechee(v1.06)\",\n\t\t[],\n\t\tfunction (context) { // Init()\n\t\t\tif (typeof window.pluginForMql != \"undefined\") {\n\t\t\t\twindow.pluginForMql.init()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\twindow.pluginForMql = {\n\t\t\t\tcreateMqlIndicator: function (definition) {\n\t\t\t\t\timportBuiltInIndicator(\n\t\t\t\t\t\tdefinition.name,\n\t\t\t\t\t\tdefinition.description,\n\t\t\t\t\t\tfunction (context) {\n\t\t\t\t\t\t\tvar indiName = getIndiName(context)\n\t\t\t\t\t\t\tif (typeof window.mqlIndicators == \"undefined\" || typeof window.mqlIndicators[indiName] == \"undefined\") {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar indiObj = window.mqlIndicators[indiName]\n\n\t\t\t\t\t\t\tvar uid = null\n\t\t\t\t\t\t\tif (typeof context.uid == \"undefined\") {\n\t\t\t\t\t\t\t\tuid = window.mqlIndiUID++\n\t\t\t\t\t\t\t\tcontext.uid = uid\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tuid = context.uid\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar calculatedLength = 0\n\t\t\t\t\t\t\tif (typeof window.mqlIndicatorsBuffer[uid + \"\"] != \"undefined\") {\n\t\t\t\t\t\t\t\tcalculatedLength = getCalculatedLength(context)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar currDefinition = indiObj.definition\n\n\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\tvar nByteString = 1\n\t\t\t\t\t\t\tvar length = 1\n\t\t\t\t\t\t\tvar buffer = null\n\n\t\t\t\t\t\t\tif (calculatedLength == 0) {\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.parameters) {\n\t\t\t\t\t\t\t\t\tif (currDefinition.parameters[i].type == PARAMETER_TYPE.INTEGER) {\n\t\t\t\t\t\t\t\t\t\tindiObj.setParamInt(uid, getIndiParameter(context, currDefinition.parameters[i].name))\n\t\t\t\t\t\t\t\t\t} else if (currDefinition.parameters[i].type == PARAMETER_TYPE.NUMBER) {\n\t\t\t\t\t\t\t\t\t\tindiObj.setParamDouble(uid, getIndiParameter(context, currDefinition.parameters[i].name))\n\t\t\t\t\t\t\t\t\t} else if (currDefinition.parameters[i].type == PARAMETER_TYPE.BOOLEAN) {\n\t\t\t\t\t\t\t\t\t\tindiObj.setParamBool(uid, getIndiParameter(context, currDefinition.parameters[i].name))\n\t\t\t\t\t\t\t\t\t} else if (currDefinition.parameters[i].type == PARAMETER_TYPE.STRING) {\n\t\t\t\t\t\t\t\t\t\tvar indiStrParam = getIndiParameter(context, currDefinition.parameters[i].name)\n\t\t\t\t\t\t\t\t\t\tif (indiStrParam == null) {\n\t\t\t\t\t\t\t\t\t\t\tindiStrParam = \"\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tindiObj.setParamString(uid, indiStrParam)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar dataLen = getDataInput(context, 0).length\n\t\t\t\t\t\t\tvar buffLen = dataLen * 2\n\t\t\t\t\t\t\tvar ratesTotal = dataLen\n\t\t\t\t\t\t\tvar prevCalc = calculatedLength\n\n\t\t\t\t\t\t\tvar buffObj = null\n\n\t\t\t\t\t\t\tif (typeof window.mqlIndicatorsBuffer[uid + \"\"] == \"undefined\") {\n\t\t\t\t\t\t\t\tvar brokerName = getBrokerNameByContext(context)\n\t\t\t\t\t\t\t\tvar accountId = getAccountIdByContext(context)\n\t\t\t\t\t\t\t\tvar symbolName = getChartSymbolNameByContext(context)\n\t\t\t\t\t\t\t\tvar timeFrame = getChartTimeFrameByContext(context)\n\n\t\t\t\t\t\t\t\twindow.mqlIndicatorsBuffer[uid + \"\"] = {\n\t\t\t\t\t\t\t\t\tname: currDefinition.name,\n\t\t\t\t\t\t\t\t\tcontext: context,\n\t\t\t\t\t\t\t\t\tbrokerName: brokerName,\n\t\t\t\t\t\t\t\t\taccountId: accountId,\n\t\t\t\t\t\t\t\t\tsymbolName: symbolName,\n\t\t\t\t\t\t\t\t\ttimeFrame: timeFrame,\n\t\t\t\t\t\t\t\t\tchartId: getChartHandleByContext(context),\n\t\t\t\t\t\t\t\t\tsymbol: getSymbolInfo(brokerName, accountId, symbolName),\n\t\t\t\t\t\t\t\t\tbufferLen: buffLen,\n\t\t\t\t\t\t\t\t\tdataInput: [],\n\t\t\t\t\t\t\t\t\tdataOutput: [],\n\t\t\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t\t\t\t\tmTime: 0\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbuffObj = window.mqlIndicatorsBuffer[uid + \"\"]\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataInput) {\n\t\t\t\t\t\t\t\t\tvar dataInput = getDataInput(context, currDefinition.dataInput[i].index)\n\n\t\t\t\t\t\t\t\t\tbuffer = indiObj.module._malloc(buffLen * nByteDouble)\n\n\t\t\t\t\t\t\t\t\tfor (var j = 0; j < dataInput.length; j++) {\n\t\t\t\t\t\t\t\t\t\tindiObj.module.setValue(buffer + j * nByteDouble, dataInput[j], \"double\")\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tindiObj.setDataInput(uid, buffLen, buffer)\n\t\t\t\t\t\t\t\t\tbuffObj.dataInput.push(buffer)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataOutput) {\n\t\t\t\t\t\t\t\t\tbuffer = indiObj.module._malloc(buffLen * nByteDouble)\n\n\t\t\t\t\t\t\t\t\tindiObj.setDataOutput(uid, buffLen, buffer)\n\t\t\t\t\t\t\t\t\tbuffObj.dataOutput.push(buffer)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tindiObj.onCalc(uid, ratesTotal, prevCalc, 10000, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed))\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataOutput) {\n\t\t\t\t\t\t\t\t\tvar dataOutputMql = buffObj.dataOutput[i]\n\t\t\t\t\t\t\t\t\tvar dataOutput = getDataOutput(context, currDefinition.dataOutput[i].name)\n\n\t\t\t\t\t\t\t\t\tfor (var j = 0; j < dataOutput.length; j++) {\n\t\t\t\t\t\t\t\t\t\tdataOutput[j] = indiObj.module.getValue(dataOutputMql + j * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (dataLen == window.mqlIndicatorsBuffer[uid + \"\"].bufferLen) {\n\t\t\t\t\t\t\t\tbuffObj = window.mqlIndicatorsBuffer[uid + \"\"]\n\n\t\t\t\t\t\t\t\tbuffObj.time = new Date().getTime()\n\t\t\t\t\t\t\t\tbuffObj.bufferLen = buffLen\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataInput) {\n\t\t\t\t\t\t\t\t\tvar dataInput = getDataInput(context, currDefinition.dataInput[i].index)\n\n\t\t\t\t\t\t\t\t\tbuffer = indiObj.module._malloc(buffLen * nByteDouble)\n\n\t\t\t\t\t\t\t\t\tfor (var j = 0; j < dataInput.length; j++) {\n\t\t\t\t\t\t\t\t\t\tindiObj.module.setValue(buffer + j * nByteDouble, dataInput[j], \"double\")\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tindiObj.setDataInput(uid, buffLen, buffer)\n\t\t\t\t\t\t\t\t\tindiObj.module._free(buffObj.dataInput[i])\n\t\t\t\t\t\t\t\t\tbuffObj.dataInput.push(buffer)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataOutput) {\n\t\t\t\t\t\t\t\t\tbuffer = indiObj.module._malloc(buffLen * nByteDouble)\n\n\t\t\t\t\t\t\t\t\tfor (var j = 0; j < dataOutput.length; j++) {\n\t\t\t\t\t\t\t\t\t\tindiObj.module.setValue(buffer + j * nByteDouble, dataOutput[j], \"double\")\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tindiObj.setDataOutput(uid, buffLen, buffer)\n\t\t\t\t\t\t\t\t\tindiObj.module._free(buffObj.dataOutput[i])\n\t\t\t\t\t\t\t\t\tbuffObj.dataOutput.push(buffer)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar cData = getDataFromIndi(context, buffObj.chartId, DATA_NAME.CLOSE)\n\t\t\t\t\t\t\t\tindiObj.onCalc(uid, ratesTotal, prevCalc, cData.length, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed))\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataOutput) {\n\t\t\t\t\t\t\t\t\tvar dataOutputMql = buffObj.dataOutput[i]\n\t\t\t\t\t\t\t\t\tvar dataOutput = getDataOutput(context, currDefinition.dataOutput[i].name)\n\n\t\t\t\t\t\t\t\t\tdataOutput[dataOutput.length - 1] = indiObj.module.getValue(dataOutputMql + (dataOutput.length - 1) * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbuffObj = window.mqlIndicatorsBuffer[uid + \"\"]\n\n\t\t\t\t\t\t\t\tbuffObj.time = new Date().getTime()\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataInput) {\n\t\t\t\t\t\t\t\t\tvar dataInputMql = buffObj.dataInput[i]\n\t\t\t\t\t\t\t\t\tvar dataInput = getDataInput(context, currDefinition.dataInput[i].index)\n\n\t\t\t\t\t\t\t\t\tindiObj.module.setValue(dataInputMql + (dataInput.length - 1) * nByteDouble, dataInput[dataInput.length - 1], \"double\")\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar cData = getDataFromIndi(context, buffObj.chartId, DATA_NAME.CLOSE)\n\t\t\t\t\t\t\t\tindiObj.onCalc(uid, ratesTotal, prevCalc, cData.length, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed))\n\n\t\t\t\t\t\t\t\tfor (var i in currDefinition.dataOutput) {\n\t\t\t\t\t\t\t\t\tvar dataOutputMql = buffObj.dataOutput[i]\n\t\t\t\t\t\t\t\t\tvar dataOutput = getDataOutput(context, currDefinition.dataOutput[i].name)\n\n\t\t\t\t\t\t\t\t\tdataOutput[dataOutput.length - 1] = indiObj.module.getValue(dataOutputMql + (dataOutput.length - 1) * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfor (var i in currDefinition.parameters) {\n\t\t\t\t\t\t\t\tif (currDefinition.parameters[i].name == \"shift\") {\n\t\t\t\t\t\t\t\t\tvar shift = getIndiParameter(context, \"shift\")\n\t\t\t\t\t\t\t\t\tif (shift != null && calculatedLength == 0) {\n\t\t\t\t\t\t\t\t\t\tfor (var j in currDefinition.dataOutput) {\n\t\t\t\t\t\t\t\t\t\t\tsetIndiShift(context, currDefinition.dataOutput[j].name, shift)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefinition.parameters,\n\t\t\t\t\t\tdefinition.dataInput,\n\t\t\t\t\t\tdefinition.dataOutput,\n\t\t\t\t\t\tdefinition.whereToRender\n\t\t\t\t\t) // registerIndicator\n\t\t\t\t},\n\t\t\t\tremoveMqlIndicator: function (name) {\n\t\t\t\t\tunregisterIndicator(name)\n\n\t\t\t\t\tif (typeof window.mqlIndicators == \"undefined\" || typeof window.mqlIndicatorsBuffer == \"undefined\") return\n\n\t\t\t\t\tdelete window.mqlIndicators[name]\n\t\t\t\t\tfor (var i in window.mqlIndicatorsBuffer) {\n\t\t\t\t\t\tif (window.mqlIndicatorsBuffer[i].name == name) {\n\t\t\t\t\t\t\tdelete window.mqlIndicatorsBuffer[i]\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tloadMqlIndicator: function (definition) {\n\t\t\t\t\treturn new Promise(function (rs, rj) {\n\t\t\t\t\t\tvar tags = document.getElementsByTagName(\"script\")\n\t\t\t\t\t\tfor (var i = tags.length - 1; i >= 0; i--) {\n\t\t\t\t\t\t\tif (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == definition.url) {\n\t\t\t\t\t\t\t\ttags[i].parentNode.removeChild(tags[i])\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar scriptPromise = new Promise(function (resolve, reject) {\n\t\t\t\t\t\t  var script = document.createElement(\"script\")\n\t\t\t\t\t\t  document.body.appendChild(script)\n\t\t\t\t\t\t  script.onload = resolve\n\t\t\t\t\t\t  script.onerror = reject\n\t\t\t\t\t\t  script.async = true\n\t\t\t\t\t\t  script.src = definition.url\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tscriptPromise.then(function () {\n\t\t\t\t\t\t\tIndiPlugIn().then(function (Module) {\n\t\t\t\t\t\t\t\tif (typeof window.mqlIndicators == \"undefined\") {\n\t\t\t\t\t\t\t\t\twindow.mqlIndicators = []\n\t\t\t\t\t\t\t\t\twindow.mqlIndicatorsBuffer = []\n\t\t\t\t\t\t\t\t\twindow.mqlIndiUID = 0\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar jPrint = Module.addFunction(function (uid, s) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tprintMessage(window.mqlIndicators[obj.name].module.UTF8ToString(s))\n\t\t\t\t\t\t\t\t}, \"vii\")\n\t\t\t\t\t\t\t\tvar jSetIndexShift = Module.addFunction(function (uid, index, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tsetIndiShift(obj.context, index, shift)\n\t\t\t\t\t\t\t\t}, \"viii\")\n\t\t\t\t\t\t\t\tvar jChartID = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t  return window.mqlIndicatorsBuffer[uid + \"\"].chartId\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jChartPeriod = Module.addFunction(function (uid, chart_id) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tif (chart_id == 0) {\n\t\t\t\t\t\t\t\t\t\treturn obj.convertTimeFrame(obj.timeFrame)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn obj.convertTimeFrame(getChartTimeFrame(chart_id))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iii\")\n\t\t\t\t\t\t\t\tvar jChartSymbol = Module.addFunction(function (uid, chart_id) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = \"\"\n\t\t\t\t\t\t\t\t\tif (chart_id == 0) {\n\t\t\t\t\t\t\t\t\t\tsymbolName = obj.symbolName\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tsymbolName = getChartSymbolName(chart_id)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlIndicators[obj.name].module.lengthBytesUTF8(symbolName) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlIndicators[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlIndicators[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"iii\")\n\t\t\t\t\t\t\t\tvar jPeriod = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn obj.convertTimeFrame(obj.timeFrame)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jSymbol = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = obj.symbolName\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlIndicators[obj.name].module.lengthBytesUTF8(symbolName) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlIndicators[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlIndicators[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jiTimeInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandleFromIndi(obj.context, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiTime = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, \"Time\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiOpenInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandleFromIndi(obj.context, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiOpen = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, \"Open\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiHighInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandleFromIndi(obj.context, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiHigh = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, \"High\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiLowInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandleFromIndi(obj.context, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiLow = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, \"Low\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiCloseInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandleFromIndi(obj.context, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiClose = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, \"Close\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiVolumeInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandleFromIndi(obj.context, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiVolume = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, \"Volume\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiHighest = Module.addFunction(function (uid, chartHandle, mode, count, start) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, md)\n\t\t\t\t\t\t\t\t\tvar highest = -Number.MAX_VALUE\n\t\t\t\t\t\t\t\t\tvar idx = -1\n\t\t\t\t\t\t\t\t\tfor (var i = start; i < start + count && i >= 0 && i < arr.length; i++) {\n\t\t\t\t\t\t\t\t\t\tif (arr[arr.length - i - 1] > highest) {\n\t\t\t\t\t\t\t\t\t\t\thighest = arr[arr.length - i - 1]\n\t\t\t\t\t\t\t\t\t\t\tidx = i\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn idx\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiLowest = Module.addFunction(function (uid, chartHandle, mode, count, start) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, chartHandle, md)\n\t\t\t\t\t\t\t\t\tvar lowest = Number.MAX_VALUE\n\t\t\t\t\t\t\t\t\tvar idx = -1\n\t\t\t\t\t\t\t\t\tfor (var i = start; i < start + count && i >= 0 && i < arr.length; i++) {\n\t\t\t\t\t\t\t\t\t\tif (arr[arr.length - i - 1] < lowest) {\n\t\t\t\t\t\t\t\t\t\t\tlowest = arr[arr.length - i - 1]\n\t\t\t\t\t\t\t\t\t\t\tidx = i\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn idx\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiACInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"ac\", [])\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiAC = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arrUp = getDataFromIndi(obj.context, indiHandle, \"up\")\n\t\t\t\t\t\t\t\t\tvar arrDown = getDataFromIndi(obj.context, indiHandle, \"down\")\n\t\t\t\t\t\t\t\t\treturn arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiADXInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"adx_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiADX = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiAlligatorInit = Module.addFunction(function (uid, symbol, timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"alligator_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"jawsPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: jaw_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"jawsShift\",\n\t\t\t\t\t\t\t\t\t\tvalue: jaw_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"teethPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: teeth_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"teethShift\",\n\t\t\t\t\t\t\t\t\t\tvalue: teeth_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"lipsPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: lips_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"lipsShift\",\n\t\t\t\t\t\t\t\t\t\tvalue: lips_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"method\",\n\t\t\t\t\t\t\t\t\t\tvalue: method\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiAlligator = Module.addFunction(function (uid, indiHandle, jaw_shift, teeth_shift, lips_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\tif (md == \"jaws\") {\n\t\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t\t} else if (md == \"teeth\") {\n\t\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"diiiiiii\")\n\t\t\t\t\t\t\t\tvar jiAOInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"ao\", [])\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiAO = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arrUp = getDataFromIndi(obj.context, indiHandle, \"up\")\n\t\t\t\t\t\t\t\t\tvar arrDown = getDataFromIndi(obj.context, indiHandle, \"down\")\n\t\t\t\t\t\t\t\t\treturn arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiATRInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"atr\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiATR = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"atr\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiBearsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"bears_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiBearsPower = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"bears\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiBandsInit = Module.addFunction(function (uid, symbol, timeframe, period, deviation, bands_shift, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"bands_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"deviations\",\n\t\t\t\t\t\t\t\t\t    value: deviation,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"shift\",\n\t\t\t\t\t\t\t\t\t    value: bands_shift,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"method\",\n\t\t\t\t\t\t\t\t\t    value: \"sma\"\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price,\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiidii\")\n\t\t\t\t\t\t\t\tvar jiBands = Module.addFunction(function (uid, indiHandle, bands_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiBandsOnArray = Module.addFunction(function (uid, array, total, period, deviation, bands_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"bands_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"deviations\",\n\t\t\t\t\t\t\t\t\t    value: deviation,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"shift\",\n\t\t\t\t\t\t\t\t\t    value: bands_shift,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"method\",\n\t\t\t\t\t\t\t\t\t    value: \"sma\"\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiidiii\")\n\t\t\t\t\t\t\t\tvar jiBullsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"bulls_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiBullsPower = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"bulls\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiCCIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"cci_for_mql\", [{\n\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t    value: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiCCI = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"cci\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiCCIOnArray = Module.addFunction(function (uid, array, total, period, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"cci_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, \"cci\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiCustomInit = Module.addFunction(function (uid, symbol, timeframe, name, paramString) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar indiName = window.mqlIndicators[obj.name].module.UTF8ToString(name)\n\t\t\t\t\t\t\t\t\tif (typeof window.mqlIndicators == \"undefined\" || typeof window.mqlIndicators[indiName] == \"undefined\") {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Please start MQL indicator loader plugin and load the specific indicator(\" + indiName + \").\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar params = window.mqlIndicators[obj.name].module.UTF8ToString(paramString).split(\"|||\")\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\tvar parameters = JSON.parse(JSON.stringify(window.mqlIndicators[indiName].definition.parameters))\n\t\t\t\t\t\t\t\t\tfor (var i in parameters) {\n\t\t\t\t\t\t\t\t\t\tif (isInteger(params[i])) {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = parseInt(params[i])\n\t\t\t\t\t\t\t\t\t\t} else if (isNumeric(params[i])) {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = parseFloat(params[i])\n\t\t\t\t\t\t\t\t\t\t} else if (params[i] == \"true\") {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = true\n\t\t\t\t\t\t\t\t\t\t} else if (params[i] == \"false\") {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = false\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = params[i]\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, indiName, parameters)\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiCustom = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiDeMarkerInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"demarker\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiDeMarker = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"demarker\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiEnvelopesInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_method, ma_shift, applied_price, deviation) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"envelopes_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"deviations\",\n\t\t\t\t\t\t\t\t\t    value: deviation\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"shift\",\n\t\t\t\t\t\t\t\t\t    value: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"method\",\n\t\t\t\t\t\t\t\t\t    value: method\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiiid\")\n\t\t\t\t\t\t\t\tvar jiEnvelopes = Module.addFunction(function (uid, indiHandle, ma_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiEnvelopesOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_method, ma_shift, deviation, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"envelopes_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\t\tname: \"deviations\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: deviation\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\t\tname: \"method\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: method\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiiiidii\")\n\t\t\t\t\t\t\t\tvar jiFractalsInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"fractals\", [])\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiFractals = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiIchimokuInit = Module.addFunction(function (uid, symbol, timeframe, tenkan_sen, kijun_sen, senkou_span_b) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"ichimoku\", [{\n\t\t\t\t\t\t\t\t\t    name: \"tenkan\",\n\t\t\t\t\t\t\t\t\t    value: tenkan_sen\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"kijun\",\n\t\t\t\t\t\t\t\t\t    value: kijun_sen\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"senkou\",\n\t\t\t\t\t\t\t\t\t    value: senkou_span_b\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiii\")\n\t\t\t\t\t\t\t\tvar jiIchimoku = Module.addFunction(function (uid, indiHandle, ichimoku_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiMAInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_shift, ma_method, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\tvar params = [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t\t\tif (ma_method == 1) {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"ema_for_mql\", params)\n\t\t\t\t\t\t\t\t\t} else if (ma_method == 2) {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"smma_for_mql\", params)\n\t\t\t\t\t\t\t\t\t} else if (ma_method == 3) {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"lwma_for_mql\", params)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"sma_for_mql\", params)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMA = Module.addFunction(function (uid, indiHandle, ma_shift, ma_method, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, method)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiMAOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_shift, ma_method, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = null\n\t\t\t\t\t\t\t\t\tvar params = [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t\t\tif (method == \"ema\") {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"ema_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t} else if (method == \"smma\") {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"smma_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t} else if (method == \"lwma\") {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"lwma_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"sma_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, method)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMACDInit = Module.addFunction(function (uid, symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"macd_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"fastEMA\",\n\t\t\t\t\t\t\t\t\t\tvalue: fast_ema_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"slowEMA\",\n\t\t\t\t\t\t\t\t\t\tvalue: slow_ema_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"signalSMA\",\n\t\t\t\t\t\t\t\t\t\tvalue: signal_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMACD = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiMFIInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"mfi\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMFI = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"mfi\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiMomentumInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"momentum_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiMomentum = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"momentum\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiMomentumOnArray = Module.addFunction(function (uid, array, total, period, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"momentum_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, \"momentum\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiRSIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"rsi_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiRSI = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"rsi\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiRSIOnArray = Module.addFunction(function (uid, array, total, period, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"rsi_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, \"rsi\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiRVIInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"rvi\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiRVI = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiSARInit = Module.addFunction(function (uid, symbol, timeframe, step, maximum) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"sar\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"acceleration\",\n\t\t\t\t\t\t\t\t\t\tvalue: step,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"afMax\",\n\t\t\t\t\t\t\t\t\t\tvalue: maximum,\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiidd\")\n\t\t\t\t\t\t\t\tvar jiSAR = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"sar\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiStochasticInit = Module.addFunction(function (uid, symbol, timeframe, Kperiod, Dperiod, slowing, ma_method) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"stochastic\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"KPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: Kperiod\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"slowing\",\n\t\t\t\t\t\t\t\t\t\tvalue: slowing\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"DPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: Dperiod\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"method\",\n\t\t\t\t\t\t\t\t\t\tvalue: method\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiStochastic = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlIndicators[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiWPRInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, \"wpr\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiWPR = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getDataFromIndi(obj.context, indiHandle, \"wpr\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jMarketInfo = Module.addFunction(function (uid, symbol, type) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar symbolObj = null\n\t\t\t\t\t\t\t\t\tif (symbolName == \"\") {\n\t\t\t\t\t\t\t\t\t\tsymbolObj = obj.symbol\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tsymbolObj = getSymbolInfo(obj.brokerName, obj.accountId, symbolName)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (type == 11) {\n\t\t\t\t\t\t\t\t\t\treturn 1.0 / symbolObj.toFixed\n\t\t\t\t\t\t\t\t\t} else if (type == 12) {\n\t\t\t\t\t\t\t\t\t\treturn Math.log10(symbolObj.toFixed)\n\t\t\t\t\t\t\t\t\t} else if (type == 18) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.swapLong\n\t\t\t\t\t\t\t\t\t} else if (type == 19) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.swapShort\n\t\t\t\t\t\t\t\t\t} else if (type == 22) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.tradable\n\t\t\t\t\t\t\t\t\t} else if (type == 23) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.lotsMinLimit\n\t\t\t\t\t\t\t\t\t} else if (type == 24) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.lotsStep\n\t\t\t\t\t\t\t\t\t} else if (type == 25) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.lotsLimit\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tprintErrorMessage(\"Not supported the specific market information currently!\")\n\t\t\t\t\t\t\t\t\treturn -1\n\t\t\t\t\t\t\t\t}, \"diii\")\n\n\t\t\t\t\t\t    window.mqlIndicators[definition.name] = {\n\t\t\t\t\t\t\t\t\tdefinition: definition,\n\t\t\t\t\t\t\t\t\tmodule: Module,\n\t\t\t\t\t\t\t\t\tsetParamInt: Module.cwrap(\"setParamInt\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetParamDouble: Module.cwrap(\"setParamDouble\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetParamBool: Module.cwrap(\"setParamBool\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetParamString: Module.cwrap(\"setParamString\", null, [\"number\", \"string\"]),\n\t\t\t\t\t\t\t\t\tsetDataInput: Module.cwrap(\"setDataInput\", null, [\"number\", \"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetDataOutput: Module.cwrap(\"setDataOutput\", null, [\"number\", \"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tonCalc: Module.cwrap(\"onCalc\", null, [\"number\", \"number\", \"number\", \"number\", \"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetjPrint: Module.cwrap(\"setjPrint\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjSetIndexShift: Module.cwrap(\"setjSetIndexShift\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartID: Module.cwrap(\"setjChartID\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartPeriod: Module.cwrap(\"setjChartPeriod\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartSymbol: Module.cwrap(\"setjChartSymbol\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjPeriod: Module.cwrap(\"setjPeriod\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjSymbol: Module.cwrap(\"setjSymbol\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiTimeInit: Module.cwrap(\"setjiTimeInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiTime: Module.cwrap(\"setjiTime\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiOpenInit: Module.cwrap(\"setjiOpenInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiOpen: Module.cwrap(\"setjiOpen\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiHighInit: Module.cwrap(\"setjiHighInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiHigh: Module.cwrap(\"setjiHigh\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiLowInit: Module.cwrap(\"setjiLowInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiLow: Module.cwrap(\"setjiLow\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCloseInit: Module.cwrap(\"setjiCloseInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiClose: Module.cwrap(\"setjiClose\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiVolumeInit: Module.cwrap(\"setjiVolumeInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiVolume: Module.cwrap(\"setjiVolume\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiHighest: Module.cwrap(\"setjiHighest\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiLowest: Module.cwrap(\"setjiLowest\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiACInit: Module.cwrap(\"setjiACInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAC: Module.cwrap(\"setjiAC\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiADXInit: Module.cwrap(\"setjiADXInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiADX: Module.cwrap(\"setjiADX\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAlligatorInit: Module.cwrap(\"setjiAlligatorInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAlligator: Module.cwrap(\"setjiAlligator\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAOInit: Module.cwrap(\"setjiAOInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAO: Module.cwrap(\"setjiAO\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiATRInit: Module.cwrap(\"setjiATRInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiATR: Module.cwrap(\"setjiATR\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBearsPowerInit: Module.cwrap(\"setjiBearsPowerInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBearsPower: Module.cwrap(\"setjiBearsPower\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBandsInit: Module.cwrap(\"setjiBandsInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBands: Module.cwrap(\"setjiBands\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBandsOnArray: Module.cwrap(\"setjiBandsOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBullsPowerInit: Module.cwrap(\"setjiBullsPowerInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBullsPower: Module.cwrap(\"setjiBullsPower\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCCIInit: Module.cwrap(\"setjiCCIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCCI: Module.cwrap(\"setjiCCI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCCIOnArray: Module.cwrap(\"setjiCCIOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCustomInit: Module.cwrap(\"setjiCustomInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCustom: Module.cwrap(\"setjiCustom\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiDeMarkerInit: Module.cwrap(\"setjiDeMarkerInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiDeMarker: Module.cwrap(\"setjiDeMarker\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiEnvelopesInit: Module.cwrap(\"setjiEnvelopesInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiEnvelopes: Module.cwrap(\"setjiEnvelopes\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiEnvelopesOnArray: Module.cwrap(\"setjiEnvelopesOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiFractalsInit: Module.cwrap(\"setjiFractalsInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiFractals: Module.cwrap(\"setjiFractals\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiIchimokuInit: Module.cwrap(\"setjiIchimokuInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiIchimoku: Module.cwrap(\"setjiIchimoku\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMAInit: Module.cwrap(\"setjiMAInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMA: Module.cwrap(\"setjiMA\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMAOnArray: Module.cwrap(\"setjiMAOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMACDInit: Module.cwrap(\"setjiMACDInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMACD: Module.cwrap(\"setjiMACD\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMFIInit: Module.cwrap(\"setjiMFIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMFI: Module.cwrap(\"setjiMFI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMomentumInit: Module.cwrap(\"setjiMomentumInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMomentum: Module.cwrap(\"setjiMomentum\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMomentumOnArray: Module.cwrap(\"setjiMomentumOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRSIInit: Module.cwrap(\"setjiRSIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRSI: Module.cwrap(\"setjiRSI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRSIOnArray: Module.cwrap(\"setjiRSIOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRVIInit: Module.cwrap(\"setjiRVIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRVI: Module.cwrap(\"setjiRVI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiSARInit: Module.cwrap(\"setjiSARInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiSAR: Module.cwrap(\"setjiSAR\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiStochasticInit: Module.cwrap(\"setjiStochasticInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiStochastic: Module.cwrap(\"setjiStochastic\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiWPRInit: Module.cwrap(\"setjiWPRInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiWPR: Module.cwrap(\"setjiWPR\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjMarketInfo: Module.cwrap(\"setjMarketInfo\", null, [\"number\"])\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjPrint(jPrint)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjSetIndexShift(jSetIndexShift)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjChartID(jChartID)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjChartPeriod(jChartPeriod)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjChartSymbol(jChartSymbol)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjPeriod(jPeriod)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjSymbol(jSymbol)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiTimeInit(jiTimeInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiTime(jiTime)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiOpenInit(jiOpenInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiOpen(jiOpen)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiHighInit(jiHighInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiHigh(jiHigh)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiLowInit(jiLowInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiLow(jiLow)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiCloseInit(jiCloseInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiClose(jiClose)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiVolumeInit(jiVolumeInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiVolume(jiVolume)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiHighest(jiHighest)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiLowest(jiLowest)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiACInit(jiACInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiAC(jiAC)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiADXInit(jiADXInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiADX(jiADX)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiAlligatorInit(jiAlligatorInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiAlligator(jiAlligator)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiAOInit(jiAOInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiAO(jiAO)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiATRInit(jiATRInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiATR(jiATR)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBearsPowerInit(jiBearsPowerInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBearsPower(jiBearsPower)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBandsInit(jiBandsInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBands(jiBands)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBandsOnArray(jiBandsOnArray)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBullsPowerInit(jiBullsPowerInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiBullsPower(jiBullsPower)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiCCIInit(jiCCIInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiCCI(jiCCI)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiCCIOnArray(jiCCIOnArray)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiCustomInit(jiCustomInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiCustom(jiCustom)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiDeMarkerInit(jiDeMarkerInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiDeMarker(jiDeMarker)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiEnvelopesInit(jiEnvelopesInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiEnvelopes(jiEnvelopes)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiEnvelopesOnArray(jiEnvelopesOnArray)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiFractalsInit(jiFractalsInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiFractals(jiFractals)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiIchimokuInit(jiIchimokuInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiIchimoku(jiIchimoku)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMAInit(jiMAInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMA(jiMA)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMAOnArray(jiMAOnArray)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMACDInit(jiMACDInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMACD(jiMACD)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMFIInit(jiMFIInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMFI(jiMFI)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMomentumInit(jiMomentumInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMomentum(jiMomentum)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiMomentumOnArray(jiMomentumOnArray)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiRSIInit(jiRSIInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiRSI(jiRSI)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiRSIOnArray(jiRSIOnArray)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiRVIInit(jiRVIInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiRVI(jiRVI)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiSARInit(jiSARInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiSAR(jiSAR)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiStochasticInit(jiStochasticInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiStochastic(jiStochastic)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiWPRInit(jiWPRInit)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjiWPR(jiWPR)\n\t\t\t\t\t\t\t\twindow.mqlIndicators[definition.name].setjMarketInfo(jMarketInfo)\n\n\t\t\t\t\t\t\t\tvar monitorMemory = function () {\n\t\t\t\t\t\t\t\t\tfor (var i in window.mqlIndicatorsBuffer) {\n\t\t\t\t\t\t\t\t\t\tvar obj = window.mqlIndicatorsBuffer[i]\n\t\t\t\t\t\t\t\t\t\tvar module = window.mqlIndicators[obj.name].module\n\n\t\t\t\t\t\t\t\t\t\tif (obj.time == obj.mTime) {\n\t\t\t\t\t\t\t\t\t\t\tfor (var j in obj.dataInput) {\n\t\t\t\t\t\t\t\t\t\t\t\tmodule._free(obj.dataInput[j])\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tfor (var j in obj.dataOutput) {\n\t\t\t\t\t\t\t\t\t\t\t\tmodule._free(obj.dataOutput[j])\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tdelete window.mqlIndicatorsBuffer[i]\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tobj.mTime = obj.time\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tsetTimeout(monitorMemory, 30000)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tsetTimeout(monitorMemory, 30000)\n\n\t\t\t\t\t\t\t\trs(definition)\n\t\t\t\t\t\t\t}) // Module[\"onRuntimeInitialized\"]\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(function () {\n\t\t\t\t\t\t\trj()\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tsaveMqlIndicator: function (definition, bAdd) {\n\t\t\t\t\tif (typeof localStorage.reservedZone == \"undefined\") {\n\t\t\t\t\t\tif (bAdd) {\n\t\t\t\t\t\t\tlocalStorage.reservedZone = JSON.stringify({allMqlIndis: [definition]})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\t\t\t\t\t\tif (typeof reservedZone.allMqlIndis == \"undefined\") {\n\t\t\t\t\t\t\tif (bAdd) {\n\t\t\t\t\t\t\t\treservedZone.allMqlIndis = [definition]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (var i in reservedZone.allMqlIndis) {\n\t\t\t\t\t\t\t\tif (reservedZone.allMqlIndis[i].name == definition.name) {\n\t\t\t\t\t\t\t\t\treservedZone.allMqlIndis.splice(i, 1)\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (bAdd) {\n\t\t\t\t\t\t\t\treservedZone.allMqlIndis.push(definition)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlocalStorage.reservedZone = JSON.stringify(reservedZone)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcreateMqlEA: function (definition) {\n\t\t\t\t\tvar parameters = []\n\t\t\t\t\tparameters.push({\n\t\t\t\t\t\tname: \"symbol\",\n\t\t\t\t\t\tvalue: \"EUR/USD\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\t\t\t\trange: null\n\t\t\t\t\t})\n\t\t\t\t\tparameters.push({\n\t\t\t\t\t\tname: \"timeframe\",\n\t\t\t\t\t\tvalue: TIME_FRAME.M1,\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\ttype: PARAMETER_TYPE.STRING,\n\t\t\t\t\t\trange: null\n\t\t\t\t\t})\n\t\t\t\t\tfor (var i in definition.parameters) {\n\t\t\t\t\t\tparameters.push(definition.parameters[i])\n\t\t\t\t\t}\n\n\t\t\t\t\timportBuiltInEA(\n\t\t\t\t\t\tdefinition.name,\n\t\t\t\t\t\tdefinition.description,\n\t\t\t\t\t\tparameters,\n\t\t\t\t\t\tfunction (context) { // Init()\n\t\t\t\t\t\t\tvar eaName = getEAName(context)\n\t\t\t\t\t\t\tif (typeof window.mqlEAs == \"undefined\" || typeof window.mqlEAs[eaName] == \"undefined\") {\n\t\t\t\t\t\t\t\tthrow new Error(\"Please start MQL EA loader plugin.\")\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar uid = null\n\t\t\t\t\t\t\tif (typeof context.uid == \"undefined\") {\n\t\t\t\t\t\t\t\tuid = window.mqlEAUID++\n\t\t\t\t\t\t\t\tcontext.uid = uid\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tuid = context.uid\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar eaObj = window.mqlEAs[eaName]\n\t\t\t\t\t\t\tvar currDefinition = eaObj.definition\n\n\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\tvar nByteString = 1\n\t\t\t\t\t\t\tvar length = 1\n\t\t\t\t\t\t\tvar buffer = null\n\n\t\t\t\t\t\t\tfor (var i in currDefinition.parameters) {\n\t\t\t\t\t\t\t\tif (currDefinition.parameters[i].type == PARAMETER_TYPE.INTEGER) {\n\t\t\t\t\t\t\t\t\teaObj.setParamInt(uid, getEAParameter(context, currDefinition.parameters[i].name))\n\t\t\t\t\t\t\t\t} else if (currDefinition.parameters[i].type == PARAMETER_TYPE.NUMBER) {\n\t\t\t\t\t\t\t\t\teaObj.setParamDouble(uid, getEAParameter(context, currDefinition.parameters[i].name))\n\t\t\t\t\t\t\t\t} else if (currDefinition.parameters[i].type == PARAMETER_TYPE.BOOLEAN) {\n\t\t\t\t\t\t\t\t\teaObj.setParamBool(uid, getEAParameter(context, currDefinition.parameters[i].name))\n\t\t\t\t\t\t\t\t} else if (currDefinition.parameters[i].type == PARAMETER_TYPE.STRING) {\n\t\t\t\t\t\t\t\t\tvar eaStrParam = getEAParameter(context, currDefinition.parameters[i].name)\n\t\t\t\t\t\t\t\t\tif (eaStrParam == null) {\n\t\t\t\t\t\t\t\t\t\teaStrParam = \"\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\teaObj.setParamString(uid, eaStrParam)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (typeof window.mqlEAsBuffer[uid + \"\"] == \"undefined\") {\n\t\t\t\t\t\t\t\tvar account = getAccount(context, 0)\n\t\t\t\t\t\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\t\t\t\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\t\t\t\t\t\tvar symbolName = getEAParameter(context, \"symbol\")\n\t\t\t\t\t\t\t\tvar timeFrame = getEAParameter(context, \"timeframe\")\n\n\t\t\t\t\t\t\t\twindow.mqlEAsBuffer[uid + \"\"] = {\n\t\t\t\t\t\t\t\t\tname: currDefinition.name,\n\t\t\t\t\t\t\t\t\tcontext: context,\n\t\t\t\t\t\t\t\t\tbrokerName: brokerName,\n\t\t\t\t\t\t\t\t\taccountId: accountId,\n\t\t\t\t\t\t\t\t\tsymbolName: symbolName,\n\t\t\t\t\t\t\t\t\ttimeFrame: timeFrame,\n\t\t\t\t\t\t\t\t\tchartId: getChartHandle(context, brokerName, accountId, symbolName, timeFrame),\n\t\t\t\t\t\t\t\t\tsymbol: getSymbolInfo(brokerName, accountId, symbolName),\n\t\t\t\t\t\t\t\t\tobjs: (typeof localStorage.mqlObjs != \"undefined\" ? JSON.parse(localStorage.mqlObjs) : []),\n\t\t\t\t\t\t\t\t\tneuralNetworks: [],\n\t\t\t\t\t\t\t\t\tbPreventCleanUp: false,\n\t\t\t\t\t\t\t\t\tlock: false,\n\t\t\t\t\t\t\t\t\tconvertTimeFrame: function () {\n\t\t\t\t\t\t\t\t\t\tif (TIME_FRAME.M1 == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.M5 == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 5\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.M15 == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 15\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.M30 == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 30\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.H1 == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 60\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.H4 == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 240\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.D == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 1440\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.W == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 10080\n\t\t\t\t\t\t\t\t\t\t} else if (TIME_FRAME.M == timeFrame) {\n\t\t\t\t\t\t\t\t\t\t\treturn 43200\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tgetQuotes (context, brokerName, accountId, symbolName)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\teaObj.onTick(uid, 10000, 0, 0, 1.0 / window.mqlEAsBuffer[uid + \"\"].symbol.toFixed, Math.log10(window.mqlEAsBuffer[uid + \"\"].symbol.toFixed))\n\t\t\t\t\t\t\teaObj.onInit(uid)\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfunction (context) { // Deinit()\n\t\t\t\t\t\t\tvar eaName = getEAName(context)\n\t\t\t\t\t\t\tvar eaObj = window.mqlEAs[eaName]\n\t\t\t\t\t\t\teaObj.onDeinit(context.uid, 0)\n\t\t\t\t\t\t\tif (!window.mqlEAsBuffer[context.uid + \"\"].bPreventCleanUp) {\n\t\t\t\t\t\t\t\tdelete window.mqlEAsBuffer[context.uid + \"\"]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfunction (context) { // OnTick()\n\t\t\t\t\t\t\tvar eaName = getEAName(context)\n\t\t\t\t\t\t\tif (typeof window.mqlEAs == \"undefined\" || typeof window.mqlEAs[eaName] == \"undefined\") {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar uid = context.uid\n\t\t\t\t\t\t\tif (typeof window.mqlEAsBuffer[uid + \"\"] == \"undefined\" || window.mqlEAsBuffer[uid + \"\"].lock) {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar buffObj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\tbuffObj.context = context\n\t\t\t\t\t\t\tvar brokerName = buffObj.brokerName\n\t\t\t\t\t\t\tvar accountId = buffObj.accountId\n\t\t\t\t\t\t\tvar symbolName = buffObj.symbolName\n\n\t\t\t\t\t\t\tvar tData = getData(context, buffObj.chartId, DATA_NAME.TIME)\n\n\t\t\t\t\t\t\tvar ask = null\n\t\t\t\t\t\t\tvar bid = null\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\task = getAsk(context, brokerName, accountId, symbolName)\n\t\t\t\t\t\t\t\tbid = getBid(context, brokerName, accountId, symbolName)\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t// This try-catch is used to bypass the \"error throw\" when you start the EA too early to call getAsk or getBid(at that time, bid or ask may be not ready yet.)\n\t\t\t\t\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\twindow.mqlEAs[eaName].onTick(\n\t\t\t\t\t\t\t\tuid,\n\t\t\t\t\t\t\t\ttData.length,\n\t\t\t\t\t\t\t\task,\n\t\t\t\t\t\t\t\tbid,\n\t\t\t\t\t\t\t\t1.0 / buffObj.symbol.toFixed,\n\t\t\t\t\t\t\t\tMath.log10(buffObj.symbol.toFixed)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t) // registerEA\n\t\t\t\t},\n\t\t\t\tremoveMqlEA: function (name) {\n\t\t\t\t\tunregisterEA(name)\n\n\t\t\t\t\tif (typeof window.mqlEAs == \"undefined\" || typeof window.mqlEAsBuffer == \"undefined\") return\n\n\t\t\t\t\tdelete window.mqlEAs[name]\n\t\t\t\t\tfor (var i in window.mqlEAsBuffer) {\n\t\t\t\t\t\tif (window.mqlEAsBuffer[i].name == name) {\n\t\t\t\t\t\t\tdelete window.mqlEAsBuffer[i]\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tloadMqlEA: function (definition) {\n\t\t\t\t\treturn new Promise(function (rs, rj) {\n\t\t\t\t\t\tvar scriptPromise = new Promise(function (resolve, reject) {\n\t\t\t\t\t\t\tvar tags = document.getElementsByTagName(\"script\")\n\t\t\t\t\t\t\tfor (var i = tags.length - 1; i >= 0; i--) {\n\t\t\t\t\t\t\t\tif (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == definition.url) {\n\t\t\t\t\t\t\t\t\ttags[i].parentNode.removeChild(tags[i])\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t  var script = document.createElement(\"script\")\n\t\t\t\t\t\t  document.body.appendChild(script)\n\t\t\t\t\t\t  script.onload = resolve\n\t\t\t\t\t\t  script.onerror = reject\n\t\t\t\t\t\t  script.async = true\n\t\t\t\t\t\t  script.src = definition.url\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tscriptPromise.then(function () {\n\t\t\t\t\t\t\tEAPlugIn().then(function (Module) {\n\t\t\t\t\t\t\t\tif (typeof window.mqlEAs == \"undefined\") {\n\t\t\t\t\t\t\t\t\twindow.mqlEAs = []\n\t\t\t\t\t\t\t\t\twindow.mqlEAsBuffer = []\n\t\t\t\t\t\t\t\t\twindow.mqlEAUID = 0\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar jChartClose = Module.addFunction(function (uid, chart_id) {\n\t\t\t\t\t\t\t\t\tif (chart_id == 0) {\n\t\t\t\t\t\t\t\t\t\treturn removeChart(window.mqlEAsBuffer[uid + \"\"].chartId)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn removeChart(chart_id)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iii\")\n\t\t\t\t\t\t\t\tvar jChartID = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t  return window.mqlEAsBuffer[uid + \"\"].chartId\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jChartOpen = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jChartPeriod = Module.addFunction(function (uid, chart_id) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tif (chart_id == 0) {\n\t\t\t\t\t\t\t\t\t\treturn obj.convertTimeFrame(obj.timeFrame)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn obj.convertTimeFrame(getChartTimeFrame(chart_id))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iii\")\n\t\t\t\t\t\t\t\tvar jChartSymbol = Module.addFunction(function (uid, chart_id) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = \"\"\n\t\t\t\t\t\t\t\t\tif (chart_id == 0) {\n\t\t\t\t\t\t\t\t\t\tsymbolName = obj.symbolName\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tsymbolName = getChartSymbolName(chart_id)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(symbolName) + 1\n\t\t\t\t\t\t\t\t\tvar stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t\twindow.mqlEAs[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t\treturn stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"iii\")\n\t\t\t\t\t\t\t\tvar jPeriod = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn obj.convertTimeFrame(obj.timeFrame)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jSymbol = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = obj.symbolName\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(symbolName) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlEAs[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jAccountBalance = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\treturn getBalanceOfAccount(account)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jAccountCompany = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(brokerName) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlEAs[obj.name].module.stringToUTF8(brokerName, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jAccountCurrency = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\tvar currency = getCurrencyOfAccount(account)\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(currency) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlEAs[obj.name].module.stringToUTF8(currency, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jAccountEquity = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\treturn getEquityOfAccount(account)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jAccountFreeMargin = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\treturn getMarginAvailableOfAccount(account)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jAccountMargin = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\treturn getMarginUsedOfAccount(account)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jAccountProfit = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar account = getAccount(obj.context, 0)\n\t\t\t\t\t\t\t\t\treturn getUnrealizedPLOfAccount(account)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jOrdersTotal = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getOrdersTradesListLength(obj.context)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrdersHistoryTotal = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getHistoryPoolLength(obj.context)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderSelect = Module.addFunction(function (uid, index, select, pool) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tvar orderOrTrade = null\n\t\t\t\t\t\t\t\t\t\tif (select == 1) {\n\t\t\t\t\t\t\t\t\t\t\tif (pool == 2) {\n\t\t\t\t\t\t\t\t\t\t\t\torderOrTrade = getOrderOrTradeFromHistoryByIndex(obj.context, index)\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\torderOrTrade = getOrderOrTradeByIndex(obj.context, index)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tif (pool == 2) {\n\t\t\t\t\t\t\t\t\t\t\t\torderOrTrade = getOrderOrTradeFromHistoryById(obj.context, index + \"\")\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\torderOrTrade = getOrderOrTradeById(obj.context, index + \"\")\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tobj.orderOrTrade = orderOrTrade.orderOrTrade\n\t\t\t\t\t\t\t\t\t\tobj.type = orderOrTrade.type\n\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jOrderOpenPrice = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getOrderTradePrice(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jOrderType = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar orderType = getOrderType(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t\tif (\"BUY\" == orderType) {\n\t\t\t\t\t\t\t\t    return 0;\n\t\t\t\t\t\t\t\t  } else if (\"SELL\" == orderType) {\n\t\t\t\t\t\t\t\t    return 1;\n\t\t\t\t\t\t\t\t  } else if (\"BUY LIMIT\" == orderType) {\n\t\t\t\t\t\t\t\t    return 2;\n\t\t\t\t\t\t\t\t  } else if (\"SELL LIMIT\" == orderType) {\n\t\t\t\t\t\t\t\t    return 3;\n\t\t\t\t\t\t\t\t  } else if (\"BUY STOP\" == orderType) {\n\t\t\t\t\t\t\t\t    return 4;\n\t\t\t\t\t\t\t\t  } else {\n\t\t\t\t\t\t\t\t    return 5;\n\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderTakeProfit = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getTakeProfit(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jOrderStopLoss = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getStopLoss(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jOrderLots = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getOrderTradeLots(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jOrderProfit = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getPL(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"di\")\n\t\t\t\t\t\t\t\tvar jOrderSymbol = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = getSymbolName(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(symbolName) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlEAs[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderTicket = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn parseInt(getId(obj.orderOrTrade))\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderMagicNumber = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getMagicNumber(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderOpenTime = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getOrderTradeTime(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderComment = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar comment = getComment(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t\tvar lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(comment) + 1\n\t\t\t\t\t\t\t\t  var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes)\n\t\t\t\t\t\t\t\t  window.mqlEAs[obj.name].module.stringToUTF8(comment, stringOnWasmHeap, lengthBytes)\n\t\t\t\t\t\t\t\t  return stringOnWasmHeap\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderExpiration = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\treturn getExpiration(obj.orderOrTrade)\n\t\t\t\t\t\t\t\t}, \"ii\")\n\t\t\t\t\t\t\t\tvar jOrderPrint = Module.addFunction(function (uid) {\n\t\t\t\t\t\t\t\t\tvar orderOrTrade = window.mqlEAsBuffer[uid + \"\"].orderOrTrade\n\t\t\t\t\t\t\t\t\t// todo add more information\n\t\t\t\t\t\t\t\t\treturn printMessage(getId(orderOrTrade) + \" \" + getOrderTradeTime(orderOrTrade) + \" \" + getOrderType(orderOrTrade) + \" \" + getOrderTradeLots(orderOrTrade) + \" \" +\n\t\t\t\t\t\t\t\t\t\t\t\t\tgetSymbolName(orderOrTrade) + \" \" + getOrderTradePrice(orderOrTrade) + \" \" + getStopLoss(orderOrTrade) + \" \" + getTakeProfit(orderOrTrade))\n\t\t\t\t\t\t\t\t}, \"vi\")\n\t\t\t\t\t\t\t\tvar jPrint = Module.addFunction(function (uid, s) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tprintMessage(window.mqlEAs[obj.name].module.UTF8ToString(s))\n\t\t\t\t\t\t\t\t}, \"vii\")\n\t\t\t\t\t\t\t\tvar jiTimeInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiTime = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, \"Time\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiOpenInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiOpen = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, \"Open\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiHighInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiHigh = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, \"High\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiLowInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiLow = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, \"Low\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiCloseInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiClose = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, \"Close\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiVolumeInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm)\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiVolume = Module.addFunction(function (uid, chartHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, \"Volume\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiHighest = Module.addFunction(function (uid, chartHandle, mode, count, start) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, md)\n\t\t\t\t\t\t\t\t\tvar highest = -Number.MAX_VALUE\n\t\t\t\t\t\t\t\t\tvar idx = -1\n\t\t\t\t\t\t\t\t\tfor (var i = start; i < start + count && i >= 0 && i < arr.length; i++) {\n\t\t\t\t\t\t\t\t\t\tif (arr[arr.length - i - 1] > highest) {\n\t\t\t\t\t\t\t\t\t\t\thighest = arr[arr.length - i - 1]\n\t\t\t\t\t\t\t\t\t\t\tidx = i\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn idx\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiLowest = Module.addFunction(function (uid, chartHandle, mode, count, start) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, chartHandle, md)\n\t\t\t\t\t\t\t\t\tvar lowest = Number.MAX_VALUE\n\t\t\t\t\t\t\t\t\tvar idx = -1\n\t\t\t\t\t\t\t\t\tfor (var i = start; i < start + count && i >= 0 && i < arr.length; i++) {\n\t\t\t\t\t\t\t\t\t\tif (arr[arr.length - i - 1] < lowest) {\n\t\t\t\t\t\t\t\t\t\t\tlowest = arr[arr.length - i - 1]\n\t\t\t\t\t\t\t\t\t\t\tidx = i\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn idx\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiACInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"ac\", [])\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiAC = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arrUp = getData(obj.context, indiHandle, \"up\")\n\t\t\t\t\t\t\t\t\tvar arrDown = getData(obj.context, indiHandle, \"down\")\n\t\t\t\t\t\t\t\t\treturn arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiADXInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"adx_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiADX = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiAlligatorInit = Module.addFunction(function (uid, symbol, timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"alligator_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"jawsPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: jaw_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"jawsShift\",\n\t\t\t\t\t\t\t\t\t\tvalue: jaw_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"teethPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: teeth_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"teethShift\",\n\t\t\t\t\t\t\t\t\t\tvalue: teeth_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"lipsPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: lips_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"lipsShift\",\n\t\t\t\t\t\t\t\t\t\tvalue: lips_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"method\",\n\t\t\t\t\t\t\t\t\t\tvalue: method\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiAlligator = Module.addFunction(function (uid, indiHandle, jaw_shift, teeth_shift, lips_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\tif (md == \"jaws\") {\n\t\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t\t} else if (md == \"teeth\") {\n\t\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"diiiiiii\")\n\t\t\t\t\t\t\t\tvar jiAOInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"ao\", [])\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiAO = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arrUp = getData(obj.context, indiHandle, \"up\")\n\t\t\t\t\t\t\t\t\tvar arrDown = getData(obj.context, indiHandle, \"down\")\n\t\t\t\t\t\t\t\t\treturn arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiATRInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"atr\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiATR = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"atr\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiBearsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"bears_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiBearsPower = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"bears\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiBandsInit = Module.addFunction(function (uid, symbol, timeframe, period, deviation, bands_shift, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"bands_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"deviations\",\n\t\t\t\t\t\t\t\t\t    value: deviation,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"shift\",\n\t\t\t\t\t\t\t\t\t    value: bands_shift,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"method\",\n\t\t\t\t\t\t\t\t\t    value: \"sma\"\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price,\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiidii\")\n\t\t\t\t\t\t\t\tvar jiBands = Module.addFunction(function (uid, indiHandle, bands_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiBandsOnArray = Module.addFunction(function (uid, array, total, period, deviation, bands_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"bands_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"deviations\",\n\t\t\t\t\t\t\t\t\t    value: deviation,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"shift\",\n\t\t\t\t\t\t\t\t\t    value: bands_shift,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"method\",\n\t\t\t\t\t\t\t\t\t    value: \"sma\"\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiidiii\")\n\t\t\t\t\t\t\t\tvar jiBullsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"bulls_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiBullsPower = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"bulls\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiCCIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"cci_for_mql\", [{\n\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t    value: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiCCI = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"cci\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiCCIOnArray = Module.addFunction(function (uid, array, total, period, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"cci_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, \"cci\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiCustomInit = Module.addFunction(function (uid, symbol, timeframe, name, paramString) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar indiName = window.mqlEAs[obj.name].module.UTF8ToString(name)\n\t\t\t\t\t\t\t\t\tif (typeof window.mqlIndicators == \"undefined\" || typeof window.mqlIndicators[indiName] == \"undefined\") {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Please start MQL indicator loader plugin and load the specific indicator(\" + indiName + \").\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar params = window.mqlEAs[obj.name].module.UTF8ToString(paramString).split(\"|||\")\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\tvar parameters = JSON.parse(JSON.stringify(window.mqlIndicators[indiName].definition.parameters))\n\t\t\t\t\t\t\t\t\tfor (var i in parameters) {\n\t\t\t\t\t\t\t\t\t\tif (isInteger(params[i])) {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = parseInt(params[i])\n\t\t\t\t\t\t\t\t\t\t} else if (isNumeric(params[i])) {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = parseFloat(params[i])\n\t\t\t\t\t\t\t\t\t\t} else if (params[i] == \"true\") {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = true\n\t\t\t\t\t\t\t\t\t\t} else if (params[i] == \"false\") {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = false\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tparameters[i].value = params[i]\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, indiName, parameters)\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiCustom = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiDeMarkerInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"demarker\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiDeMarker = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"demarker\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiEnvelopesInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_method, ma_shift, applied_price, deviation) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"envelopes_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"deviations\",\n\t\t\t\t\t\t\t\t\t    value: deviation\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"shift\",\n\t\t\t\t\t\t\t\t\t    value: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"method\",\n\t\t\t\t\t\t\t\t\t    value: method\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiiid\")\n\t\t\t\t\t\t\t\tvar jiEnvelopes = Module.addFunction(function (uid, indiHandle, ma_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiEnvelopesOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_method, ma_shift, deviation, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"envelopes_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\t\tname: \"deviations\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: deviation\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\t\tname: \"method\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: method\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiiiidii\")\n\t\t\t\t\t\t\t\tvar jiFractalsInit = Module.addFunction(function (uid, symbol, timeframe) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"fractals\", [])\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jiFractals = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiIchimokuInit = Module.addFunction(function (uid, symbol, timeframe, tenkan_sen, kijun_sen, senkou_span_b) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"ichimoku\", [{\n\t\t\t\t\t\t\t\t\t    name: \"tenkan\",\n\t\t\t\t\t\t\t\t\t    value: tenkan_sen\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"kijun\",\n\t\t\t\t\t\t\t\t\t    value: kijun_sen\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t    name: \"senkou\",\n\t\t\t\t\t\t\t\t\t    value: senkou_span_b\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiii\")\n\t\t\t\t\t\t\t\tvar jiIchimoku = Module.addFunction(function (uid, indiHandle, ichimoku_shift, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiMAInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_shift, ma_method, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\tvar params = [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t\t\tif (ma_method == 1) {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"ema_for_mql\", params)\n\t\t\t\t\t\t\t\t\t} else if (ma_method == 2) {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"smma_for_mql\", params)\n\t\t\t\t\t\t\t\t\t} else if (ma_method == 3) {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"lwma_for_mql\", params)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"sma_for_mql\", params)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMA = Module.addFunction(function (uid, indiHandle, ma_shift, ma_method, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, method)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiMAOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_shift, ma_method, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = null\n\t\t\t\t\t\t\t\t\tvar params = [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\t\t\t\tvalue: ma_shift\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t\t\tif (method == \"ema\") {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"ema_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t} else if (method == \"smma\") {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"smma_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t} else if (method == \"lwma\") {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"lwma_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tdataOutput = calcIndicatorOnArray(\"sma_for_mql\", params, dataInput, total)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, method)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMACDInit = Module.addFunction(function (uid, symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"macd_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"fastEMA\",\n\t\t\t\t\t\t\t\t\t\tvalue: fast_ema_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"slowEMA\",\n\t\t\t\t\t\t\t\t\t\tvalue: slow_ema_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"signalSMA\",\n\t\t\t\t\t\t\t\t\t\tvalue: signal_period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMACD = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiMFIInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"mfi\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiMFI = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"mfi\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiMomentumInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"momentum_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiMomentum = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"momentum\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiMomentumOnArray = Module.addFunction(function (uid, array, total, period, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"momentum_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, \"momentum\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiRSIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"rsi_for_mql\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: applied_price\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiii\")\n\t\t\t\t\t\t\t\tvar jiRSI = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"rsi\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiRSIOnArray = Module.addFunction(function (uid, array, total, period, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar nByteDouble = 8\n\t\t\t\t\t\t\t\t\tvar data = new Array(total)\n\t\t\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t\t\tdata[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tvar dataInput = []\n\t\t\t\t\t\t\t\t\tdataInput[0] = data\n\t\t\t\t\t\t\t\t\tvar dataOutput = calcIndicatorOnArray(\"rsi_for_mql\", [{\n\t\t\t\t\t\t\t\t\t    name: \"period\",\n\t\t\t\t\t\t\t\t\t    value: period,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"appliedPrice\",\n\t\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t\t}], dataInput, total)\n\t\t\t\t\t\t\t\t\tvar arr = getDataOnArray(dataOutput, \"rsi\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiiii\")\n\t\t\t\t\t\t\t\tvar jiRVIInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"rvi\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiRVI = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiSARInit = Module.addFunction(function (uid, symbol, timeframe, step, maximum) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"sar\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"acceleration\",\n\t\t\t\t\t\t\t\t\t\tvalue: step,\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"afMax\",\n\t\t\t\t\t\t\t\t\t\tvalue: maximum,\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiidd\")\n\t\t\t\t\t\t\t\tvar jiSAR = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"sar\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jiStochasticInit = Module.addFunction(function (uid, symbol, timeframe, Kperiod, Dperiod, slowing, ma_method) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tvar method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"stochastic\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"KPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: Kperiod\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"slowing\",\n\t\t\t\t\t\t\t\t\t\tvalue: slowing\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"DPeriod\",\n\t\t\t\t\t\t\t\t\t\tvalue: Dperiod\n\t\t\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\t\t\tname: \"method\",\n\t\t\t\t\t\t\t\t\t\tvalue: method\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiiiiii\")\n\t\t\t\t\t\t\t\tvar jiStochastic = Module.addFunction(function (uid, indiHandle, mode, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar md = window.mqlEAs[obj.name].module.UTF8ToString(mode)\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, md)\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\t\t\t\t\t\t\t\tvar jiWPRInit = Module.addFunction(function (uid, symbol, timeframe, period) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe)\n\t\t\t\t\t\t\t\t\tsymbolName = symbolName == \"\" ? obj.symbolName : symbolName\n\t\t\t\t\t\t\t\t\ttimeFrm = timeFrm == \"0\" ? obj.timeFrame : timeFrm\n\t\t\t\t\t\t\t\t\treturn getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, \"wpr\", [{\n\t\t\t\t\t\t\t\t\t\tname: \"period\",\n\t\t\t\t\t\t\t\t\t\tvalue: period\n\t\t\t\t\t\t\t\t\t}])\n\t\t\t\t\t\t\t\t}, \"iiiii\")\n\t\t\t\t\t\t\t\tvar jiWPR = Module.addFunction(function (uid, indiHandle, shift) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar arr = getData(obj.context, indiHandle, \"wpr\")\n\t\t\t\t\t\t\t\t\treturn arr[arr.length - shift - 1]\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jObjectCreate = Module.addFunction(function (uid, chart_id, object_name, object_type, time, price, time2, price2) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar name = window.mqlEAs[obj.name].module.UTF8ToString(object_name)\n\t\t\t\t\t\t\t\t\tif (object_type == 1) { // OBJ_ARROW_CHECK\n\t\t\t\t\t\t\t\t\t\tvar objId = addSignal(chart_id, name, time, price)\n\t\t\t\t\t\t\t\t\t\tif (objId != -1) {\n\t\t\t\t\t\t\t\t\t\t\tobj.objs.push({id: objId, chartId: chart_id, name: name})\n\t\t\t\t\t\t\t\t\t\t\tlocalStorage.mqlObjs = JSON.stringify(obj.objs)\n\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else if (object_type == 2) { // OBJ_TREND\n\t\t\t\t\t\t\t\t\t\tvar objId = addTrendLine(chart_id, name, time, price, time2, price2)\n\t\t\t\t\t\t\t\t\t\tif (objId != -1) {\n\t\t\t\t\t\t\t\t\t\t\tobj.objs.push({id: objId, chartId: chart_id, name: name})\n\t\t\t\t\t\t\t\t\t\t\tlocalStorage.mqlObjs = JSON.stringify(obj.objs)\n\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iiiiiidid\")\n\t\t\t\t\t\t\t\tvar jObjectDelete = Module.addFunction(function (uid, object_name) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar name = window.mqlEAs[obj.name].module.UTF8ToString(object_name)\n\t\t\t\t\t\t\t\t\tvar success = false\n\t\t\t\t\t\t\t\t\tfor (var i = obj.objs.length - 1; i >= 0; i--) {\n\t\t\t\t\t\t\t\t\t\tif (obj.objs[i].name == name) {\n\t\t\t\t\t\t\t\t\t\t\tif (removeObject(obj.objs[i].chartId, obj.objs[i].id)) {\n\t\t\t\t\t\t\t\t\t\t\t\tsuccess = true\n\t\t\t\t\t\t\t\t\t\t\t\tobj.objs.splice(i, 1)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (success) {\n\t\t\t\t\t\t\t\t\t\tlocalStorage.mqlObjs = JSON.stringify(obj.objs)\n\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iii\")\n\t\t\t\t\t\t\t\tvar jObjectGet = Module.addFunction(function (uid, object_name, property_index) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar name = window.mqlEAs[obj.name].module.UTF8ToString(object_name)\n\t\t\t\t\t\t\t\t\tfor (var i = obj.objs.length - 1; i >= 0; i--) {\n\t\t\t\t\t\t\t\t\t\tif (obj.objs[i].name == name) {\n\t\t\t\t\t\t\t\t\t\t\tif (property_index == 0) { // OBJPROP_TIME1\n\t\t\t\t\t\t\t\t\t\t\t\treturn getObjectPropTime1(obj.objs[i].chartId, obj.objs[i].id)\n\t\t\t\t\t\t\t\t\t\t\t} else if (property_index == 1) { // OBJPROP_PRICE1\n\t\t\t\t\t\t\t\t\t\t\t\treturn getObjectPropPrice1(obj.objs[i].chartId, obj.objs[i].id)\n\t\t\t\t\t\t\t\t\t\t\t} else if (property_index == 2) { // OBJPROP_TIME2\n\t\t\t\t\t\t\t\t\t\t\t\treturn getObjectPropTime2(obj.objs[i].chartId, obj.objs[i].id)\n\t\t\t\t\t\t\t\t\t\t\t} else if (property_index == 3) { // OBJPROP_PRICE2\n\t\t\t\t\t\t\t\t\t\t\t\treturn getObjectPropPrice2(obj.objs[i].chartId, obj.objs[i].id)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn -1\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jObjectSet = Module.addFunction(function (uid, object_name, property_index, property_value) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar name = window.mqlEAs[obj.name].module.UTF8ToString(object_name)\n\t\t\t\t\t\t\t\t\tfor (var i = obj.objs.length - 1; i >= 0; i--) {\n\t\t\t\t\t\t\t\t\t\tif (obj.objs[i].name == name) {\n\t\t\t\t\t\t\t\t\t\t\tif (property_index == 0) { // OBJPROP_TIME1\n\t\t\t\t\t\t\t\t\t\t\t\tif (setObjectPropTime1(obj.objs[i].chartId, obj.objs[i].id, property_value)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else if (property_index == 1) { // OBJPROP_PRICE1\n\t\t\t\t\t\t\t\t\t\t\t\tif (setObjectPropPrice1(obj.objs[i].chartId, obj.objs[i].id, property_value)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else if (property_index == 2) { // OBJPROP_TIME2\n\t\t\t\t\t\t\t\t\t\t\t\tif (setObjectPropTime2(obj.objs[i].chartId, obj.objs[i].id, property_value)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else if (property_index == 3) { // OBJPROP_PRICE2\n\t\t\t\t\t\t\t\t\t\t\t\tif (setObjectPropPrice2(obj.objs[i].chartId, obj.objs[i].id, property_value)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t}, \"iiiid\")\n\t\t\t\t\t\t\t\tvar jIsTesting = Module.addFunction(function () {\n\t\t\t\t\t\t\t\t\treturn isTesting() ? 1 : 0\n\t\t\t\t\t\t\t\t}, \"i\")\n\t\t\t\t\t\t\t\tvar jMarketInfo = Module.addFunction(function (uid, symbol, type) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t\tvar symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol)\n\t\t\t\t\t\t\t\t\tvar symbolObj = null\n\t\t\t\t\t\t\t\t\tif (symbolName == \"\") {\n\t\t\t\t\t\t\t\t\t\tsymbolObj = obj.symbol\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tsymbolObj = getSymbolInfo(obj.brokerName, obj.accountId, symbolName)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (type == 11) {\n\t\t\t\t\t\t\t\t\t\treturn 1.0 / symbolObj.toFixed\n\t\t\t\t\t\t\t\t\t} else if (type == 12) {\n\t\t\t\t\t\t\t\t\t\treturn Math.log10(symbolObj.toFixed)\n\t\t\t\t\t\t\t\t\t} else if (type == 18) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.swapLong\n\t\t\t\t\t\t\t\t\t} else if (type == 19) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.swapShort\n\t\t\t\t\t\t\t\t\t} else if (type == 22) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.tradable\n\t\t\t\t\t\t\t\t\t} else if (type == 23) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.lotsMinLimit\n\t\t\t\t\t\t\t\t\t} else if (type == 24) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.lotsStep\n\t\t\t\t\t\t\t\t\t} else if (type == 25) {\n\t\t\t\t\t\t\t\t\t\treturn symbolObj.lotsLimit\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tprintErrorMessage(\"Not supported the specific market information currently!\")\n\t\t\t\t\t\t\t\t\treturn -1\n\t\t\t\t\t\t\t\t}, \"diii\")\n\t\t\t\t\t\t\t\tvar jCreateNeuralNetwork = Module.addFunction(function (uid, name, nnJson) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t  var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name)\n\t\t\t\t\t\t\t\t\tvar neuralNetworkJson = window.mqlEAs[obj.name].module.UTF8ToString(nnJson)\n\t\t\t\t\t\t\t\t\tif (nnName != \"\" && neuralNetworkJson != \"\" && typeof obj.neuralNetworks[nnName] == \"undefined\") {\n\t\t\t\t\t\t\t\t\t\tobj.neuralNetworks[nnName] = {\n\t\t\t\t\t\t\t\t\t\t\tperceptron: synaptic.Network.fromJSON(JSON.parse(neuralNetworkJson))\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn 1\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"iiii\")\n\t\t\t\t\t\t\t\tvar jActivateNeuralNetwork = Module.addFunction(function (uid, name, input, inputNum) {\n\t\t\t\t\t\t\t\t\tvar obj = window.mqlEAsBuffer[uid + \"\"]\n\t\t\t\t\t\t\t\t  var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name)\n\t\t\t\t\t\t\t\t  var nByteDouble = 8\n\t\t\t\t\t\t\t\t  var data = new Array(inputNum)\n\t\t\t\t\t\t\t\t  for (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\t    data[i] = window.mqlEAs[obj.name].module.getValue(input + i * nByteDouble, \"double\")\n\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t  if (typeof obj.neuralNetworks[nnName] != \"undefined\" && typeof obj.neuralNetworks[nnName].perceptron != \"undefined\") {\n\t\t\t\t\t\t\t\t    return obj.neuralNetworks[nnName].perceptron.activate(data)[0]\n\t\t\t\t\t\t\t\t  } else {\n\t\t\t\t\t\t\t\t\t\treturn 0.5\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, \"diiii\")\n\n\t\t\t\t\t\t    window.mqlEAs[definition.name] = {\n\t\t\t\t\t\t\t\t\tdefinition: definition,\n\t\t\t\t\t\t\t\t\tmodule: Module,\n\t\t\t\t\t\t\t\t\tsetParamInt: Module.cwrap(\"setParamInt\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetParamDouble: Module.cwrap(\"setParamDouble\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetParamBool: Module.cwrap(\"setParamBool\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetParamString: Module.cwrap(\"setParamString\", null, [\"number\", \"string\"]),\n\t\t\t\t\t\t\t\t\tonInit: Module.cwrap(\"onInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tonDeinit: Module.cwrap(\"onDeinit\", null, [\"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tonTick: Module.cwrap(\"onTick\", null, [\"number\", \"number\", \"number\", \"number\", \"number\", \"number\"]),\n\t\t\t\t\t\t\t\t\tsetjPrint: Module.cwrap(\"setjPrint\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartClose: Module.cwrap(\"setjChartClose\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartID: Module.cwrap(\"setjChartID\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartOpen: Module.cwrap(\"setjChartOpen\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartPeriod: Module.cwrap(\"setjChartPeriod\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjChartSymbol: Module.cwrap(\"setjChartSymbol\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjPeriod: Module.cwrap(\"setjPeriod\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjSymbol: Module.cwrap(\"setjSymbol\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountBalance: Module.cwrap(\"setjAccountBalance\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountCompany: Module.cwrap(\"setjAccountCompany\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountCurrency: Module.cwrap(\"setjAccountCurrency\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountEquity: Module.cwrap(\"setjAccountEquity\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountFreeMargin: Module.cwrap(\"setjAccountFreeMargin\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountMargin: Module.cwrap(\"setjAccountMargin\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjAccountProfit: Module.cwrap(\"setjAccountProfit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrdersTotal: Module.cwrap(\"setjOrdersTotal\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrdersHistoryTotal: Module.cwrap(\"setjOrdersHistoryTotal\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderSelect: Module.cwrap(\"setjOrderSelect\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderOpenPrice: Module.cwrap(\"setjOrderOpenPrice\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderType: Module.cwrap(\"setjOrderType\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderTakeProfit: Module.cwrap(\"setjOrderTakeProfit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderStopLoss: Module.cwrap(\"setjOrderStopLoss\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderLots: Module.cwrap(\"setjOrderLots\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderProfit: Module.cwrap(\"setjOrderProfit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderSymbol: Module.cwrap(\"setjOrderSymbol\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderTicket: Module.cwrap(\"setjOrderTicket\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderMagicNumber: Module.cwrap(\"setjOrderMagicNumber\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderOpenTime: Module.cwrap(\"setjOrderOpenTime\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderComment: Module.cwrap(\"setjOrderComment\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderExpiration: Module.cwrap(\"setjOrderExpiration\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjOrderPrint: Module.cwrap(\"setjOrderPrint\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiTimeInit: Module.cwrap(\"setjiTimeInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiTime: Module.cwrap(\"setjiTime\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiOpenInit: Module.cwrap(\"setjiOpenInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiOpen: Module.cwrap(\"setjiOpen\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiHighInit: Module.cwrap(\"setjiHighInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiHigh: Module.cwrap(\"setjiHigh\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiLowInit: Module.cwrap(\"setjiLowInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiLow: Module.cwrap(\"setjiLow\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCloseInit: Module.cwrap(\"setjiCloseInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiClose: Module.cwrap(\"setjiClose\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiVolumeInit: Module.cwrap(\"setjiVolumeInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiVolume: Module.cwrap(\"setjiVolume\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiHighest: Module.cwrap(\"setjiHighest\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiLowest: Module.cwrap(\"setjiLowest\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiACInit: Module.cwrap(\"setjiACInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAC: Module.cwrap(\"setjiAC\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiADXInit: Module.cwrap(\"setjiADXInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiADX: Module.cwrap(\"setjiADX\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAlligatorInit: Module.cwrap(\"setjiAlligatorInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAlligator: Module.cwrap(\"setjiAlligator\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAOInit: Module.cwrap(\"setjiAOInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiAO: Module.cwrap(\"setjiAO\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiATRInit: Module.cwrap(\"setjiATRInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiATR: Module.cwrap(\"setjiATR\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBearsPowerInit: Module.cwrap(\"setjiBearsPowerInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBearsPower: Module.cwrap(\"setjiBearsPower\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBandsInit: Module.cwrap(\"setjiBandsInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBands: Module.cwrap(\"setjiBands\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBandsOnArray: Module.cwrap(\"setjiBandsOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBullsPowerInit: Module.cwrap(\"setjiBullsPowerInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiBullsPower: Module.cwrap(\"setjiBullsPower\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCCIInit: Module.cwrap(\"setjiCCIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCCI: Module.cwrap(\"setjiCCI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCCIOnArray: Module.cwrap(\"setjiCCIOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCustomInit: Module.cwrap(\"setjiCustomInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiCustom: Module.cwrap(\"setjiCustom\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiDeMarkerInit: Module.cwrap(\"setjiDeMarkerInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiDeMarker: Module.cwrap(\"setjiDeMarker\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiEnvelopesInit: Module.cwrap(\"setjiEnvelopesInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiEnvelopes: Module.cwrap(\"setjiEnvelopes\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiEnvelopesOnArray: Module.cwrap(\"setjiEnvelopesOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiFractalsInit: Module.cwrap(\"setjiFractalsInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiFractals: Module.cwrap(\"setjiFractals\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiIchimokuInit: Module.cwrap(\"setjiIchimokuInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiIchimoku: Module.cwrap(\"setjiIchimoku\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMAInit: Module.cwrap(\"setjiMAInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMA: Module.cwrap(\"setjiMA\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMAOnArray: Module.cwrap(\"setjiMAOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMACDInit: Module.cwrap(\"setjiMACDInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMACD: Module.cwrap(\"setjiMACD\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMFIInit: Module.cwrap(\"setjiMFIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMFI: Module.cwrap(\"setjiMFI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMomentumInit: Module.cwrap(\"setjiMomentumInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMomentum: Module.cwrap(\"setjiMomentum\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiMomentumOnArray: Module.cwrap(\"setjiMomentumOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRSIInit: Module.cwrap(\"setjiRSIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRSI: Module.cwrap(\"setjiRSI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRSIOnArray: Module.cwrap(\"setjiRSIOnArray\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRVIInit: Module.cwrap(\"setjiRVIInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiRVI: Module.cwrap(\"setjiRVI\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiSARInit: Module.cwrap(\"setjiSARInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiSAR: Module.cwrap(\"setjiSAR\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiStochasticInit: Module.cwrap(\"setjiStochasticInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiStochastic: Module.cwrap(\"setjiStochastic\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiWPRInit: Module.cwrap(\"setjiWPRInit\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjiWPR: Module.cwrap(\"setjiWPR\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjObjectCreate: Module.cwrap(\"setjObjectCreate\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjObjectDelete: Module.cwrap(\"setjObjectDelete\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjObjectGet: Module.cwrap(\"setjObjectGet\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjObjectSet: Module.cwrap(\"setjObjectSet\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjIsTesting: Module.cwrap(\"setjIsTesting\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjMarketInfo: Module.cwrap(\"setjMarketInfo\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjCreateNeuralNetwork: Module.cwrap(\"setjCreateNeuralNetwork\", null, [\"number\"]),\n\t\t\t\t\t\t\t\t\tsetjActivateNeuralNetwork: Module.cwrap(\"setjActivateNeuralNetwork\", null, [\"number\"])\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjPrint(jPrint)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjChartClose(jChartClose)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjChartID(jChartID)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjChartOpen(jChartOpen)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjChartPeriod(jChartPeriod)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjChartSymbol(jChartSymbol)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjPeriod(jPeriod)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjSymbol(jSymbol)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountBalance(jAccountBalance)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountCompany(jAccountCompany)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountCurrency(jAccountCurrency)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountEquity(jAccountEquity)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountFreeMargin(jAccountFreeMargin)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountMargin(jAccountMargin)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjAccountProfit(jAccountProfit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrdersTotal(jOrdersTotal)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrdersHistoryTotal(jOrdersHistoryTotal)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderSelect(jOrderSelect)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderOpenPrice(jOrderOpenPrice)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderType(jOrderType)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderTakeProfit(jOrderTakeProfit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderStopLoss(jOrderStopLoss)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderLots(jOrderLots)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderProfit(jOrderProfit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderSymbol(jOrderSymbol)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderTicket(jOrderTicket)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderMagicNumber(jOrderMagicNumber)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderOpenTime(jOrderOpenTime)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderComment(jOrderComment)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderExpiration(jOrderExpiration)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjOrderPrint(jOrderPrint)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiTimeInit(jiTimeInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiTime(jiTime)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiOpenInit(jiOpenInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiOpen(jiOpen)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiHighInit(jiHighInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiHigh(jiHigh)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiLowInit(jiLowInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiLow(jiLow)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiCloseInit(jiCloseInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiClose(jiClose)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiVolumeInit(jiVolumeInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiVolume(jiVolume)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiHighest(jiHighest)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiLowest(jiLowest)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiACInit(jiACInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiAC(jiAC)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiADXInit(jiADXInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiADX(jiADX)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiAlligatorInit(jiAlligatorInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiAlligator(jiAlligator)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiAOInit(jiAOInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiAO(jiAO)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiATRInit(jiATRInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiATR(jiATR)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBearsPowerInit(jiBearsPowerInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBearsPower(jiBearsPower)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBandsInit(jiBandsInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBands(jiBands)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBandsOnArray(jiBandsOnArray)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBullsPowerInit(jiBullsPowerInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiBullsPower(jiBullsPower)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiCCIInit(jiCCIInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiCCI(jiCCI)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiCCIOnArray(jiCCIOnArray)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiCustomInit(jiCustomInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiCustom(jiCustom)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiDeMarkerInit(jiDeMarkerInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiDeMarker(jiDeMarker)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiEnvelopesInit(jiEnvelopesInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiEnvelopes(jiEnvelopes)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiEnvelopesOnArray(jiEnvelopesOnArray)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiFractalsInit(jiFractalsInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiFractals(jiFractals)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiIchimokuInit(jiIchimokuInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiIchimoku(jiIchimoku)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMAInit(jiMAInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMA(jiMA)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMAOnArray(jiMAOnArray)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMACDInit(jiMACDInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMACD(jiMACD)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMFIInit(jiMFIInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMFI(jiMFI)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMomentumInit(jiMomentumInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMomentum(jiMomentum)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiMomentumOnArray(jiMomentumOnArray)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiRSIInit(jiRSIInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiRSI(jiRSI)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiRSIOnArray(jiRSIOnArray)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiRVIInit(jiRVIInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiRVI(jiRVI)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiSARInit(jiSARInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiSAR(jiSAR)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiStochasticInit(jiStochasticInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiStochastic(jiStochastic)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiWPRInit(jiWPRInit)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjiWPR(jiWPR)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjObjectCreate(jObjectCreate)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjObjectDelete(jObjectDelete)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjObjectGet(jObjectGet)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjObjectSet(jObjectSet)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjIsTesting(jIsTesting)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjMarketInfo(jMarketInfo)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjCreateNeuralNetwork(jCreateNeuralNetwork)\n\t\t\t\t\t\t\t\twindow.mqlEAs[definition.name].setjActivateNeuralNetwork(jActivateNeuralNetwork)\n\n\t\t\t\t\t\t\t\trs(definition)\n\t\t\t\t\t\t\t}) // Module[\"onRuntimeInitialized\"]\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(function () {\n\t\t\t\t\t\t\trj()\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tsaveMqlEA: function (definition, bAdd) {\n\t\t\t\t\tif (typeof localStorage.reservedZone == \"undefined\") {\n\t\t\t\t\t\tif (bAdd) {\n\t\t\t\t\t\t\tlocalStorage.reservedZone = JSON.stringify({allMqlEAs: [definition]})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\t\t\t\t\t\tif (typeof reservedZone.allMqlEAs == \"undefined\") {\n\t\t\t\t\t\t\tif (bAdd) {\n\t\t\t\t\t\t\t\treservedZone.allMqlEAs = [definition]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (var i in reservedZone.allMqlEAs) {\n\t\t\t\t\t\t\t\tif (reservedZone.allMqlEAs[i].name == definition.name) {\n\t\t\t\t\t\t\t\t\treservedZone.allMqlEAs.splice(i, 1)\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (bAdd) {\n\t\t\t\t\t\t\t\treservedZone.allMqlEAs.push(definition)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlocalStorage.reservedZone = JSON.stringify(reservedZone)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tremoveScript: function (url) {\n\t\t\t\t\tvar tags = document.getElementsByTagName(\"script\")\n\t\t\t\t\tfor (var i = tags.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tif (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == url) {\n\t\t\t\t\t\t\ttags[i].parentNode.removeChild(tags[i])\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tloadMqlPrograms: function () {\n\t\t\t\t\tvar mqlPrograms = []\n\n\t\t\t\t\tif (typeof localStorage.reservedZone != \"undefined\") {\n\t\t\t\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\n\t\t\t\t\t\tif (typeof reservedZone.allMqlIndis != \"undefined\") {\n\t\t\t\t\t\t\tvar mqlIndicatorsLoaded = (typeof window.mqlIndicators != \"undefined\" ? true : false)\n\t\t\t\t\t\t\tvar allMqlIndis = reservedZone.allMqlIndis\n\n\t\t\t\t\t\t\tfor (var i in allMqlIndis) {\n\t\t\t\t\t\t\t\tvar mqlIndi = allMqlIndis[i]\n\t\t\t\t\t\t\t\tmqlPrograms.push({\n\t\t\t\t\t\t\t\t\tname: mqlIndi.name,\n\t\t\t\t\t\t\t\t\tdescription: mqlIndi.description,\n\t\t\t\t\t\t\t\t\ttype: \"Indicator\",\n\t\t\t\t\t\t\t\t\tloaded: ((mqlIndicatorsLoaded && typeof window.mqlIndicators[mqlIndi.name] != \"undefined\") ? true : false)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (typeof reservedZone.allMqlEAs != \"undefined\") {\n\t\t\t\t\t\t\tvar mqlEAsLoaded = (typeof window.mqlEAs != \"undefined\" ? true : false)\n\t\t\t\t\t\t\tvar allMqlEAs = reservedZone.allMqlEAs\n\n\t\t\t\t\t\t\tfor (var i in allMqlEAs) {\n\t\t\t\t\t\t\t\tvar mqlEA = allMqlEAs[i]\n\t\t\t\t\t\t\t\tmqlPrograms.push({\n\t\t\t\t\t\t\t\t\tname: mqlEA.name,\n\t\t\t\t\t\t\t\t\tdescription: mqlEA.description,\n\t\t\t\t\t\t\t\t\ttype: \"EA\",\n\t\t\t\t\t\t\t\t\tloaded: ((mqlEAsLoaded && typeof window.mqlEAs[mqlEA.name] != \"undefined\") ? true : false)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn mqlPrograms\n\t\t\t\t},\n\t\t\t\tshowMqlPrograms: function (mqlPrograms) {\n\t\t\t\t\t$(\"#mql_based_programs_list\").DataTable().clear().draw()\n\n\t\t\t\t\tfor (var i in mqlPrograms) {\n\t\t\t\t\t\tvar mqlProgram = mqlPrograms[i]\n\n\t\t\t\t\t\tvar row = $(\"#mql_based_programs_list\").DataTable().row.add([\n\t\t\t\t\t\t\tmqlProgram.name,\n\t\t\t\t\t\t\tmqlProgram.description,\n\t\t\t\t\t\t\tmqlProgram.type,\n\t\t\t\t\t\t\tmqlProgram.loaded ? \"Loaded\" : \"\"\n\t\t\t\t\t\t]).draw(false)\n\t\t\t\t\t}\n\t      },\n\t\t\t\tshowAddedMqlProgram: function (mqlProgram, type) {\n\t\t\t\t\tvar data = $(\"#mql_based_programs_list\").DataTable().rows().data()\n\t\t\t\t\tvar rowId = -1\n\t\t\t\t\tfor (var i in data) {\n\t\t\t\t\t\tif (data[i][0] == mqlProgram.name && data[i][2] == type) {\n\t\t\t\t\t\t\trowId = parseInt(i)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rowId != -1) {\n\t\t\t\t\t\t$(\"#mql_based_programs_list\").dataTable().fnUpdate(\"Loaded\", rowId, 3, false, false)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(\"#mql_based_programs_list\").DataTable().row.add([\n\t\t\t\t\t\t\tmqlProgram.name,\n\t\t\t\t\t\t\tmqlProgram.description,\n\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\"Loaded\"\n\t\t\t\t\t\t]).draw(false)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tshowMqlProgramNewState: function (name, type, state) {\n\t\t\t\t\tvar data = $(\"#mql_based_programs_list\").DataTable().rows().data()\n\t\t\t\t\tvar rowId = -1\n\t\t\t\t\tfor (var i in data) {\n\t\t\t\t\t\tif (data[i][0] == name && data[i][2] == type) {\n\t\t\t\t\t\t\trowId = parseInt(i)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rowId != -1) {\n\t\t\t\t\t\t$(\"#mql_based_programs_list\").dataTable().fnUpdate(state, rowId, 3, false, false)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tremoveMqlProgram: function (name, type) {\n\t\t\t\t\tvar data = $(\"#mql_based_programs_list\").DataTable().rows().data()\n\t\t\t\t\tvar rowId = -1\n\t\t\t\t\tfor (var i in data) {\n\t\t\t\t\t\tif (data[i][0] == name && data[i][2] == type) {\n\t\t\t\t\t\t\trowId = parseInt(i)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rowId != -1) {\n\t\t\t\t\t\t$(\"#mql_based_programs_list\").dataTable().fnDeleteRow(rowId)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetSelected: function () {\n\t\t\t\t\tvar selected = []\n\t\t\t\t\tvar mqlPrograms = $(\"#mql_based_programs_list\").DataTable().rows(\".selected\").data().toArray()\n\t\t\t\t\tfor (var i in mqlPrograms) {\n\t\t\t\t\t\tselected.push({\n\t\t\t\t\t\t\tname: mqlPrograms[i][0],\n\t\t\t\t\t\t\ttype: mqlPrograms[i][2]\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\treturn selected\n\t\t\t\t},\n\t\t\t\tloadSelected: function (selected) {\n\t\t\t\t\tvar allMqlIndis = []\n\t\t\t\t\tvar allMqlEAs = []\n\n\t\t\t\t\tif (typeof localStorage.reservedZone != \"undefined\") {\n\t\t\t\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\t\t\t\t\t\tif (typeof reservedZone.allMqlIndis != \"undefined\") {\n\t\t\t\t\t\t\tallMqlIndis = reservedZone.allMqlIndis\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (typeof reservedZone.allMqlEAs != \"undefined\") {\n\t\t\t\t\t\t\tallMqlEAs = reservedZone.allMqlEAs\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tvar that = this\n\n\t\t\t\t\tfor (var i in selected) {\n\t\t\t\t\t\tvar sel = selected[i]\n\t\t\t\t\t\tif (sel.type == \"Indicator\") {\n\t\t\t\t\t\t\tfor (var j in allMqlIndis) {\n\t\t\t\t\t\t\t\tvar mqlIndi = allMqlIndis[j]\n\t\t\t\t\t\t\t\tif (sel.name == mqlIndi.name) {\n\t\t\t\t\t\t\t\t\tthis.loadMqlIndicator(mqlIndi)\n\t\t\t\t\t\t\t\t\t.then(function (definition) {\n\t\t\t\t\t\t\t\t\t\tthat.showMqlProgramNewState(definition.name, \"Indicator\", \"Loaded\")\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.catch(function () {})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (sel.type == \"EA\") {\n\t\t\t\t\t\t\tfor (var j in allMqlEAs) {\n\t\t\t\t\t\t\t\tvar mqlEA = allMqlEAs[j]\n\t\t\t\t\t\t\t\tif (sel.name == mqlEA.name) {\n\t\t\t\t\t\t\t\t\tthis.loadMqlEA(mqlEA)\n\t\t\t\t\t\t\t\t\t.then(function (definition) {\n\t\t\t\t\t\t\t\t\t\tthat.showMqlProgramNewState(definition.name, \"EA\", \"Loaded\")\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.catch(function () {})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tremoveSelected: function (selected) {\n\t\t\t\t\tvar allMqlIndis = []\n\t\t\t\t\tvar allMqlEAs = []\n\n\t\t\t\t\tif (typeof localStorage.reservedZone != \"undefined\") {\n\t\t\t\t\t\tvar reservedZone = JSON.parse(localStorage.reservedZone)\n\t\t\t\t\t\tif (typeof reservedZone.allMqlIndis != \"undefined\") {\n\t\t\t\t\t\t\tallMqlIndis = reservedZone.allMqlIndis\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (typeof reservedZone.allMqlEAs != \"undefined\") {\n\t\t\t\t\t\t\tallMqlEAs = reservedZone.allMqlEAs\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tvar that = this\n\n\t\t\t\t\tfor (var i in selected) {\n\t\t\t\t\t\tvar sel = selected[i]\n\t\t\t\t\t\tif (sel.type == \"Indicator\") {\n\t\t\t\t\t\t\tfor (var j in allMqlIndis) {\n\t\t\t\t\t\t\t\tvar mqlIndi = allMqlIndis[j]\n\t\t\t\t\t\t\t\tif (sel.name == mqlIndi.name) {\n\t\t\t\t\t\t\t\t\tthat.removeMqlIndicator(mqlIndi.name)\n\t\t\t\t\t\t\t\t\tthat.removeMqlProgram(mqlIndi.name, \"Indicator\")\n\t\t\t\t\t\t\t\t\tthat.saveMqlIndicator(mqlIndi, false)\n\t\t\t\t\t\t\t\t\tthat.removeScript(mqlIndi.url)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (sel.type == \"EA\") {\n\t\t\t\t\t\t\tfor (var j in allMqlEAs) {\n\t\t\t\t\t\t\t\tvar mqlEA = allMqlEAs[j]\n\t\t\t\t\t\t\t\tif (sel.name == mqlEA.name) {\n\t\t\t\t\t\t\t\t\tthat.removeMqlEA(mqlEA.name)\n\t\t\t\t\t\t\t\t\tthat.removeMqlProgram(mqlEA.name, \"EA\")\n\t\t\t\t\t\t\t\t\tthat.saveMqlEA(mqlEA, false)\n\t\t\t\t\t\t\t\t\tthat.removeScript(mqlEA.url)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tinit: function () {\n\t\t\t\t\tvar that = this\n\n\t\t\t\t\tif (typeof $(\"#mql_based_programs_dashboard\").html() == \"undefined\") {\n\t\t        var panel = '<div class=\"ui form modal\" id=\"mql_based_programs_dashboard\">' +\n\t\t          '<div class=\"content\">' +\n\t\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"mqlIndiDefinition\" placeholder=\"Indicator Definition\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"add_mql_indicator\" class=\"ui button\" style=\"width:130px\">Add Indicator</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'<div class=\"row\" style=\"margin-top:2px\">' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"mqlEADefinition\" placeholder=\"EA Definition\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"add_mql_ea\" class=\"ui button\" style=\"width:130px\">Add EA</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t            '<div class=\"description\">' +\n\t\t              '<table id=\"mql_based_programs_list\" class=\"cell-border\" cellspacing=\"0\">' +\n\t\t        \t\t\t'</table>' +\n\t\t            '</div>' +\n\t\t          '</div>' +\n\t\t          '<div class=\"actions\">' +\n\t\t            '<div class=\"ui button\" id=\"load_mql_programs\">Load</div>' +\n\t\t\t\t\t\t\t\t'<div class=\"ui button\" id=\"remove_mql_programs\">Remove</div>' +\n\t\t\t\t\t\t\t\t'<div class=\"ui button\" id=\"close_mql_dashboard\">Close</div>' +\n\t\t          '</div>' +\n\t\t        '</div>'\n\n\t\t\t\t\t\t$(\"#reserved_zone\").append(panel)\n\n\t\t\t\t\t\t$(\"#add_mql_indicator\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar def = $(\"#mqlIndiDefinition\").val().trim()\n\n\t\t\t\t\t\t\tif (def != \"\") {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tthat.loadMqlIndicator(JSON.parse(def))\n\t\t\t\t\t\t\t\t\t.then(function (definition) {\n\t\t\t\t\t\t\t\t\t\tthat.createMqlIndicator(definition)\n\t\t\t\t\t\t\t\t\t\tthat.showAddedMqlProgram(definition, \"Indicator\")\n\t\t\t\t\t\t\t\t\t\tthat.saveMqlIndicator(definition, true)\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.catch(function () {})\n\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\tpopupErrorMessage(e.message)\n\t\t\t\t\t\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#add_mql_ea\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar def = $(\"#mqlEADefinition\").val().trim()\n\n\t\t\t\t\t\t\tif (def != \"\") {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tthat.loadMqlEA(JSON.parse(def))\n\t\t\t\t\t\t\t\t\t.then(function (definition) {\n\t\t\t\t\t\t\t\t\t\tthat.createMqlEA(definition)\n\t\t\t\t\t\t\t\t\t\tthat.showAddedMqlProgram(definition, \"EA\")\n\t\t\t\t\t\t\t\t\t\tthat.saveMqlEA(definition, true)\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.catch(function () {})\n\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\tpopupErrorMessage(e.message)\n\t\t\t\t\t\t\t\t\tprintErrorMessage(e.message)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#load_mql_programs\").on(\"click\", function () {\n\t\t\t\t\t\t\tthat.loadSelected(that.getSelected())\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#remove_mql_programs\").on(\"click\", function () {\n\t\t\t\t\t\t\tthat.removeSelected(that.getSelected())\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#close_mql_dashboard\").on(\"click\", function () {\n\t\t\t\t\t\t\t$(\"#mql_based_programs_dashboard\").modal(\"hide\")\n\t\t\t\t\t\t})\n\t\t      }\n\n\t\t      if (!$.fn.dataTable.isDataTable(\"#mql_based_programs_list\")) {\n\t\t  \t\t\t$(\"#mql_based_programs_list\").DataTable({\n\t\t  \t\t\t\tdata: [],\n\t\t  \t\t\t\tcolumns: [\n\t\t  \t\t\t\t\t{title: \"Name\"},\n\t\t  \t\t\t\t\t{title: \"Description\"},\n\t\t            {title: \"Type\"},\n\t\t\t\t\t\t\t\t{title: \"State\"}\n\t\t  \t\t\t\t],\n\t\t          ordering: false,\n\t\t          searching: false,\n\t\t          bPaginate: false,\n\t\t          bLengthChange: false,\n\t\t          bFilter: false,\n\t\t          bInfo: false,\n\t\t          scrollY: '50vh',\n\t\t          scrollCollapse: true,\n\t\t          paging: false,\n\t\t          columnDefs: [\n\t\t            {width: \"20%\", targets: 0, className: \"dt-body-left\"},\n\t\t            {width: \"50%\", targets: 1, className: \"dt-body-left\"},\n\t\t            {width: \"15%\", targets: 2, className: \"dt-body-left\"},\n\t\t\t\t\t\t\t\t{width: \"15%\", targets: 2, className: \"dt-body-left\"},\n\t\t            {targets: [0, 1, 2, 3], className: \"dt-head-left\"}\n\t\t          ]\n\t\t  \t\t\t})\n\n\t\t\t\t\t\t$(\"#mql_based_programs_list tbody\").on(\"click\", \"tr\", function () {\n\t\t\t\t\t\t\t$(this).toggleClass(\"selected\")\n\t\t\t\t\t\t})\n\t\t  \t\t}\n\n\t\t\t\t\tthis.showMqlPrograms(this.loadMqlPrograms())\n\n\t\t\t\t\t$(\"#mql_based_programs_dashboard\").modal({autofocus:false}).modal(\"show\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\twindow.pluginForMql.init()\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-MQL/runtestcnn.cpp",
    "content": "#define INPUT_NUM 10\n#define HIDDEN_NUM 10\n#define NN_NAME \"testcnn\"\n\ninput string ext_strSymbol = \"EUR/USD\";\ninput int ext_iPeriod = 60;\ninput double ext_dblVolume = 0.01;\n\ndatetime currTime = 0;\n\nint cntL = 0;\nint cntS = 0;\ndouble totalPlL = 0;\ndouble totalPlS = 0;\ndouble highestPriceL = -DBL_MAX;\ndouble lowestPriceL = DBL_MAX;\ndouble highestPriceS = -DBL_MAX;\ndouble lowestPriceS = DBL_MAX;\n\ndatetime upTime = 0;\ndatetime downTime = 0;\ndatetime prevClsUpTime = 0;\ndatetime prevClsDownTime = 0;\n\nvoid getPosInfo(datetime currTime) {\n  cntL = 0;\n  cntS = 0;\n  totalPlL = 0;\n  totalPlS = 0;\n  highestPriceL = -DBL_MAX;\n  lowestPriceL = DBL_MAX;\n  highestPriceS = -DBL_MAX;\n  lowestPriceS = DBL_MAX;\n\n  int cnt = OrdersTotal();\n  for (int i = cnt - 1; i >= 0; i--) {\n    if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) return;\n\n    if (StringCompare(Symbol(), OrderSymbol()) == 0) {\n      double openPrice = OrderOpenPrice();\n      datetime openTime = OrderOpenTime();\n\n      if (OrderType() == OP_BUY) {\n        cntL++;\n        totalPlL += OrderProfit();\n        if (openPrice > highestPriceL) {\n          highestPriceL = openPrice;\n        }\n        if (openPrice < lowestPriceL) {\n          lowestPriceL = openPrice;\n        }\n\n        if (openTime > currTime) {\n          upTime = currTime;\n        }\n      }\n      if (OrderType() == OP_SELL) {\n        cntS++;\n        totalPlS += OrderProfit();\n        if (openPrice > highestPriceS) {\n          highestPriceS = openPrice;\n        }\n        if (openPrice < lowestPriceS) {\n          lowestPriceS = openPrice;\n        }\n\n        if (openTime > currTime) {\n          downTime = currTime;\n        }\n      }\n    }\n  }\n}\n\nbool trade(int odrType, double volume, bool bOpen) {\n  bool res = false;\n\n  if (bOpen) {\n    if (odrType == OP_BUY) {\n      OrderSend(ext_strSymbol, OP_BUY, volume, 0, 0, 0, 0, \"\", 0, 0, Green);\n      res = true;\n    } else if (odrType == OP_SELL) {\n      OrderSend(ext_strSymbol, OP_SELL, volume, 0, 0, 0, 0, \"\", 0, 0, Red);\n      res = true;\n    }\n  } else {\n    bool bClosed = false;\n\n    if (odrType == OP_BUY) {\n      int cnt = OrdersTotal();\n\n      for (int i = cnt - 1; i >= 0; i--) {\n        if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) return false;\n\n        if (StringCompare(Symbol(), OrderSymbol()) == 0 && OrderType() == OP_BUY) {\n          OrderClose(OrderTicket(), volume, 0, 0, Green);\n          bClosed = true;\n        }\n      }\n    } else if (odrType == OP_SELL) {\n      int cnt = OrdersTotal();\n\n      for (int i = cnt - 1; i >= 0; i--) {\n        if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) return false;\n\n        if (StringCompare(Symbol(), OrderSymbol()) == 0 && OrderType() == OP_SELL) {\n          OrderClose(OrderTicket(), volume, 0, 0, Red);\n          bClosed = true;\n        }\n      }\n    }\n\n    if (bClosed) {\n      res = true;\n    }\n  }\n\n  return res;\n}\n\nint OnInit (void) {\n  PreventCleanUp();\n  LoadCNN(NN_NAME);\n  return 0;\n}\n\nvoid OnTick(void) {\n  if (currTime == iTime(ext_strSymbol, ext_iPeriod, 0)) return;\n  currTime = iTime(ext_strSymbol, ext_iPeriod, 0);\n\n  double arr[INPUT_NUM];\n  double highest = -DBL_MAX;\n  double lowest = DBL_MAX;\n  for (int i = 1; i <= INPUT_NUM; i++) {\n    arr[i - 1] = iMACD(ext_strSymbol, ext_iPeriod, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, i);\n    if (arr[i - 1] > highest) {\n      highest = arr[i - 1];\n    }\n    if (arr[i - 1] < lowest) {\n      lowest = arr[i - 1];\n    }\n  }\n  double height = highest - lowest;\n  if (height <= 0) return;\n\n  double input[INPUT_NUM];\n\n  for (int i = 0; i < INPUT_NUM; i++) {\n    input[i] = (arr[i] - lowest) / height;\n  }\n\n  double result = RunCNN(NN_NAME, input, INPUT_NUM);\n  int signal = result >= 0.5 ? 1 : 0;\n\n  getPosInfo(currTime);\n\n  if (upTime > 0 || downTime > 0) {\n    if (signal == 1) {\n      if (trade(OP_SELL, ext_dblVolume, false)) {\n        downTime = 0;\n      }\n    } else {\n      if (trade(OP_BUY, ext_dblVolume, false)) {\n        upTime = 0;\n      }\n    }\n\n    return;\n  }\n\n  if (signal == 1) {\n    if (trade(OP_BUY, ext_dblVolume, true)) {\n      upTime = currTime;\n    }\n  } else {\n    if (trade(OP_SELL, ext_dblVolume, true)) {\n      downTime = currTime;\n    }\n  }\n}\n\nvoid OnDeinit (const int) {\n}\n"
  },
  {
    "path": "EA/Plugin-for-MQL/testcnn.cpp",
    "content": "#define ARR_NUM 1001\n#define INPUT_NUM 10\n#define HIDDEN_NUM 10\n#define NN_NAME \"testcnn\"\n#define ITERATIONS 1000\n#define BATCH_SIZE 512\n\ninput string ext_strSymbol = \"EUR/USD\";\ninput int ext_iPeriod = 60;\ninput bool ext_bTrain = true; // if testing, set false to it\n\ndouble macdArr[ARR_NUM * INPUT_NUM];\ndouble oArr[ARR_NUM];\nint cursor = 0;\ndatetime currTime = 0;\n\nint OnInit (void) {\n  PreventCleanUp();\n  for (int i = 0; i < ARR_NUM * INPUT_NUM; i++) {\n    macdArr[i] = 0;\n  }\n  for (int i = 0; i < ARR_NUM; i++) {\n    oArr[i] = 0;\n  }\n  return 0;\n}\n\nvoid OnTick(void) {\n  if (cursor >= ARR_NUM) return;\n  if (currTime == iTime(ext_strSymbol, ext_iPeriod, 0)) return;\n  currTime = iTime(ext_strSymbol, ext_iPeriod, 0);\n\n  double arr[INPUT_NUM];\n  double highest = -DBL_MAX;\n  double lowest = DBL_MAX;\n  for (int i = 1; i <= INPUT_NUM; i++) {\n    arr[i - 1] = iMACD(ext_strSymbol, ext_iPeriod, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, i);\n    if (arr[i - 1] > highest) {\n      highest = arr[i - 1];\n    }\n    if (arr[i - 1] < lowest) {\n      lowest = arr[i - 1];\n    }\n  }\n  double height = highest - lowest;\n  if (height <= 0) return;\n\n  for (int i = 0; i < INPUT_NUM; i++) {\n    macdArr[cursor * INPUT_NUM + i] = (arr[i] - lowest) / height;\n  }\n  oArr[cursor] = iOpen(ext_strSymbol, ext_iPeriod, 0);\n  cursor++;\n}\n\nvoid OnDeinit (const int) {\n  double trainingSetI[(cursor - 1) * INPUT_NUM];\n  double trainingSetO[(cursor - 1) * 2];\n\n  if (ext_bTrain) {\n    if (BuildCNN(NN_NAME, INPUT_NUM, HIDDEN_NUM)) {\n      for (int i = 0; i < cursor - 1; i++) {\n        for (int j = 0; j < INPUT_NUM; j++) {\n          trainingSetI[i * INPUT_NUM + j] = macdArr[i * INPUT_NUM + j];\n        }\n\n        if (oArr[i] <= oArr[i + 1]) {\n          trainingSetO[i * 2] = 1.0;\n          trainingSetO[i * 2 + 1] = 0.0;\n        } else {\n          trainingSetO[i * 2] = 0.0;\n          trainingSetO[i * 2 + 1] = 1.0;\n        }\n      }\n\n      Print(\"Please be patient with the training progress.\");\n\n      if (TrainCNN(NN_NAME, trainingSetI, trainingSetO, cursor - 1, INPUT_NUM, ITERATIONS, BATCH_SIZE, false)) {\n        SaveCNN(NN_NAME);\n      } else {\n        return;\n      }\n    } else {\n      return;\n    }\n  } else {\n    if (!LoadCNN(NN_NAME)) {\n      return;\n    }\n  }\n\n  int longWinCnt = 0;\n  int shortWinCnt = 0;\n  int longCnt = 0;\n  int shortCnt = 0;\n\n  for (int i = 0; i < cursor - 1; i++) {\n    double input[INPUT_NUM];\n    double output = trainingSetO[i * 2];\n\n    for (int j = 0; j < INPUT_NUM; j++) {\n      input[j] = trainingSetI[i * INPUT_NUM + j];\n    }\n\n    double result = RunCNN(NN_NAME, input, INPUT_NUM);\n    bool resWin = ((result >= 0.5 ? 1.0 : 0.0) == output ? true : false);\n\n    if (resWin) {\n      if (output == 1.0) {\n        longCnt++;\n        longWinCnt++;\n      } else {\n        shortCnt++;\n        shortWinCnt++;\n      }\n    } else {\n      if (output == 1.0) {\n        longCnt++;\n      } else {\n        shortCnt++;\n      }\n    }\n  }\n\n  int lsCount = longCnt + shortCnt;\n\n  Print(\"Long: \", longCnt, \", \", (longWinCnt * 1.0 / lsCount));\n  Print(\"Short: \", shortCnt, \", \", (shortWinCnt * 1.0 / lsCount));\n}\n"
  },
  {
    "path": "EA/Plugin-for-MQL/testverisig.cpp",
    "content": "// This example is for the developers who want to sell EAs via Fintechee.io website.\n// If you use EA for yourself or you don't care copyright infringement, then you don't need to add the codes below to your source files.\n\ninput string FINTECHEE_DATA = \"\"; // Keep this variable empty and DO NOT change the name of this variable.\ninput string FINTECHEE_SIGNATURE = \"\"; // Keep this variable empty and DO NOT change the name of this variable.\ninput string FINTECHEE_PUBLIC_KEY = \"\"; // Keep this variable empty and DO NOT change the name of this variable.\n// string APPLICATION_PUBLIC_KEY = \"-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwGzur7MO/CJPHvr2+r3lwxmjAL2d6nH2iyTwhL/CJZ8OGKm/+aikyluxoxF9Nq9aVLhCW5D1q9vAJCVYke7aquA/uuRE7a7frcWnKYOKNS2Pwvx88bJJBpfXfVh2K46i/2EfqdsghR+B1kSojS4lZggDB70uwIpeT2Q32X/5jEHl3p/9ZpFUwhStE2VMaEx/YOcdhAuS5BomDCe9g4KSI7faH3R0mA4dF1Tru6sAQarkAybI0RNlV52CpWfP2MfpeXm/P6WSXolM++DqFw8OsdrdqfyKM31zKyDOxzNib/DZbk72q6hzRtzGB4y3dTiyOVh3iP7nGOC/R0qPZCjRNQIDAQAB-----END PUBLIC KEY-----\";\nstring APPLICATION_PUBLIC_KEY = \"\"; // Replace this string with your public key. The public key above is an example. DO NOT change the name of this variable. You can get your public key on Fintechee.io's inventory page. Please choose \"Seller\" to create an inventory item first, then a key pair will be generated.\nbool bVerified = false; // This global variable is used to check whether your license is available. You can set an assert condition such as \"if(!bVerified) return;\" anywhere that you want to block abuse.\n\nint OnInit (void) {\n  // Please code the lines below anywhere that you want to verify the license. But note that calling VeriSig takes time, so we recommend you set an interval to check the license in the OnTick function or call VeriSig in OnInit.\n  if (VeriSig(FINTECHEE_DATA, FINTECHEE_SIGNATURE, FINTECHEE_PUBLIC_KEY, APPLICATION_PUBLIC_KEY)) {\n    bVerified = true;\n    Print(\"Verification is done!\");\n  }\n  return 0;\n}\n\nvoid OnTick(void) {\n  if (!bVerified) return;\n}\n"
  },
  {
    "path": "EA/Plugin-for-MQL/usage.txt",
    "content": "Our platform is compatible with any programming language based on WEB-Assembly. MQL, C++, and Python based programs can be used on our platform. This plugin allows MQL and C++ based programs to be imported into our system and run directly in the browser.\n\nVisit our website, https://fintechee.io, to explore our EA marketplace, which is supported by multiple vendors. If you have an EA that is based on MQL or C++, you can utilize our compiler, https://github.com/fintechees/Expert-Advisor-Cpp-Compiler, to compile and sell it on our marketplace.\n\nYour algo trading strategies can be experienced by clients who can utilize this plugin to import it into our WEB-trader.\n"
  },
  {
    "path": "EA/Plugin-for-Oanda/plugin_for_oanda.js",
    "content": "registerEA(\n\t\"plugin_for_oanda\",\n\t\"An EA to integrate with Oanda(v1.0)\",\n\t[],\n\tfunction (context) { // Init()\n\t\t// Disclaimer: we are not affiliated with Oanda.\n\t\tif (typeof window.pluginForOanda == \"undefined\") {\n\t\t\twindow.pluginForOanda = {\n\t\t\t\toandaDemo: true,\n\t\t\t\toandaAccountId: \"\",\n\t\t\t\toandaTradeKey: \"\",\n\t\t\t\twrapperLibUrl: \"https://www.fintechee.com/js/oanda/oanda_wrapper.js\",\n\t\t\t\tinterval: 120000,\n\t\t\t\tlatestHBTime: 0,\n\t\t\t\tbLibLoaded: false,\n\t\t\t\tbMonitoring: false,\n\t\t\t\tcurrenciesList: [],\n\t\t\t\topenPositions: [],\n\t\t\t\tclearTable: function () {\n\t\t\t\t\tvar posTable = null\n\n\t\t\t\t\tif ($.fn.dataTable.isDataTable(\"#oanda_pos_list\")) {\n\t\t\t      posTable = $(\"#oanda_pos_list\").DataTable();\n\t\t\t      posTable.clear().draw();\n\t\t\t      posTable.destroy();\n\t\t\t      $(\"#oanda_pos_list\").empty();\n\t\t\t    }\n\n\t\t\t\t\t$(\"#oanda_pos_list\").DataTable({\n\t\t\t\t\t\tdata: [],\n\t\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\t{title: \"Instrument\"},\n\t\t\t\t\t\t\t{title: \"Units\"},\n\t\t\t\t\t\t\t{title: \"Type\"}\n\t\t\t\t\t\t],\n\t\t\t\t\t\tordering: false,\n\t\t\t\t\t\tsearching: false,\n\t\t\t\t\t\tbPaginate: false,\n\t\t\t\t\t\tbLengthChange: false,\n\t\t\t\t\t\tbFilter: false,\n\t\t\t\t\t\tbInfo: false,\n\t\t\t\t\t\tscrollY: '50vh',\n\t\t\t\t\t\tscrollCollapse: true,\n\t\t\t\t\t\tpaging: false,\n\t\t\t\t\t\tcolumnDefs: [\n\t\t\t\t\t\t\t{width: \"40%\", targets: 0, className: \"dt-body-left\"},\n\t\t\t\t\t\t\t{width: \"30%\", targets: 1, className: \"dt-body-left\"},\n\t\t\t\t\t\t\t{width: \"30%\", targets: 2, className: \"dt-body-left\"},\n\t\t\t\t\t\t\t{targets: [0, 1, 2], className: \"dt-head-left\"}\n\t\t\t\t\t\t]\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tupdatePositions: function (trade) {\n\t\t\t\t\tvar rowId = -1\n\t\t\t\t\tvar instrument = trade.instrument.replace(\"_\", \"/\")\n\t\t\t\t\tvar currentUnits = parseFloat(trade.currentUnits)\n\t\t\t\t\tvar units = 0\n\n\t\t\t\t\tfor (var i in this.openPositions) {\n\t\t\t\t\t\tvar openPos = this.openPositions[i]\n\t\t\t\t\t\tif (openPos[0] == instrument) {\n\t\t\t\t\t\t\trowId = parseInt(i)\n\t\t\t\t\t\t\tif (openPos[2] == \"Long\") {\n\t\t\t\t\t\t\t\tunits = openPos[1]\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tunits = -openPos[1]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tunits += currentUnits\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rowId != -1) {\n\t\t\t\t\t\tif (units == 0) {\n\t\t\t\t\t\t\tthis.openPositions.splice(rowId, 1)\n\t\t\t\t\t\t\tthis.removePosFromTable(rowId)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (units > 0) {\n\t\t\t\t\t\t\t\tthis.openPositions[rowId][2] = \"Long\"\n\t\t\t\t\t\t\t\tthis.openPositions[rowId][1] = units\n\t\t\t\t\t\t\t\tthis.updatePosOnTable(rowId, \"Long\", units)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.openPositions[rowId][2] = \"Short\"\n\t\t\t\t\t\t\t\tthis.openPositions[rowId][1] = -units\n\t\t\t\t\t\t\t\tthis.updatePosOnTable(rowId, \"Short\", -units)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar pos = [\n\t\t\t\t\t\t\ttrade.instrument.replace(\"_\", \"/\"),\n\t\t\t\t\t\t\tMath.abs(currentUnits),\n\t\t\t\t\t\t\tcurrentUnits > 0 ? \"Long\" : \"Short\"\n\t\t\t\t\t\t]\n\t\t\t\t\t\tthis.openPositions.push(pos)\n\t\t\t\t\t\tthis.addPosToTable(pos)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\taddPosToTable: function (pos) {\n\t\t\t\t\t$(\"#oanda_pos_list\").DataTable().row.add(pos).draw(false)\n\t\t\t\t},\n\t\t\t\tupdatePosOnTable: function (rowId, orderType, units) {\n\t\t\t\t\t$(\"#oanda_pos_list\").dataTable().fnUpdate(units, rowId, 1, false, false)\n\t\t\t\t\t$(\"#oanda_pos_list\").dataTable().fnUpdate(orderType, rowId, 2, false, false)\n\t\t\t\t},\n\t\t\t\tremovePosFromTable: function (rowId) {\n\t\t\t\t\t$(\"#oanda_pos_list\").dataTable().postable.fnDeleteRow(rowId)\n\t\t\t\t},\n\t\t\t\tloadTrades: function () {\n\t\t\t\t\tvar that = this\n\t\t\t\t\tif (typeof window.oandaOrderAPI != \"undefined\") {\n\t\t\t\t\t\twindow.oandaOrderAPI.trades.listOpen(this.oandaAccountId)\n\t\t\t\t\t\t.then(function (res) {\n\t\t\t\t\t\t\tthat.clearTable()\n\n\t\t\t\t\t\t\tfor (var i in res.trades) {\n\t\t\t          that.updatePositions(res.trades[i])\n\t\t\t        }\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(function () {})\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsendOrder: function (symbolName, orderType, volume) {\n\t\t\t\t\tif (typeof window.oandaOrderAPI != \"undefined\") {\n\t\t\t\t\t\twindow.oandaOrderAPI.orders.openOrder(this.oandaAccountId, {\n\t\t\t\t\t\t\tunits: (orderType == ORDER_TYPE.OP_BUY ? (volume * 100000 + \"\") : (-volume * 100000 + \"\")),\n\t\t\t\t\t\t\tinstrument: symbolName.replace(\"/\", \"_\"),\n\t\t\t\t\t\t\ttimeInForce: \"FOK\",\n\t\t\t\t\t\t\ttype: \"MARKET\",\n\t\t\t\t\t\t\tpositionFill: \"DEFAULT\"\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tloadLib: function () {\n\t\t\t\t\tvar tags = document.getElementsByTagName(\"script\")\n\t\t\t\t\tfor (var i = tags.length - 1; i >= 0; i--) {\n\t\t\t\t\t\tif (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == this.wrapperLibUrl) {\n\t\t\t\t\t\t\tthis.bLibLoaded = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar that = this\n\n\t\t\t\t\tif (!this.bLibLoaded) {\n\t\t\t\t\t\tvar script = document.createElement(\"script\")\n\t\t\t\t\t\tscript.id = \"oanda_wrapper_lib\"\n\n\t\t\t\t\t\tdocument.body.appendChild(script)\n\t\t\t\t\t\tscript.onload = function () {\n\t\t\t\t\t\t\tthat.bLibLoaded = true\n\t\t\t\t\t\t\tpopupMessage(\"The wrapper lib for Oanda has been loaded successfully!\")\n\t\t\t\t\t\t}\n\t\t\t\t\t\tscript.onerror = function () {\n\t\t\t\t\t\t\tthat.bLibLoaded = false\n\t\t\t\t\t\t\tpopupErrorMessage(\"Failed to load the wrapper lib for Oanda.\")\n\t\t\t\t\t\t}\n\t\t\t\t\t\tscript.async = true\n\t\t\t\t\t\tscript.src = this.wrapperLibUrl\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmonitorConnection: function () {\n\t\t\t\t\tif (this.latestHBTime != 0 && new Date().getTime() - this.latestHBTime >= this.interval) {\n\t\t\t\t\t\tthis.bMonitoring = false\n\t\t\t\t\t\tthis.reconnect()\n\t\t\t\t\t}\n\t\t\t\t\tvar that = this\n\t\t\t\t\tsetTimeout(function () {that.monitorConnection()}, this.interval)\n\t\t\t\t},\n\t\t\t\tdataSubscribers: [],\n\t\t\t\torderSubscribers: [],\n\t\t\t\tsubscribeToDataChannel: function (subscriberName, subscriberCallback) {\n\t\t\t\t\tthis.dataSubscribers[subscriberName] = subscriberCallback\n\t\t\t\t},\n\t\t\t\tsubscribeToOrderChannel: function (subscriberName, subscriberCallback) {\n\t\t\t\t\tthis.orderSubscribers[subscriberName] = subscriberCallback\n\t\t\t\t},\n\t\t\t\tunsubscribeFromDataChannel: function (subscriberName) {\n\t\t\t\t\tdelete this.dataSubscribers[subscriberName]\n\t\t\t\t},\n\t\t\t\tunsubscribeFromOrderChannel: function (subscriberName) {\n\t\t\t\t\tdelete this.orderSubscribers[subscriberName]\n\t\t\t\t},\n\t\t\t\toandaDataCallback: function (res) {\n\t\t\t\t\tif (!this.bMonitoring) {\n\t\t\t\t\t\tpopupMessage(\"Oanda has been connected successfully!\")\n\t\t\t\t\t\tthis.monitorConnection()\n\t\t\t\t\t\tthis.bMonitoring = true\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (var i in this.dataSubscribers) {\n\t\t\t\t\t\tthis.dataSubscribers[i](res)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toandaOrderCallback: function (res) {\n\t\t\t\t\tif (typeof res.type != \"undefined\") {\n\t\t\t\t\t\tif (res.type == \"ORDER_FILL\") {\n\t\t\t\t\t\t\tres.currentUnits = res.units\n\t\t\t\t\t\t\tthis.updatePositions(res)\n\t\t\t\t\t\t} else if (res.type == \"HEARTBEAT\") {\n\t\t\t\t\t\t\tthis.latestHBTime = new Date().getTime()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (var i in this.orderSubscribers) {\n\t\t\t\t\t\tthis.orderSubscribers[i](res)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\treconnect: function () {\n\t\t\t\t\tvar that = this\n\t\t\t\t\tif (typeof window.oandaDataAPI != \"undefined\") {\n\t\t\t\t\t\tvar symbolsList = []\n\t\t        for (var i in this.currenciesList) {\n\t\t          symbolsList.push(this.currenciesList[i].symbolName)\n\t\t        }\n\n\t\t\t\t\t\twindow.oandaDataAPI.addToken(this.oandaDemo, this.oandaAccountId, this.oandaTradeKey)\n\t\t\t\t\t\twindow.oandaDataAPI.pricing.stream(this.oandaAccountId, {instruments: symbolsList.join(\",\"), snapshot: false}, function (res) {\n\t\t\t\t\t\t\tthat.oandaDataCallback(res)\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof window.oandaOrderAPI != \"undefined\") {\n\t\t\t\t\t\twindow.oandaOrderAPI.addToken(this.oandaDemo, this.oandaAccountId, this.oandaTradeKey)\n\t\t\t\t\t\twindow.oandaOrderAPI.transactions.stream(this.oandaAccountId, function (res) {\n\t\t\t\t\t\t\tthat.oandaOrderCallback(res)\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcharts: [],\n\t      chartChangeCallback: function (ctx) { // This callback function will be called once the chart switches from the normal mode to the takeover mode or the symbol of the chart under the takeover mode changes.\n\t        var symbolName = getExtraSymbolName(ctx)\n\n\t        if (typeof this.currenciesList[symbolName] != \"undefined\") {\n\t          var chartId = getChartHandleByContext(ctx)\n\n\t          setTakeoverMode(chartId)\n\t          var timeFrame = getTimeFrame(ctx)\n\n\t          if (typeof this.charts[chartId + \"\"] == \"undefined\") {\n\t            this.charts[chartId + \"\"] = {\n\t              chartId: chartId,\n\t              symbolName: null,\n\t              timeFrame: null\n\t            }\n\t          }\n\t          var chart = this.charts[chartId + \"\"]\n\t          chart.symbolName = this.currenciesList[symbolName].symbolName\n\t          chart.timeFrame = timeFrame\n\n\t          var that = this\n\n\t          window.oandaDataAPI.instruments.candles(this.oandaAccountId, chart.symbolName, {\n\t            granularity: timeFrame.toUpperCase()\n\t          })\n\t          .then(function (res) {\n\t            var data = []\n\n\t            if (Array.isArray(res.candles)) {\n\t              for (var i in res.candles) {\n\t                var ohlc = res.candles[i].mid\n\n\t                data.push({\n\t                  time: Math.floor(new Date(res.candles[i].time).getTime() / 1000),\n\t                  volume: res.candles[i].volume,\n\t                  open: parseFloat(ohlc.o),\n\t                  high: parseFloat(ohlc.h),\n\t                  low: parseFloat(ohlc.l),\n\t                  close: parseFloat(ohlc.c)\n\t                })\n\t              }\n\n\t              takeoverLoad(chartId, data)\n\t            }\n\t          })\n\n\t        } else {\n\t          var chartId = getChartHandleByContext(ctx)\n\t          unsetTakeoverMode(chartId)\n\t          takeoverLoad(chartId, [])\n\t          delete this.charts[chartId + \"\"]\n\t        }\n\t      },\n\t      chartRemoveCallback: function (ctx) { // This callback function will be called once the chart switches from the takeover mode to the normal mode or the chart is removed.\n\t        var chartId = getChartHandleByContext(ctx)\n\t        unsetTakeoverMode(chartId)\n\t        takeoverLoad(chartId, [])\n\t        delete this.charts[chartId + \"\"]\n\t      },\n\t\t\t\tquotes: [],\n\t      onTick: function (res) {\n\t        if (typeof res.instrument != \"undefined\") {\n\t          var ask = null\n\t          var bid = null\n\t          var price = null\n\t          if (Array.isArray(res.asks)) {\n\t            ask = parseFloat(res.asks[0].price)\n\t            price = ask\n\t          }\n\t          if (Array.isArray(res.bids)) {\n\t            bid = parseFloat(res.bids[0].price)\n\t            price = bid\n\t          }\n\t          if (ask == null) {\n\t            ask = price\n\t          }\n\t          if (bid == null) {\n\t            bid = price\n\t          }\n\t          if (ask == null || bid == null) {\n\t            return\n\t          }\n\n\t          for (var i in this.charts) {\n\t            var chart = this.charts[i]\n\n\t            if (chart.symbolName == res.instrument) {\n\t              var tick = {\n\t                time: Math.floor(new Date().getTime() / 1000),\n\t                volume: 0,\n\t                price: Math.round((bid + ask) / 2 * 100000) / 100000\n\t              }\n\n\t              if (chart.timeFrame == \"M1\") {\n\t                takeoverUpdate(chart.chartId, 60, tick)\n\t              } else if (chart.timeFrame == \"M5\") {\n\t                takeoverUpdate(chart.chartId, 300, tick)\n\t              } else if (chart.timeFrame == \"M15\") {\n\t                takeoverUpdate(chart.chartId, 900, tick)\n\t              } else if (chart.timeFrame == \"M30\") {\n\t                takeoverUpdate(chart.chartId, 1800, tick)\n\t              } else if (chart.timeFrame == \"H1\") {\n\t                takeoverUpdate(chart.chartId, 3600, tick)\n\t              } else if (chart.timeFrame == \"H4\") {\n\t                takeoverUpdate(chart.chartId, 14400, tick)\n\t              } else if (chart.timeFrame == \"D\") {\n\t                takeoverUpdate(chart.chartId, 86400, tick)\n\t              } else {\n\t                takeoverUpdate(chart.chartId, 86400, tick)\n\t              }\n\t            }\n\t          }\n\n\t\t\t\t\t\tthis.quotes[res.instrument.replace(\"_\", \"/\")] = {\n\t\t\t\t\t\t\task: ask,\n\t\t\t\t\t\t\tbid: bid\n\t\t\t\t\t\t}\n\t        }\n\t      },\n\t\t\t\tinitDashboard: function () {\n\t\t\t\t\tif (typeof $(\"#oanda_dashboard\").html() == \"undefined\") {\n\t\t\t\t\t\tvar panel = '<div class=\"ui form modal\" id=\"oanda_dashboard\">' +\n\t\t\t\t\t\t\t'<div class=\"content\">' +\n\t\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\">' +\n\t\t\t\t\t\t\t\t\t\t'<div class=\"ui selection dropdown\" id=\"dropdownOandaDemo\">' +\n\t\t\t\t\t\t\t\t\t\t\t'<input type=\"hidden\" id=\"oandaDemo\">' +\n\t\t\t\t\t\t\t\t\t\t\t'<i class=\"dropdown icon\"></i>' +\n\t\t\t\t\t\t\t\t\t\t\t'<div class=\"default text\">Demo (Default)</div>' +\n\t\t\t\t\t\t\t\t\t\t\t'<div class=\"menu\">' +\n\t\t\t\t\t\t\t\t\t\t\t\t'<div class=\"item\" data-value=\"true\">Demo</div>' +\n\t\t\t\t\t\t\t\t\t\t\t\t'<div class=\"item\" data-value=\"false\">Live</div>' +\n\t\t\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"oandaAccountId\" placeholder=\"Oanda Account ID\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"password\" id=\"oandaTradeKey\" placeholder=\"Token\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"connect_to_oanda\" class=\"ui button\">Connect</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'<div class=\"description\">' +\n\t\t\t\t\t\t\t\t\t'<table id=\"oanda_pos_list\" class=\"cell-border\" cellspacing=\"0\">' +\n\t\t\t\t\t\t\t\t\t'</table>' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t'<div class=\"actions\">' +\n\t\t\t\t\t\t\t\t'<div class=\"ui button\" id=\"close_oanda_dashboard\">Close</div>' +\n\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t'</div>'\n\n\t\t\t\t\t\t$(\"#reserved_zone\").append(panel)\n\n\t\t\t\t\t\t$(\"#dropdownOandaDemo\").dropdown()\n\n\t\t\t\t\t\tvar that = this\n\n\t\t\t\t\t\t$(\"#connect_to_oanda\").on(\"click\", function () {\n\t\t\t\t\t\t\tthat.oandaDemo = $(\"#oandaDemo\").val() == \"\" || $(\"#oandaDemo\").val() == \"true\"\n\t\t\t\t\t\t\tthat.oandaAccountId = $(\"#oandaAccountId\").val().trim()\n\t\t\t\t\t\t\tthat.oandaTradeKey = $(\"#oandaTradeKey\").val().trim()\n\n\t\t\t\t\t\t\tif (that.oandaAccountId != \"\" && that.oandaTradeKey != \"\" && that.bLibLoaded) {\n\t\t\t\t\t\t\t\tthat.reconnect()\n\t\t\t\t\t\t\t\tthat.subscribeToDataChannel(\"oanda_data\", function (res) {\n\t                that.onTick(res)\n\t              })\n\t\t\t\t\t\t\t\tthat.loadTrades()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#close_oanda_dashboard\").on(\"click\", function () {\n\t\t\t\t\t\t\t$(\"#oanda_dashboard\").modal(\"hide\")\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tvar currenciesList = [{\n\t\t\t\t      symbolName: \"AUD_CAD\",\n\t\t\t\t      displayName: \"AUD/CAD (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"AUD_CHF\",\n\t\t\t\t      displayName: \"AUD/CHF (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"AUD_JPY\",\n\t\t\t\t      displayName: \"AUD/JPY (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"AUD_USD\",\n\t\t\t\t      displayName: \"AUD/USD (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"EUR_GBP\",\n\t\t\t\t      displayName: \"EUR/GBP (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"EUR_JPY\",\n\t\t\t\t      displayName: \"EUR/JPY (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"EUR_USD\",\n\t\t\t\t      displayName: \"EUR/USD (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"GBP_AUD\",\n\t\t\t\t      displayName: \"GBP/AUD (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"GBP_CHF\",\n\t\t\t\t      displayName: \"GBP/CHF (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"GBP_JPY\",\n\t\t\t\t      displayName: \"GBP/JPY (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"GBP_USD\",\n\t\t\t\t      displayName: \"GBP/USD (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"USD_CAD\",\n\t\t\t\t      displayName: \"USD/CAD (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"USD_CHF\",\n\t\t\t\t      displayName: \"USD/CHF (Oanda)\"\n\t\t\t\t    }, {\n\t\t\t\t      symbolName: \"USD_JPY\",\n\t\t\t\t      displayName: \"USD/JPY (Oanda)\"\n\t\t\t\t    }]\n\n\t\t\t\t\t\tfor (var i in currenciesList) {\n\t\t\t\t      this.currenciesList[currenciesList[i].displayName] = currenciesList[i]\n\t\t\t\t\t\t\tthis.quotes[currenciesList[i].symbolName.replace(\"_\", \"/\")] = null\n\t\t\t\t    }\n\n\t\t\t\t\t\tvar chartIds = getLayout(1).concat(getLayout(2)).concat(getLayout(3)).concat(getLayout(4))\n\t\t\t\t    for (var i in chartIds) {\n\t\t\t\t      if (typeof this.charts[chartIds[i] + \"\"] == \"undefined\") {\n\t\t\t\t        this.charts[chartIds[i] + \"\"] = {\n\t\t\t\t          chartId: chartIds[i],\n\t\t\t\t          symbolName: null,\n\t\t\t\t          timeFrame: null\n\t\t\t\t        }\n\t\t\t\t        createTakeover(chartIds[i],\n\t\t\t\t          function (ctx) {\n\t\t\t\t            that.chartChangeCallback(ctx)\n\t\t\t\t          },\n\t\t\t\t          function (ctx) {\n\t\t\t\t            that.chartRemoveCallback(ctx)\n\t\t\t\t          }\n\t\t\t\t        )\n\t\t\t\t      }\n\t\t\t\t    }\n\n\t\t\t\t    addExtraSymbols(this.currenciesList)\n\t\t\t\t\t}\n\n\t\t\t\t\t$(\"#oanda_dashboard\").modal({autofocus:false}).modal(\"show\")\n\n\t\t\t\t\tthis.clearTable()\n\t\t\t\t\tfor (var i in this.openPositions) {\n\t\t\t\t\t\tthis.addPosToTable(this.openPositions[i])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\twindow.pluginForOanda.initDashboard()\n\t\twindow.pluginForOanda.loadLib()\n\t},\n\tfunction (context) { // Deinit()\n\t\tif (!window.pluginForOanda.bLibLoaded) {\n\t\t\tvar script = document.getElementById(\"oanda_wrapper_lib\")\n\t\t\tscript.remove()\n\t\t}\n\t},\n\tfunction (context) { // OnTick()\n\t}\n)\n"
  },
  {
    "path": "EA/Plugin-for-Oanda/usage.txt",
    "content": "Oanda is a well-known broker that offers API trading. As a result, we have created a plugin that establishes both a data channel for retrieving real-time quotes from Oanda and a trade channel for sending orders via Oanda’s REST API.\n\nDue to the substantial variance in prices between FIX API, which is utilized by institutions, and retail brokers, there can be arbitrage opportunities. However, arbitrage trading is not easy and requires considerable expenditures to develop appropriate tools. This plugin now allows traders to track market movements between two data sources and trade for arbitrage on their local machines without additional expenses.\n"
  },
  {
    "path": "EA/Plugin-for-SNS/plugin_for_sns.js",
    "content": "registerEA(\n\t\"plugin_for_sns\",\n\t\"An EA to integrate with Fintechee SNS(v1.0)\",\n\t[],\n\tfunction (context) { // Init()\n\t\tif (typeof window.pluginForSns == \"undefined\") {\n\t\t\twindow.pluginForSns = {\n\t\t\t\tdata: [],\n\t\t\t\tdefaultTopic: \"FintecheeEcoCal\",\n\t\t\t\ttopics: [],\n\t\t\t\tcreateTopic: function (topic, publishToken) {\n\t\t\t\t\t$.ajax({\n\t          type: \"POST\",\n\t          url: \"https://ciq1ir66d3.execute-api.eu-central-1.amazonaws.com/v1/register\",\n\t          contentType: \"application/json; charset=utf-8\",\n\t          dataType: \"json\",\n\t          data: JSON.stringify({\n\t\t\t\t\t\t\ttopic: topic,\n\t\t\t\t\t\t\tpublishToken: publishToken\n\t          }),\n\t          success: function (data) {\n\t            if (typeof data.res == \"string\") {\n\t              $(\"#publishToken\").val(data.res)\n\t            }\n\t          },\n\t          error: function (request, status, error) {\n\t\t\t\t\t\t\tpopupErrorMessage(request.responseText)\n\t          }\n\t        })\n\t\t\t\t},\n\t\t\t\tpostToTopic: function (topic, publishToken, content) {\n\t\t\t\t\tthis.websocket.send(JSON.stringify({\n\t\t\t\t\t\taction: \"post\",\n\t\t\t\t\t\ttopic: topic,\n\t\t\t\t\t\tpublishToken: publishToken,\n\t\t\t\t\t\tcontent: content\n\t\t\t\t\t}))\n\t\t\t\t},\n\t\t\t\tsubscribeToTopic: function (topic) {\n\t\t\t\t\tthis.websocket.send(JSON.stringify({\n\t\t\t\t\t\taction: \"subscribe\",\n\t\t\t\t\t\ttopic: topic\n\t\t\t\t\t}))\n\t\t\t\t\tthis.topics[topic] = true\n\t\t\t\t\tif (typeof this.data[topic] == \"undefined\") {\n\t\t\t\t\t\tthis.data[topic] = []\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsubscribers: [],\n\t\t\t\tsubscribe: function (name, callback, ctx) {\n\t\t\t\t\tif (typeof name == \"string\" && typeof callback == \"function\" && typeof ctx == \"object\") {\n\t\t\t\t\t\tthis.subscribers[name] = {\n\t\t\t\t\t\t\tcallback: callback,\n\t\t\t\t\t\t\tcontext: ctx\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tunsubscribe: function (name) {\n\t\t\t\t\tif (typeof name == \"string\") {\n\t\t\t\t\t\tdelete this.subscribers[name]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tupdateData: function (data) {\n\t\t\t\t\tif (data.bFull) {\n\t\t\t\t\t\tthis.data[data.topic] = data.data\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (data.topic == this.defaultTopic) {\n\t\t\t\t\t\t\tvar oldData = this.data[data.topic]\n\n\t\t\t\t\t\t\tfor (var i in data.data) {\n\t\t\t\t\t\t\t\tvar iFound = -1\n\t\t\t\t\t\t\t\tvar updItem = data.data[i]\n\t\t\t\t\t\t\t\tfor (var j in oldData) {\n\t\t\t\t\t\t\t\t\tvar oldItem = oldData[j]\n\t\t\t\t\t\t\t\t\tif (updItem.data == oldItem.data) {\n\t\t\t\t\t\t\t\t\t\tiFound = parseInt(j)\n\t\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (iFound != -1) {\n\t\t\t\t\t\t\t\t\tthis.data[data.topic][iFound] = data.data[i]\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthis.data[data.topic].push(data.data[i])\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (var i in data.data) {\n\t\t\t\t\t\t\t\tthis.data[data.topic].push(data.data[i])\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (var i in this.subscribers) {\n\t\t\t\t\t\tthis.subscribers[i].callback(this.subscribers[i].context)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tbConnected: false,\n\t\t\t\twebsocket: null,\n\t\t\t\treconnect: function () {\n\t\t\t\t\tvar socket = new WebSocket(\"wss://5k4mgf59ce.execute-api.eu-central-1.amazonaws.com/production\")\n\n\t\t\t\t\tvar that = this\n\n\t\t\t\t\tsocket.onopen = function (e) {\n\t\t\t\t\t\tthat.bConnected = true\n\t\t\t\t\t\tconsole.log(\"[open] Connection established\")\n\t\t\t\t\t  console.log(\"Sending to server\")\n\n\t\t\t\t\t\tvar subscriptionCnt = 0\n\n\t\t\t\t\t\tfor (var i in that.topics) {\n\t\t\t\t\t\t\tif (that.topics[i] && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.subscribeToTopic(i)\n\t\t\t\t\t\t\t\tsubscriptionCnt++\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (subscriptionCnt == 0) {\n\t\t\t\t\t\t\tthat.subscribeToTopic(that.defaultTopic)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.onmessage = function (event) {\n\t\t\t\t\t  console.log('[message] Data received from server')\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthat.updateData(JSON.parse(event.data))\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.onclose = function (event) {\n\t\t\t\t\t\tthat.bConnected = false\n\t\t\t\t\t  if (event.wasClean) {\n\t\t\t\t\t    console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`)\n\t\t\t\t\t  } else {\n\t\t\t\t\t    console.log('[close] Connection down')\n\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\tthat.reconnect()\n\t\t\t\t\t\t\t}, 1000)\n\t\t\t\t\t  }\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.onerror = function (error) {\n\t\t\t\t\t  console.log(`[error] ${error}`)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.websocket = socket\n\t\t\t\t},\n\t\t\t\tinitDashboard: function () {\n\t\t\t\t\tif (typeof $(\"#sns_dashboard\").html() == \"undefined\") {\n\t\t\t\t\t\tvar panel = '<div class=\"ui form modal\" id=\"sns_dashboard\">' +\n\t\t\t\t\t\t\t'<div class=\"content\">' +\n\t\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"topicName\" placeholder=\"Topic\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"password\" id=\"publishToken\" placeholder=\"Publish Token\"><div style=\"border-top:1px solid #ddd;border-bottom:1px solid #ddd\"><i class=\"eye icon toggle-token\" id=\"tokenToggle\" style=\"color:#ddd\"></i></div>' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnCreateTopic\" class=\"ui button\" style=\"width:100px\">Create</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\" style=\"margin-top:5px\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"topicContent\" placeholder=\"Content\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnPostToTopic\" class=\"ui button\" style=\"width:100px\">Post</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\" style=\"margin-top:5px\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"topicToSubscribeTo\" placeholder=\"Topic to Subscribe to\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnSubscribeToTopic\" class=\"ui button\" style=\"width:100px\">Subscribe</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t'<div class=\"actions\">' +\n\t\t\t\t\t\t\t\t'<div class=\"ui button\" id=\"btnCloseSnsDashboard\">Close</div>' +\n\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t'</div>'\n\n\t\t\t\t\t\t$(\"#reserved_zone\").append(panel)\n\n\t\t\t\t\t\tvar that = this\n\n\t\t\t\t\t\t$(\"#btnCreateTopic\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar topic = $(\"#topicName\").val().trim()\n\t\t\t\t\t\t\tvar publishToken = $(\"#publishToken\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\") {\n\t\t\t\t\t\t\t\tthat.createTopic(topic, publishToken)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnPostToTopic\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar topic = $(\"#topicName\").val().trim()\n\t\t\t\t\t\t\tvar publishToken = $(\"#publishToken\").val().trim()\n\t\t\t\t\t\t\tvar content = $(\"#topicContent\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\" && publishToken != \"\" && content != \"\" && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.postToTopic(topic, publishToken, content)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnSubscribeToTopic\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar topic = $(\"#topicToSubscribeTo\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\" && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.subscribeToTopic(topic)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnCloseSnsDashboard\").on(\"click\", function () {\n\t\t\t\t\t\t\t$(\"#sns_dashboard\").modal(\"hide\")\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#tokenToggle\").on(\"click\", function() {\n\t\t\t\t      var tokenInput = $(\"#publishToken\")\n\t\t\t\t      var icon = $(this)\n\n\t\t\t\t      if (tokenInput.attr(\"type\") == \"password\") {\n\t\t\t\t        tokenInput.attr(\"type\", \"text\")\n\t\t\t\t      } else {\n\t\t\t\t        tokenInput.attr(\"type\", \"password\")\n\t\t\t\t      }\n\t\t\t\t    })\n\t\t\t\t\t}\n\n\t\t\t\t\t$(\"#sns_dashboard\").modal({autofocus:false}).modal(\"show\")\n\n\t\t\t\t\tthis.reconnect()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\twindow.pluginForSns.initDashboard()\n\n\t\tif (typeof window.fintecheeBarrage != \"undefined\") {\n\t\t\tfor (var i in window.fintecheeBarrage.context) {\n\t\t\t\twindow.pluginForSns.subscribe(\"barrage-\" + i, window.fintecheeBarrage.callback, window.fintecheeBarrage.context[i])\n\t\t\t}\n\t\t}\n\t},\n\tfunction (context) { // Deinit()\n\t},\n\tfunction (context) { // OnTick()\n\t}\n)\n"
  },
  {
    "path": "EA/Plugin-for-SNS/usage.txt",
    "content": "This plugin is deprecated. We have a new plugin named \"Plugin for SNS with OpenAI\" instead.\n1, Launch an EA (Expert Advisor) named \"plugin_for_sns\".\n2, If you are a publisher, input the topic name and click the \"Create\" button. The backend system will create a topic for you (if the topic already exists, the creation will fail) and generate a publish token. You can then begin posting your content.\n3, If you are a subscriber, input the topic you wish to subscribe to. Afterward, please add an indicator called \"barrage\" to the chart. Whenever the publisher posts content, you will see a triangle on the chart. Hover your mouse over the triangle to view the content from the publisher in your social network.\n\n"
  },
  {
    "path": "EA/Plugin-for-SNS-with-OpenAI/plugin_for_sns_with_openai.js",
    "content": "registerEA(\n\t\"plugin_for_sns_with_openai\",\n\t\"An EA to integrate with SNS and OpenAI(v1.0)\",\n\t[],\n\tfunction (context) { // Init()\n\t\tif (typeof window.pluginForSns == \"undefined\") {\n\t\t\twindow.pluginForSns = {\n\t\t\t\tdata: [],\n\t\t\t\tdefaultTopic: \"FintecheeEcoCal\",\n\t\t\t\ttopics: [],\n\t\t\t\tcreateTopic: function (topic, publishToken) {\n\t\t\t\t\t$.ajax({\n\t          type: \"POST\",\n\t          url: \"https://ciq1ir66d3.execute-api.eu-central-1.amazonaws.com/v1/register\",\n\t          contentType: \"application/json; charset=utf-8\",\n\t          dataType: \"json\",\n\t          data: JSON.stringify({\n\t\t\t\t\t\t\ttopic: topic,\n\t\t\t\t\t\t\tpublishToken: publishToken\n\t          }),\n\t          success: function (data) {\n\t            if (typeof data.res == \"string\") {\n\t              $(\"#publishToken\").val(data.res)\n\t            }\n\t          },\n\t          error: function (request, status, error) {\n\t\t\t\t\t\t\tpopupErrorMessage(request.responseText)\n\t          }\n\t        })\n\t\t\t\t},\n\t\t\t\tpostToTopic: function (topic, publishToken, content) {\n\t\t\t\t\tthis.websocket.send(JSON.stringify({\n\t\t\t\t\t\taction: \"post\",\n\t\t\t\t\t\ttopic: topic,\n\t\t\t\t\t\tpublishToken: publishToken,\n\t\t\t\t\t\tcontent: content\n\t\t\t\t\t}))\n\t\t\t\t},\n\t\t\t\tchatWithOpenAI: function (topic, publishToken, content) {\n\t\t\t\t\tthis.websocket.send(JSON.stringify({\n\t\t\t\t\t\taction: \"openai\",\n\t\t\t\t\t\ttopic: topic,\n\t\t\t\t\t\tpublishToken: publishToken,\n\t\t\t\t\t\tcontent: content\n\t\t\t\t\t}))\n\t\t\t\t},\n\t\t\t\tsubscribeToTopic: function (topic) {\n\t\t\t\t\tthis.websocket.send(JSON.stringify({\n\t\t\t\t\t\taction: \"subscribe\",\n\t\t\t\t\t\ttopic: topic\n\t\t\t\t\t}))\n\t\t\t\t\tthis.topics[topic] = true\n\t\t\t\t\tif (typeof this.data[topic] == \"undefined\") {\n\t\t\t\t\t\tthis.data[topic] = []\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsubscribers: [],\n\t\t\t\tsubscribe: function (name, callback, ctx) {\n\t\t\t\t\tif (typeof name == \"string\" && typeof callback == \"function\" && typeof ctx == \"object\") {\n\t\t\t\t\t\tthis.subscribers[name] = {\n\t\t\t\t\t\t\tcallback: callback,\n\t\t\t\t\t\t\tcontext: ctx\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tunsubscribe: function (name) {\n\t\t\t\t\tif (typeof name == \"string\") {\n\t\t\t\t\t\tdelete this.subscribers[name]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tupdateData: function (data) {\n\t\t\t\t\tif (data.bFull) {\n\t\t\t\t\t\tthis.data[data.topic] = data.data\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (data.topic == this.defaultTopic) {\n\t\t\t\t\t\t\tvar oldData = this.data[data.topic]\n\n\t\t\t\t\t\t\tfor (var i in data.data) {\n\t\t\t\t\t\t\t\tvar iFound = -1\n\t\t\t\t\t\t\t\tvar updItem = data.data[i]\n\t\t\t\t\t\t\t\tfor (var j in oldData) {\n\t\t\t\t\t\t\t\t\tvar oldItem = oldData[j]\n\t\t\t\t\t\t\t\t\tif (updItem.data == oldItem.data) {\n\t\t\t\t\t\t\t\t\t\tiFound = parseInt(j)\n\t\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (iFound != -1) {\n\t\t\t\t\t\t\t\t\tthis.data[data.topic][iFound] = data.data[i]\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthis.data[data.topic].push(data.data[i])\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (var i in data.data) {\n\t\t\t\t\t\t\t\tthis.data[data.topic].push(data.data[i])\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (var i in this.subscribers) {\n\t\t\t\t\t\tthis.subscribers[i].callback(this.subscribers[i].context)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\trespond: function (data) {\n\t\t\t\t\tif (data.bError) {\n\t\t\t\t\t\t$(\"#openAIResponse\").val(data.errMsg)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (data.type == \"OpenAI\") {\n\t\t\t\t\t\t\tvar response = JSON.parse(data.data)\n\n\t\t\t\t\t\t\t$(\"#openAIResponse\").val(response.choices[0].message.content)\n\t\t\t\t\t\t} else if (data.type == \"PostToSns\") {\n\t\t\t\t\t\t\t$(\"#openAIResponse\").val(data.data[0].name)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tbConnected: false,\n\t\t\t\twebsocket: null,\n\t\t\t\treconnect: function () {\n\t\t\t\t\tvar socket = new WebSocket(\"wss://5k4mgf59ce.execute-api.eu-central-1.amazonaws.com/production\")\n\n\t\t\t\t\tvar that = this\n\n\t\t\t\t\tsocket.onopen = function (e) {\n\t\t\t\t\t\tthat.bConnected = true\n\t\t\t\t\t\tconsole.log(\"[open] Connection established\")\n\t\t\t\t\t  console.log(\"Sending to server\")\n\n\t\t\t\t\t\tvar subscriptionCnt = 0\n\n\t\t\t\t\t\tfor (var i in that.topics) {\n\t\t\t\t\t\t\tif (that.topics[i] && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.subscribeToTopic(i)\n\t\t\t\t\t\t\t\tsubscriptionCnt++\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (subscriptionCnt == 0) {\n\t\t\t\t\t\t\tthat.subscribeToTopic(that.defaultTopic)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.onmessage = function (event) {\n\t\t\t\t\t  console.log('[message] Data received from server')\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar data = JSON.parse(event.data)\n\t\t\t\t\t\t\tif (data.bResponse) {\n\t\t\t\t\t\t\t\tthat.respond(data)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthat.updateData(data)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.onclose = function (event) {\n\t\t\t\t\t\tthat.bConnected = false\n\t\t\t\t\t  if (event.wasClean) {\n\t\t\t\t\t    console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`)\n\t\t\t\t\t  } else {\n\t\t\t\t\t    console.log('[close] Connection down')\n\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\tthat.reconnect()\n\t\t\t\t\t\t\t}, 1000)\n\t\t\t\t\t  }\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.onerror = function (error) {\n\t\t\t\t\t  console.log(`[error] ${error}`)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.websocket = socket\n\t\t\t\t},\n\t\t\t\tinitDashboard: function () {\n\t\t\t\t\tif (typeof $(\"#sns_dashboard\").html() == \"undefined\") {\n\t\t\t\t\t\tvar panel = '<div class=\"ui form modal\" id=\"sns_dashboard\">' +\n\t\t\t\t\t\t\t'<div class=\"content\">' +\n\t\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui center aligned tiny header\">' +\n\t\t\t\t\t\t\t\t\t  'As Topic Owner' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"topicName\" placeholder=\"Topic\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"password\" id=\"publishToken\" placeholder=\"Publish Token\"><div style=\"border-top:1px solid #ddd;border-bottom:1px solid #ddd\"><i class=\"eye icon toggle-token\" id=\"tokenToggle\" style=\"color:#ddd\"></i></div>' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnCreateTopic\" class=\"ui button\" style=\"width:100px\">Create</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\" style=\"margin-top:5px\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"topicContent\" placeholder=\"Content to Post\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnPostToTopic\" class=\"ui button\" style=\"width:100px\">Post</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\" style=\"margin-top:5px\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"openAIContent\" placeholder=\"Chat with OpenAI\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnChatWithOpenAI\" class=\"ui button\" style=\"width:100px\">Chat</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\" style=\"margin-top:5px\">' +\n\t\t\t\t\t\t\t\t\t\t'<textarea id=\"openAIResponse\"></textarea>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui center aligned tiny header\">' +\n\t\t\t\t\t\t\t\t\t  'As Subscriber' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid action input\" style=\"margin-top:5px\">' +\n\t\t\t\t\t\t\t\t\t\t'<input type=\"text\" id=\"topicToSubscribeTo\" placeholder=\"Topic to Subscribe to\">' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnSubscribeToTopic\" class=\"ui button\" style=\"width:100px\">Subscribe</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t'<div class=\"actions\">' +\n\t\t\t\t\t\t\t\t'<div class=\"ui button\" id=\"btnCloseSnsDashboard\">Close</div>' +\n\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t'</div>'\n\n\t\t\t\t\t\t$(\"#reserved_zone\").append(panel)\n\n\t\t\t\t\t\tvar that = this\n\n\t\t\t\t\t\t$(\"#btnCreateTopic\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar topic = $(\"#topicName\").val().trim()\n\t\t\t\t\t\t\tvar publishToken = $(\"#publishToken\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\") {\n\t\t\t\t\t\t\t\tthat.createTopic(topic, publishToken)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnPostToTopic\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar topic = $(\"#topicName\").val().trim()\n\t\t\t\t\t\t\tvar publishToken = $(\"#publishToken\").val().trim()\n\t\t\t\t\t\t\tvar content = $(\"#topicContent\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\" && publishToken != \"\" && content != \"\" && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.postToTopic(topic, publishToken, content)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnChatWithOpenAI\").on(\"click\", function () {\n\t\t\t\t\t\t\t$(\"#btnChatWithOpenAI\").prop(\"disabled\", true)\n\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t$(\"#btnChatWithOpenAI\").prop(\"disabled\", false)\n\t\t\t\t\t\t\t}, 15000)\n\t\t\t\t\t\t\tvar topic = $(\"#topicName\").val().trim()\n\t\t\t\t\t\t\tvar publishToken = $(\"#publishToken\").val().trim()\n\t\t\t\t\t\t\tvar content = $(\"#openAIContent\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\" && publishToken != \"\" && content != \"\" && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.chatWithOpenAI(topic, publishToken, content)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnSubscribeToTopic\").on(\"click\", function () {\n\t\t\t\t\t\t\tvar topic = $(\"#topicToSubscribeTo\").val().trim()\n\n\t\t\t\t\t\t\tif (topic != \"\" && that.bConnected) {\n\t\t\t\t\t\t\t\tthat.subscribeToTopic(topic)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#btnCloseSnsDashboard\").on(\"click\", function () {\n\t\t\t\t\t\t\t$(\"#sns_dashboard\").modal(\"hide\")\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t$(\"#tokenToggle\").on(\"click\", function() {\n\t\t\t\t      var tokenInput = $(\"#publishToken\")\n\t\t\t\t      var icon = $(this)\n\n\t\t\t\t      if (tokenInput.attr(\"type\") == \"password\") {\n\t\t\t\t        tokenInput.attr(\"type\", \"text\")\n\t\t\t\t      } else {\n\t\t\t\t        tokenInput.attr(\"type\", \"password\")\n\t\t\t\t      }\n\t\t\t\t    })\n\t\t\t\t\t}\n\n\t\t\t\t\t$(\"#sns_dashboard\").modal({autofocus:false}).modal(\"show\")\n\n\t\t\t\t\tthis.reconnect()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\twindow.pluginForSns.initDashboard()\n\n\t\tif (typeof window.fintecheeBarrage != \"undefined\") {\n\t\t\tfor (var i in window.fintecheeBarrage.context) {\n\t\t\t\twindow.pluginForSns.subscribe(\"barrage-\" + i, window.fintecheeBarrage.callback, window.fintecheeBarrage.context[i])\n\t\t\t}\n\t\t}\n\t},\n\tfunction (context) { // Deinit()\n\t},\n\tfunction (context) { // OnTick()\n\t}\n)\n"
  },
  {
    "path": "EA/Plugin-for-SNS-with-OpenAI/usage.txt",
    "content": "1, Launch an EA (Expert Advisor) named \"plugin_for_sns_with_openai\".\n2, If you are a publisher, input the topic name and click the \"Create\" button. The backend system will create a topic for you (if the topic already exists, the creation will fail) and generate a publish token. You can then begin posting your content or chat with OpenAI.\n3, If you are a subscriber, input the topic you wish to subscribe to. Afterward, please add an indicator called \"barrage\" to the chart. Whenever the publisher posts content, you will see a triangle on the chart. Hover your mouse over the triangle to view the content from the publisher in your social network.\n\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/import_export_model.js",
    "content": "registerEA(\n\"import_export_model\",\n\"An EA to import a model from files to localStorage or export a model from localStorage to files(v1.0)\",\n[{\n\tname: \"tfModelName\",\n\tvalue: \"testcnn\",\n\trequired: true,\n\ttype: \"String\",\n\trange: null,\n\tstep: null\n}, {\n\tname: \"import\",\n\tvalue: true, // If true, then this EA imports the specific model from files to localStorage. If false, then this EA exports the specific model from localStorage to files.\n\trequired: true,\n\ttype: \"Boolean\",\n\trange: null,\n\tstep: null\n}],\nfunction (context) { // Init()\n    if (typeof window.tf == \"undefined\") {\n      printErrorMessage(\"Please run the plugin to load Tensorflow first.\")\n      return\n    }\n\n    var tfModelName = getEAParameter(context, \"tfModelName\")\n    var bImport = getEAParameter(context, \"import\")\n\n    context.cnn = {\n      initDashboard: function () {\n        if (typeof $(\"#import_cnn_model\").html() == \"undefined\") {\n          var panel = '<div class=\"ui form modal\" id=\"import_cnn_model\">' +\n            '<div class=\"content\">' +\n\t\t\t\t\t\t\t'<div class=\"row\">' +\n\t\t\t\t\t\t\t\t'No worries. The model files will not be uploaded to anywhere. It will be just imported to the LocalStorage of your browser.' +\n\t\t\t\t\t\t\t'</div>' +\n              '<div class=\"row\">' +\n\t\t\t\t\t\t\t\t'<div class=\"ui middle aligned center aligned\">' +\n\t\t\t\t\t\t\t\t\t'<div class=\"ui fluid segment\" style=\"height:100px\">' +\n\t\t\t\t\t\t\t\t\t\t'<input style=\"width:0.1px;height:0.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1\" type=\"file\" id=\"jsonFile\"><label for=\"jsonFile\" class=\"ui huge green left floated button\">JSON File</label>' +\n\t\t\t\t\t\t\t\t\t\t'<input style=\"width:0.1px;height:0.1px;opacity:0;overflow:hidden;position:absolute;z-index:-1\" type=\"file\" id=\"weightsFile\"><label for=\"weightsFile\" class=\"ui huge green left floated button\">Weights File</label>' +\n\t\t\t\t\t\t\t\t\t\t'<button id=\"btnImportModel\" class=\"ui huge right floated button\">Import</button>' +\n\t\t\t\t\t\t\t\t\t'</div>' +\n\t\t\t\t\t\t\t\t'</div>' +\n              '</div>' +\n            '</div>' +\n          '</div>'\n\n          $(\"#reserved_zone\").append(panel)\n\n          var that = this\n\n          $(\"#btnImportModel\").on(\"click\", function () {\n\t\t\t\t\t\tcontext.cnn.importModel()\n          })\n\t\t\t\t}\n\n\t\t\t\t$(\"#import_cnn_model\").modal({autofocus:false}).modal(\"show\")\n      },\n\t\t\timportModel: function () {\n\t\t\t\tvar jsonFile = document.getElementById(\"jsonFile\")\n\t\t\t\tvar weightsFile = document.getElementById(\"weightsFile\")\n\n\t\t\t\tif (jsonFile.files.length == 0 || weightsFile.files[0] == 0) {\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\tcontext.cnn.importModel()\n\t\t\t\t\t}, 1000)\n\t\t\t\t} else {\n\t\t\t\t\t$(\"#import_cnn_model\").modal(\"hide\")\n\n\t\t\t\t\twindow.loadCnn(tfModelName, true, jsonFile.files[0], weightsFile.files[0])\n\t\t\t\t\t.then(function (tfModel) {\n\t\t\t\t\t\twindow.saveCnn(tfModel, tfModelName, false)\n\t\t\t\t\t\tpopupMessage(\"Successfully imported the CNN model.\")\n\t\t\t\t\t})\n\t\t\t\t\t.catch(function (e) {\n\t\t\t\t\t\tpopupErrorMessage(\"Failed to import the CNN model.\")\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n    }\n\n    if (bImport) {\n      context.cnn.initDashboard()\n    } else {\n      window.loadCnn(tfModelName)\n      .then(function (tfModel) {\n        window.saveCnn(tfModel, tfModelName, true)\n\t\t\t\tpopupMessage(\"Successfully exported the CNN model.\")\n      })\n      .catch(function (e) {\n        popupErrorMessage(\"Failed to load the CNN model.\")\n      })\n    }\n  },\nfunction (context) { // Deinit()\n},\nfunction (context) { // OnTick()\n},\nfunction (context) { // OnTransaction()\n}\n)\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/plugin_to_load_tensorflow.js",
    "content": "registerEA(\n\t  \"plugin_to_load_tensorflow\",\n\t  \"A plugin to load Tensorflow(v1.13)\",\n\t  [{ // parameters\n\t    name: \"tfjs\",\n\t    value: \"https://www.fintechee.com/js/tf/tf.min.js\",\n\t    required: false,\n\t    type: PARAMETER_TYPE.STRING,\n\t    range: null\n\t  },{\n\t    name: \"tfvisjs\",\n\t    value: \"https://www.fintechee.com/js/tf/tfjs-vis.js\",\n\t    required: false,\n\t    type: PARAMETER_TYPE.STRING,\n\t    range: null\n\t\t}],\n\t  function (context) { // Init()\n\t    if (typeof tf == \"undefined\") {\n\t      var tfjs = getEAParameter(context, \"tfjs\")\n\t      var tfvisjs = getEAParameter(context, \"tfvisjs\")\n\n\t      var tags = document.getElementsByTagName(\"script\")\n\t      for (var i = tags.length - 1; i >= 0; i--) {\n\t        if (tags[i] && tags[i].getAttribute(\"src\") != null && (tags[i].getAttribute(\"src\") == tfjs || tags[i].getAttribute(\"src\") == tfvisjs)) {\n\t          tags[i].parentNode.removeChild(tags[i])\n\t        }\n\t      }\n\n\t      var script1 = document.createElement(\"script\")\n\t      document.body.appendChild(script1)\n\t      script1.onload = function () {\n\t        var script2 = document.createElement(\"script\")\n\t\t      document.body.appendChild(script2)\n\t\t      script2.onload = function () {\n\t\t\t\t\t\t// Deprecated. It will be retained for compatibility with existing source codes.\n\t          window.buildCnn = function (featuresNum, kernelSize, filters, strides) {\n\t            return new Promise(function (resolve, reject) {\n\t              var tfModel = window.tf.sequential()\n\n\t              tfModel.add(window.tf.layers.conv1d({\n\t                inputShape: [featuresNum, 1],\n\t                kernelSize: kernelSize,\n\t                filters: filters,\n\t                strides: strides,\n\t                use_bias: true,\n\t                activation: \"relu\",\n\t                kernelInitializer: \"VarianceScaling\"\n\t              }))\n\n\t              tfModel.add(window.tf.layers.flatten({\n\t              }))\n\n\t              tfModel.add(window.tf.layers.dense({\n\t                units: 2,\n\t                kernelInitializer: \"VarianceScaling\",\n\t                activation: \"softmax\"\n\t              }))\n\n\t              return resolve(tfModel)\n\t            })\n\t          }\n\n\t\t\t\t\t\t// substitution for buildCnn\n\t\t\t\t\t\twindow.buildExtraCnn = function (featuresNum, kernelSize, filters, strides, units) {\n\t            return new Promise(function (resolve, reject) {\n\t              var tfModel = window.tf.sequential()\n\n\t              tfModel.add(window.tf.layers.conv1d({\n\t                inputShape: [featuresNum, 1],\n\t                kernelSize: kernelSize,\n\t                filters: filters,\n\t                strides: strides,\n\t                use_bias: true,\n\t                activation: \"relu\",\n\t                kernelInitializer: \"VarianceScaling\"\n\t              }))\n\n\t              tfModel.add(window.tf.layers.flatten({\n\t              }))\n\n\t              tfModel.add(window.tf.layers.dense({\n\t                units: units,\n\t                kernelInitializer: \"VarianceScaling\",\n\t                activation: \"softmax\"\n\t              }))\n\n\t              return resolve(tfModel)\n\t            })\n\t          }\n\n\t          window.trainCnn = function (tfModel, trainingSet, epochs, batchSize, bMonitor) {\n\t            if (bMonitor) {\n\t              printMessage(\"Summary: \")\n\t              tfModel.summary()\n\t            }\n\n\t            return new Promise(function (resolve, reject) {\n\t              try {\n\t                tfModel.compile({\n\t                  optimizer: window.tf.train.adam(),\n\t                  loss: \"categoricalCrossentropy\",\n\t                  metrics: [\"accuracy\"]\n\t                })\n\n\t                if (bMonitor) {\n\t                  tfModel.fit(trainingSet.input, trainingSet.output, {\n\t                    batchSize: batchSize,\n\t                    epochs: epochs,\n\t                    shuffle: true,\n\t                    callbacks: tfvis.show.fitCallbacks({\n\t                      name: \"Model Training\", tab: \"Model\", styles: { height: \"500px\" }\n\t                    }, [\"loss\", \"val_loss\", \"acc\", \"val_acc\"])\n\t                  }).then(function (result) {\n\t\t\t\t\t\t\t\t\t\t\tif (typeof result.history.loss != \"undefined\") {\n\t\t\t\t\t\t\t\t\t\t\t\tprintMessage(\"Loss after last Epoch (\" + result.epoch.length + \") is: \" + result.history.loss[result.epoch.length-1])\n\t\t\t\t\t\t\t\t\t\t\t}\n\t                    resolve()\n\t                  })\n\n\t                  $(\"#tfjs-visor-container\").show()\n\t                } else {\n\t                  tfModel.fit(trainingSet.input, trainingSet.output, {\n\t                    batchSize: batchSize,\n\t                    epochs: epochs,\n\t                    shuffle: true\n\t                  }).then(function (result) {\n\t\t\t\t\t\t\t\t\t\t\tif (typeof result.history.loss != \"undefined\") {\n\t                    \tprintMessage(\"Loss after last Epoch (\" + result.epoch.length + \") is: \" + result.history.loss[result.epoch.length-1])\n\t\t\t\t\t\t\t\t\t\t\t}\n\t                    resolve()\n\t                  })\n\t                }\n\t              } catch (ex) {\n\t                reject(ex)\n\t              }\n\t            })\n\t          }\n\n\t\t\t\t\t\twindow.checkIfCnnExisted = function (tfModelName) {\n\t\t\t\t\t\t\treturn new Promise(function (resolve, reject) {\n\t\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tvar models = await tf.io.listModels()\n\n\t\t\t\t\t\t\t\t\t\tvar key = `localstorage://${tfModelName}`\n\t\t\t\t\t\t\t\t\t\tif (models[key]) {\n\t\t\t\t\t\t\t\t\t\t\tresolve({res:true})\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tresolve({res:false})\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\treject(e.message)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.saveCnn = function (tfModel, tfModelName, bNotLocal) {\n\t\t\t\t\t\t\treturn new Promise(function (resolve, reject) {\n\t\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (typeof bNotLocal == \"undefined\" || (typeof bNotLocal == \"boolean\" && !bNotLocal)) {\n\t\t\t\t\t\t\t\t\t\t\tawait tfModel.save(\"localstorage://\" + tfModelName)\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tawait tfModel.save(\"downloads://\" + tfModelName)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tresolve()\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\treject(e.message)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.loadCnn = function (tfModelName, bNotLocal, jsonFile, weightsFile) {\n\t\t\t\t\t\t\treturn new Promise(function (resolve, reject) {\n\t\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tvar tfModel = null\n\t\t\t\t\t\t\t\t\t\tif (typeof bNotLocal == \"undefined\" || (typeof bNotLocal == \"boolean\" && !bNotLocal)) {\n\t\t\t\t\t\t\t\t\t\t\ttfModel = await window.tf.loadLayersModel(\"localstorage://\" + tfModelName)\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\ttfModel = await window.tf.loadLayersModel(window.tf.io.browserFiles([jsonFile, weightsFile]))\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tresolve(tfModel)\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\treject(e.message)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.loadRemoteCnn = function (jsonUrl) {\n\t\t\t\t\t\t\treturn new Promise(function (resolve, reject) {\n\t\t\t\t\t\t\t\t(async () => {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tvar tfModel = await window.tf.loadLayersModel(jsonUrl)\n\n\t\t\t\t\t\t\t\t\t\tresolve(tfModel)\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\treject(e.message)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Deprecated. It will be retained for compatibility with existing source codes.\n\t\t\t\t\t\twindow.runCnn = function (tfModel, input, inputNum) {\n\t\t\t\t\t\t\treturn window.tf.tidy(function () {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\treturn tfModel.predict(window.tf.tensor3d(input, [1, inputNum, 1])).arraySync()[0][0]\n\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\treturn -1\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// substitution for runCnn\n\t\t\t\t\t\twindow.getArgMaxOfCnn = function (tfModel, input, inputNum) {\n\t\t\t\t\t\t\treturn window.tf.tidy(function () {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tvar arr = tfModel.predict(window.tf.tensor3d(input, [1, inputNum, 1])).arraySync()[0]\n\t\t\t\t\t\t\t\t\treturn arr.indexOf(Math.max(...arr))\n\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\treturn -1\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.removeCnn = function (tfModelName) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\twindow.tf.io.removeModel(\"localstorage://\" + tfModelName)\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t(async function () {\n\t\t\t\t\t\t\tawait window.tf.ready()\n\t\t\t\t\t\t\tif (window.tf.getBackend() == \"webgl\") {\n\t\t\t\t\t\t\t\twindow.tf.tensor(0).dataSync()\n\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\twindow.tf.env().registerFlag(\"WEBGL_DELETE_TEXTURE_THRESHOLD\", () => 128 * 1024 * 1024, (val) => {\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\twindow.tf.env().set(\"WEBGL_DELETE_TEXTURE_THRESHOLD\", 128 * 1024 * 1024)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})()\n\n\t          popupMessage(\"Tensorflow has been loaded successfully!\")\n\t        }\n\t        script2.onerror = function () {\n\t          popupErrorMessage(\"Failed to load Tensorflow! Please run this plugin again.\")\n\t        }\n\t\t      script2.async = true\n\t\t      script2.src = tfvisjs\n\t      }\n\t      script1.onerror = function () {\n\t        popupErrorMessage(\"Failed to load Tensorflow! Please run this plugin again.\")\n\t      }\n\t      script1.async = true\n\t      script1.src = tfjs\n\t    }\n\t  },\n\t  function (context) { // Deinit()\n\t  },\n\t  function (context) { // OnTick()\n\t  }\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/sample_running_cnn_model.js",
    "content": "registerEA(\n\t  \"sample_running_cnn_model\",\n\t  \"An EA sample to run neuron model(v1.04)\",\n\t  [{ // parameters\n\t    name: \"version\",\n\t    value: 1,\n\t    required: true,\n\t    type: PARAMETER_TYPE.NUMBER,\n\t    range: [0, 100]\n\t  }, {\n\t    name: \"symbolName\",\n\t    value: \"EUR/USD\",\n\t    required: true,\n\t    type: PARAMETER_TYPE.STRING,\n\t    range: null\n\t  }, {\n\t    name: \"timeFrame\",\n\t    value: \"H1\",\n\t    required: true,\n\t    type: PARAMETER_TYPE.STRING,\n\t    range: null\n\t  }, {\n\t    name: \"inputNum\",\n\t    value: 10,\n\t    required: true,\n\t    type: PARAMETER_TYPE.INTEGER,\n\t    range: [1, 100]\n\t  }, {\n\t    name: \"hiddenNum\",\n\t    value: 20,\n\t    required: true,\n\t    type: PARAMETER_TYPE.INTEGER,\n\t    range: [1, 100]\n\t  }, {\n\t    name: \"predictNum\",\n\t    value: 10,\n\t    required: true,\n\t    type: PARAMETER_TYPE.INTEGER,\n\t    range: [1, 100]\n\t  }, {\n\t    name: \"volume\",\n\t    value: 0.01,\n\t    required: true,\n\t    type: PARAMETER_TYPE.NUMBER,\n\t    range: [0.01, 1]\n\t  }],\n\t  function (context) { // Init()\n\t    if (typeof window.tf == \"undefined\") {\n\t      printErrorMessage(\"Please run the plugin to load Tensorflow first.\")\n\t      return\n\t    }\n\n\t    var version = getEAParameter(context, \"version\")\n\t    var symbolName = getEAParameter(context, \"symbolName\")\n\t    var timeFrame = getEAParameter(context, \"timeFrame\")\n\t    var inputNum = getEAParameter(context, \"inputNum\")\n\t    var hiddenNum = getEAParameter(context, \"hiddenNum\")\n\t    var predictNum = getEAParameter(context, \"predictNum\")\n\n\t    context.runMyCnn = function (input) {\n\t      if (typeof input == \"undefined\" || input.length == 0) return -1\n\n\t      var result = window.runCnn(this.tfModel, input, inputNum)\n\n\t      printMessage(result)\n\n\t      return result\n\t    }\n\n\t\t\tvar tfModelName = \"Fintechee \" + symbolName.replace(\"/\", \"\") + \"-\" + timeFrame + \"-\" + inputNum + \"-\" + hiddenNum + \"-\" + predictNum + \"-\" + version\n\n\t\t\tcontext.tfModel = null\n\t\t\twindow.loadCnn(tfModelName)\n\t\t\t.then(function (tfModel) {\n\t\t\t\tcontext.tfModel = tfModel\n\t\t\t})\n\t\t\t.catch(function (e) {\n\t\t\t\tpopupErrorMessage(\"Failed to load the CNN model.\")\n\t\t\t})\n\n\t    var account = getAccount(context, 0)\n\t    var brokerName = getBrokerNameOfAccount(account)\n\t    var accountId = getAccountIdOfAccount(account)\n\n\t    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n\t    context.indiHandleMacd = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"macd\", [{\n\t      name: \"fastEMA\",\n\t      value: 12\n\t    },{\n\t      name: \"slowEMA\",\n\t      value: 26\n\t    },{\n\t      name: \"signalSMA\",\n\t      value: 9\n\t    }])\n\n\t\t\tcontext.tradingManager = {\n\t      posLong: [],\n\t      posShort: [],\n\t      getPosInfo: function (brokerNm, accId, symbolNm) {\n\t        this.posLong = []\n\t        this.posShort = []\n\n\t        var cnt = getOpenTradesListLength(context)\n\t        for (var i = cnt - 1; i >= 0; i--) {\n\t          var openTrade = getOpenTrade(context, i)\n\t          var symbol = getSymbolName(openTrade)\n\n\t          if (symbol == symbolNm) {\n\t            var orderType = getOrderType(openTrade)\n\n\t            if (orderType == ORDER_TYPE.OP_BUY) {\n\t              this.posLong.push(getTradeId(openTrade))\n\t            } else {\n\t              this.posShort.push(getTradeId(openTrade))\n\t            }\n\t          }\n\t        }\n\t      },\n\t      trade: function (brokerNm, accId, symbolNm, odrType, volume, orderNum) {\n\t        if (orderNum < 0) return\n\n\t        if (orderNum > 0) {\n\t          var orderLots = volume * orderNum\n\n\t          if (odrType == ORDER_TYPE.OP_BUY) {\n\t\t\t\t\t\t\tif (this.posLong.length > 0) {\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\n\t            sendOrder(brokerNm, accId, symbolNm, ORDER_TYPE.OP_BUY, 0, 0, Math.round(orderLots * 100) / 100, 0, 0, \"\", 0, 0)\n\t            return true\n\t          } else if (odrType == ORDER_TYPE.OP_SELL) {\n\t\t\t\t\t\t\tif (this.posShort.length > 0) {\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\n\t            sendOrder(brokerNm, accId, symbolNm, ORDER_TYPE.OP_SELL, 0, 0, Math.round(orderLots * 100) / 100, 0, 0, \"\", 0, 0)\n\t            return true\n\t          }\n\t        } else {\n\t          if (odrType == ORDER_TYPE.OP_BUY) {\n\t            var bClosed = false\n\t            for (var i in this.posLong) {\n\t              closeTrade(brokerNm, accId, this.posLong[i], 0, 0)\n\t              bClosed = true\n\t            }\n\t          } else if (odrType == ORDER_TYPE.OP_SELL) {\n\t            var bClosed = false\n\t            for (var i in this.posShort) {\n\t              closeTrade(brokerNm, accId, this.posShort[i], 0, 0)\n\t              bClosed = true\n\t            }\n\t          }\n\n\t          if (bClosed) {\n\t            return true\n\t          }\n\t        }\n\n\t        return false\n\t      }\n\t    }\n\n\t\t\tcontext.signalManager = {\n\t      inputNum: inputNum,\n\t      checkCnnSignal: function (arrMain) {\n\t        var arrLen = arrMain.length\n\n\t        var input = []\n\t        var highVal = -Number.MAX_VALUE\n\t        var lowVal = Number.MAX_VALUE\n\n\t        for (var i = this.inputNum + 1; i >= 2; i--) {\n\t          if (arrMain[arrLen - i] > highVal) {\n\t            highVal = arrMain[arrLen - i]\n\t          }\n\t          if (arrMain[arrLen - i] < lowVal) {\n\t            lowVal = arrMain[arrLen - i]\n\t          }\n\t        }\n\n\t        var height = highVal - lowVal\n\t        if (height <= 0) {\n\t          return -1\n\t        }\n\n\t\t\t\t\tfor (var i = this.inputNum + 1; i >= 2; i--) {\n\t          input.push((arrMain[arrLen - i] - lowVal) / height)\n\t        }\n\n\t        var result = this.runMyCnn(input)\n\n\t        return result == -1 ? -1 : (result >= 0.5 ? 1 : 0)\n\t      },\n\t      upSl: 0,\n\t      downSl: 0,\n\t      predictNum: predictNum,\n\t      checkCloseSignal: function (currIdx) {\n\t        var signal = -1\n\n\t        if (this.upSl > 0) {\n\t          if (currIdx - this.upSl > this.predictNum) {\n\t            signal = 3\n\t          }\n\t        }\n\n\t        if (this.downSl > 0) {\n\t          if (currIdx - this.downSl > this.predictNum) {\n\t            signal = 2\n\t          }\n\t        }\n\n\t        return signal\n\t      }\n\t    }\n\t  },\n\t  function (context) { // Deinit()\n\t  },\n\t  function (context) { // OnTick()\n\t    if (typeof window.tf == \"undefined\") {\n\t      return\n\t    }\n\n\t    if (context.tfModel == null) return\n\t    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n\t    if (typeof context.currTime == \"undefined\") {\n\t      context.currTime = arrTime[arrTime.length - 1]\n\t    } else if (context.currTime != arrTime[arrTime.length - 1]) {\n\t      context.currTime = arrTime[arrTime.length - 1]\n\t    } else {\n\t      return\n\t    }\n\n\t    var account = getAccount(context, 0)\n\t    var brokerName = getBrokerNameOfAccount(account)\n\t    var accountId = getAccountIdOfAccount(account)\n\t    var symbolName = getEAParameter(context, \"symbolName\")\n\n\t    var version = getEAParameter(context, \"version\")\n\t    var inputNum = getEAParameter(context, \"inputNum\")\n\t    var predictNum = getEAParameter(context, \"predictNum\")\n\t\t\tvar arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)\n\t    var arrMain = getData(context, context.indiHandleMacd, \"main\")\n\n\t    if (200 >= arrMain.length) throw new Error(\"No enough data.\")\n\n\t\t\tvar account = getAccount(context, 0)\n\t\t  var brokerName = getBrokerNameOfAccount(account)\n\t\t  var accountId = getAccountIdOfAccount(account)\n\t\t  var symbolName = getEAParameter(context, \"symbolName\")\n\t\t  var volume = getEAParameter(context, \"volume\")\n\n\t\t  var signal = -1\n\t\t\tvar arrLen =  arrClose.length\n\t\t  var currTick = arrClose[arrLen - 1]\n\n\t\t  context.tradingManager.getPosInfo(brokerName, accountId, symbolName)\n\n\t\t  if (context.signalManager.upSl > 0 || context.signalManager.downSl > 0) {\n\t\t    signal = context.signalManager.checkCloseSignal(arrLen - 1)\n\t\t  }\n\n\t\t  if (signal == -1) {\n\t\t    signal = context.signalManager.checkCnnSignal(arrMain)\n\t\t  }\n\n\t\t  if (signal == 1) {\n\t\t    if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, volume, 1)) {\n\t\t      context.signalManager.upSl = arrLen - 1\n\t\t    }\n\t\t  } else if (signal == 0) {\n\t\t    if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, volume, 1)) {\n\t\t      context.signalManager.downSl = arrLen - 1\n\t\t    }\n\t\t  } else if (signal == 3) {\n\t\t    if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, volume, 0)) {\n\t\t      context.signalManager.upSl = 0\n\t\t    }\n\t\t  } else if (signal == 2) {\n\t\t    if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, volume, 0)) {\n\t\t      context.signalManager.downSl = 0\n\t\t    }\n\t\t  }\n\t  }\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/sample_training_cnn_model.js",
    "content": "registerEA(\n\t\"sample_training_cnn_model\",\n\t\"An EA sample to train neuron model(v1.05)\",\n\t[{\n\t\tname: \"version\",\n\t\tvalue: 1,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\trange: [0, 100],\n\t\tstep: null\n\t}, {\n\t\tname: \"symbolName\",\n\t\tvalue: \"EUR/USD\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING,\n\t\trange: null,\n\t\tstep: null\n\t}, {\n\t\tname: \"timeFrame\",\n\t\tvalue: \"H1\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING,\n\t\trange: null,\n\t\tstep: null\n\t}, {\n\t\tname: \"inputNum\",\n\t\tvalue: 10,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100],\n\t\tstep: null\n\t}, {\n\t\tname: \"hiddenNum\",\n\t\tvalue: 20,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100],\n\t\tstep: null\n\t}, {\n\t\tname: \"predictNum\",\n\t\tvalue: 10,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100],\n\t\tstep: null\n\t}, {\n\t\tname: \"iterations\",\n\t\tvalue: 10000,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 1000000],\n\t\tstep: null\n\t}, {\n\t\tname: \"batchSize\",\n\t\tvalue: 512,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100000],\n\t\tstep: null\n\t}, {\n\t\tname: \"bContinue\",\n\t\tvalue: false,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.BOOLEAN,\n\t\trange: null,\n\t\tstep: null\n\t}, {\n\t\tname: \"bTest\",\n\t\tvalue: false,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.BOOLEAN,\n\t\trange: null,\n\t\tstep: null\n\t}, {\n\t\tname: \"bMem\",\n\t\tvalue: false,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.BOOLEAN,\n\t\trange: null,\n\t\tstep: null\n\t}, {\n\t\tname: \"bMonitor\",\n\t\tvalue: false,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.BOOLEAN,\n\t\trange: null,\n\t\tstep: null\n\t}],\n\tfunction (context) { // Init()\n\t    if (typeof window.tf == \"undefined\") {\n\t      printErrorMessage(\"Please run the plugin to load Tensorflow first.\")\n\t      return\n\t    }\n\n\t    var version = getEAParameter(context, \"version\")\n\t\t\tvar symbolName = getEAParameter(context, \"symbolName\")\n\t    var timeFrame = getEAParameter(context, \"timeFrame\")\n\t    var iterations = getEAParameter(context, \"iterations\")\n\t    var inputNum = getEAParameter(context, \"inputNum\")\n\t    var hiddenNum = getEAParameter(context, \"hiddenNum\")\n\t    var predictNum = getEAParameter(context, \"predictNum\")\n\t    var bContinue = getEAParameter(context, \"bContinue\")\n\t\t\tvar bTest = getEAParameter(context, \"bTest\")\n\t    var bMem = getEAParameter(context, \"bMem\")\n\t    var bMonitor = getEAParameter(context, \"bMonitor\")\n\t    var batchSize = getEAParameter(context, \"batchSize\")\n\t\t\tvar tfModelName = \"Fintechee \" + symbolName.replace(\"/\", \"\") + \"-\" + timeFrame + \"-\" + inputNum + \"-\" + hiddenNum + \"-\" + predictNum + \"-\" + version\n\n\t    context.buildMyCnn = function () {\n\t      window.buildCnn(inputNum, inputNum, hiddenNum, inputNum).then(function (tfModel) {\n\t        context.tfModel = tfModel\n\t      })\n\t    }\n\n\t\t\tcontext.runMyCnn = function (input) {\n\t      return window.runCnn(this.tfModel, input, inputNum)\n\t    }\n\n\t    context.trainMyCnn = function () {\n\t      printMessage(\"Start training!\")\n\n\t      window.trainCnn(this.tfModel, window.tensorSet, iterations, batchSize, bMonitor).then(function () {\n\t        printMessage(\"Training is done!\");\n\n\t\t\t\t\twindow.saveCnn(context.tfModel, tfModelName)\n\n\t        var longCnt = 0\n\t        var shortCnt = 0\n\t        var longWinCnt = 0\n\t        var shortWinCnt = 0\n\t        var levelCnt = []\n\t        var levelWinCnt = []\n\t        var levelProfit = []\n\t        var levelLoss = []\n\t        var longProfit = 0\n\t        var shortProfit = 0\n\t        var longLoss = 0\n\t        var shortLoss = 0\n\n\t        for (var i = 0; i < window.tensorSet.lsCount; i++) {\n\t          var input = []\n\n\t          for (var j = 0; j < inputNum; j++) {\n\t            input.push(window.tensorSet.trainingSetI[i * inputNum + j])\n\t          }\n\n\t          var output = window.tensorSet.trainingSetO[i * 2]\n\n\t          var profit = window.tensorSet.trainingSetP[i]\n\n\t          var result = context.runMyCnn(input)\n\t          var resWin = (result == -1 ? false : ((result >= 0.5 ? 1 : 0) == output ? true : false))\n\n\t          var idx = Math.floor(Math.floor(result * 100) / Math.floor(100 / 10)) * Math.floor(100 / 10)\n\n\t          if (typeof levelCnt[idx] == \"undefined\") {\n\t            levelCnt[idx] = 0\n\t            levelWinCnt[idx] = 0\n\t            levelProfit[idx] = 0\n\t            levelLoss[idx] = 0\n\t          }\n\n\t          levelCnt[idx]++\n\n\t          if (resWin) {\n\t            if (output == 1) {\n\t              longCnt++\n\t              longWinCnt++\n\t              longProfit += profit\n\t            } else {\n\t              shortCnt++\n\t              shortWinCnt++\n\t              shortProfit += profit\n\t\t\t\t\t\t\t}\n\t            levelWinCnt[idx]++\n\t            levelProfit[idx] += profit\n\t          } else {\n\t            if (output == 1) {\n\t              shortCnt++\n\t              shortLoss += profit\n\t            } else {\n\t              longCnt++\n\t              longLoss += profit\n\t            }\n\t            levelLoss[idx] += profit\n\t          }\n\t        }\n\n\t        printMessage(tfModelName)\n\n\t        printMessage(\"Long: \" + longCnt + \", \" + (longWinCnt / window.tensorSet.lsCount) + \", \" + longProfit + \", \" + longLoss + \", \" + ((longProfit - longLoss) / longCnt))\n\t        printMessage(\"Short: \" + shortCnt + \", \" + (shortWinCnt / window.tensorSet.lsCount) + \", \" + shortProfit + \", \" + shortLoss + \", \" + ((shortProfit - shortLoss) / shortCnt))\n\n\t        for (var i in levelCnt) {\n\t          printMessage(i + \", \" + levelCnt[i] + \", \" + (levelWinCnt[i] / levelCnt[i]) + \", \" + levelProfit[i] + \", \" + levelLoss[i] + \", \" + ((levelProfit[i] - levelLoss[i]) / levelCnt[i]))\n\t        }\n\n\t        $(\"#tfjs-visor-container\").hide()\n\t      })\n\t    }\n\n\t    context.testMyCnn = function () {\n\t      printMessage(\"Start testing!\")\n\n\t      var longCnt = 0\n\t      var shortCnt = 0\n\t      var longWinCnt = 0\n\t      var shortWinCnt = 0\n\t      var levelCnt = []\n\t      var levelWinCnt = []\n\t      var levelProfit = []\n\t      var levelLoss = []\n\t      var longProfit = 0\n\t      var shortProfit = 0\n\t      var longLoss = 0\n\t      var shortLoss = 0\n\n\t      for (var i = 0; i < window.tensorSet.testLsCount; i++) {\n\t        var input = []\n\n\t        for (var j = 0; j < inputNum; j++) {\n\t          input.push(window.tensorSet.testSetI[i * inputNum + j])\n\t        }\n\n\t        var output = window.tensorSet.testSetO[i * 2]\n\n\t        var profit = window.tensorSet.testSetP[i]\n\n\t\t\t\t\tvar result = this.runMyCnn(input)\n\t\t\t\t\tvar resWin = (result == -1 ? false : ((result >= 0.5 ? 1 : 0) == output ? true : false))\n\n\t        var idx = Math.floor(Math.floor(result * 100) / Math.floor(100 / 10)) * Math.floor(100 / 10)\n\n\t        if (typeof levelCnt[idx] == \"undefined\") {\n\t          levelCnt[idx] = 0\n\t          levelWinCnt[idx] = 0\n\t          levelProfit[idx] = 0\n\t          levelLoss[idx] = 0\n\t        }\n\n\t        levelCnt[idx]++\n\n\t        if (resWin) {\n\t          if (output == 1) {\n\t            longCnt++\n\t            longWinCnt++\n\t            longProfit += profit\n\t          } else {\n\t            shortCnt++\n\t            shortWinCnt++\n\t            shortProfit += profit\n\t          }\n\t          levelWinCnt[idx]++\n\t          levelProfit[idx] += profit\n\t        } else {\n\t          if (output == 1) {\n\t            shortCnt++\n\t            shortLoss += profit\n\t          } else {\n\t            longCnt++\n\t            longLoss += profit\n\t          }\n\t          levelLoss[idx] += profit\n\t        }\n\t      }\n\n\t      printMessage(tfModelName)\n\n\t      printMessage(\"Long: \" + longCnt + \", \" + (longWinCnt / window.tensorSet.testLsCount) + \", \" + longProfit + \", \" + longLoss + \", \" + ((longProfit - longLoss) / longCnt))\n\t      printMessage(\"Short: \" + shortCnt + \", \" + (shortWinCnt / window.tensorSet.testLsCount) + \", \" + shortProfit + \", \" + shortLoss + \", \" + ((shortProfit - shortLoss) / shortCnt))\n\n\t      for (var i in levelCnt) {\n\t        printMessage(i + \", \" + levelCnt[i] + \", \" + (levelWinCnt[i] / levelCnt[i]) + \", \" + levelProfit[i] + \", \" + levelLoss[i] + \", \" + ((levelProfit[i] - levelLoss[i]) / levelCnt[i]))\n\t      }\n\n\t      printMessage(\"Testing is done!\")\n\t    }\n\n\t\t\tif (bContinue) {\n\t\t\t\twindow.loadCnn(tfModelName)\n\t\t\t\t.then(function (tfModel) {\n\t\t\t\t\tcontext.tfModel = tfModel\n\n\t\t\t\t\tif (typeof window.tensorSet != \"undefined\") {\n            if (bMem) {\n              if (bTest) {\n                setTimeout(function () {context.testMyCnn()}, 5000)\n              } else {\n                setTimeout(function () {context.trainMyCnn()}, 5000)\n              }\n            }\n          }\n\t\t\t\t})\n\t\t\t\t.catch(function (e) {\n\t\t\t\t\tpopupErrorMessage(\"Failed to load the CNN model.\")\n\t\t\t\t})\n\t    } else {\n\t      context.buildMyCnn()\n\t    }\n\n\t    var account = getAccount(context, 0)\n\t    var brokerName = getBrokerNameOfAccount(account)\n\t    var accountId = getAccountIdOfAccount(account)\n\n\t\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n\t    context.indiHandleMacd = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"macd\", [{\n\t      name: \"fastEMA\",\n\t      value: 12\n\t    },{\n\t      name: \"slowEMA\",\n\t      value: 26\n\t    },{\n\t      name: \"signalSMA\",\n\t      value: 9\n\t    }])\n\t  },\n\tfunction (context) { // Deinit()\n\t    if (typeof window.tf == \"undefined\") {\n\t      printErrorMessage(\"Please run the plugin to load Tensorflow first.\")\n\t      return\n\t    }\n\n\t    var bMem = getEAParameter(context, \"bMem\")\n\t    if (bMem && typeof window.tensorSet != \"undefined\") {\n\t      return\n\t    }\n\n\t    var version = getEAParameter(context, \"version\")\n\t    var inputNum = getEAParameter(context, \"inputNum\")\n\t    var predictNum = getEAParameter(context, \"predictNum\")\n\t\t\tvar bTest = getEAParameter(context, \"bTest\")\n\t\t\tvar arrOpen = getData(context, context.chartHandle, DATA_NAME.OPEN)\n\t    var arrMain = getData(context, context.indiHandleMacd, \"main\")\n\n\t    if (200 >= arrMain.length) throw new Error(\"No enough data.\")\n\n\t    var trainingSetI = []\n\t    var trainingSetO = []\n\t    var trainingSetP = []\n\t\t\tvar longCount = 0\n\t\t\tvar shortCount = 0\n\n\t\t\tfor (var i = 26 + inputNum; i < arrMain.length - predictNum - 1; i++) {\n        var input = []\n        var highVal = -Number.MAX_VALUE\n        var lowVal = Number.MAX_VALUE\n\n        for (var j = inputNum - 1; j >= 0; j--) {\n          if (arrMain[i - j] > highVal) {\n            highVal = arrMain[i - j]\n          }\n          if (arrMain[i - j] < lowVal) {\n            lowVal = arrMain[i - j]\n          }\n        }\n\n        var height = highVal - lowVal\n        if (height <= 0) {\n          continue\n        }\n\n        for (var j = inputNum - 1; j >= 0; j--) {\n          input.push((arrMain[i - j] - lowVal) / height)\n        }\n\n\t\t\t\tfor (var j = 0; j < input.length; j++) {\n\t\t\t\t\ttrainingSetI.push(input[j])\n\t\t\t\t}\n\n        if (arrOpen[i + 1 + predictNum] - arrOpen[i + 1] >= 0) {\n\t\t\t\t\ttrainingSetO.push(1)\n\t\t\t\t\ttrainingSetO.push(0)\n          longCount++\n          trainingSetP.push(arrOpen[i + 1 + predictNum] - arrOpen[i + 1])\n        } else {\n\t\t\t\t\ttrainingSetO.push(0)\n\t\t\t\t\ttrainingSetO.push(1)\n          shortCount++\n          trainingSetP.push(arrOpen[i + 1] - arrOpen[i + 1 + predictNum])\n        }\n      }\n\n\t    var lsCount = longCount + shortCount\n\n\t    if (!bTest) {\n\t      var tensorSet = {\n\t        lsCount: lsCount,\n\t        trainingSetI: trainingSetI,\n\t        trainingSetO: trainingSetO,\n\t        trainingSetP: trainingSetP,\n\t        input: window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1]),\n\t        output: window.tf.tensor2d(trainingSetO, [lsCount, 2]),\n\t      }\n\n\t      if (typeof window.tensorSet == \"undefined\") {\n\t        tensorSet.testLsCount = lsCount\n\t        tensorSet.testSetI = trainingSetI\n\t        tensorSet.testSetO = trainingSetO\n\t        tensorSet.testSetP = trainingSetP\n\t        tensorSet.testInput = window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1])\n\t        tensorSet.testOutput = window.tf.tensor2d(trainingSetO, [lsCount, 2])\n\t      } else {\n\t        tensorSet.testLsCount = window.tensorSet.testLsCount\n\t        tensorSet.testSetI = window.tensorSet.testSetI\n\t        tensorSet.testSetO = window.tensorSet.testSetO\n\t        tensorSet.testSetP = window.tensorSet.testSetP\n\t        tensorSet.testInput = window.tensorSet.testInput\n\t        tensorSet.testOutput = window.tensorSet.testOutput\n\t      }\n\n\t      window.tensorSet = tensorSet\n\n\t      context.trainMyCnn()\n\t    } else {\n\t      var tensorSet = {\n\t        testLsCount: lsCount,\n\t        testSetI: trainingSetI,\n\t        testSetO: trainingSetO,\n\t        testSetP: trainingSetP,\n\t        testInput: window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1]),\n\t        testOutput: window.tf.tensor2d(trainingSetO, [lsCount, 2])\n\t      }\n\n\t      if (typeof window.tensorSet == \"undefined\") {\n\t        tensorSet.lsCount = lsCount\n\t        tensorSet.trainingSetI = trainingSetI\n\t        tensorSet.trainingSetO = trainingSetO\n\t        tensorSet.trainingSetP = trainingSetP\n\t        tensorSet.input = window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1])\n\t        tensorSet.output = window.tf.tensor2d(trainingSetO, [lsCount, 2])\n\t      } else {\n\t        tensorSet.lsCount = window.tensorSet.lsCount\n\t        tensorSet.trainingSetI = window.tensorSet.trainingSetI\n\t        tensorSet.trainingSetO = window.tensorSet.trainingSetO\n\t        tensorSet.trainingSetP = window.tensorSet.trainingSetP\n\t        tensorSet.input = window.tensorSet.input\n\t        tensorSet.output = window.tensorSet.output\n\t      }\n\n\t      window.tensorSet = tensorSet\n\n\t      context.testMyCnn()\n\t    }\n\n\t    printMessage(\"Training Set or Testing Set: \" + longCount + \", \" + shortCount)\n\t  },\n\tfunction (context) { // OnTick()\n\t},\n\tfunction (context) { // OnTransaction()\n\t}\n\t)\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/test_loading_tensorflow.js",
    "content": "registerEA(\n  \"test_loading_tensorflow\",\n  \"A test EA to load Tensorflow2.0 (v1.0)\",\n  [{ // parameters\n    name: \"url\",\n    value: \"https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function (context) { // Init()\n    if (typeof tf == \"undefined\") {\n      var url = getEAParameter(context, \"url\")\n\n      var tags = document.getElementsByTagName(\"script\")\n      for (var i = tags.length - 1; i >= 0; i--) {\n        if (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == url) {\n          tags[i].parentNode.removeChild(tags[i])\n        }\n      }\n\n      var script1 = document.createElement(\"script\")\n      document.body.appendChild(script1)\n      script1.onload = function () {\n      }\n      script1.onerror = function () {}\n      script1.async = true\n      script1.src = url\n    }\n  },\n  function (context) { // Deinit()\n  },\n  function (context) { // OnTick()\n  }\n)\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/test_xor_powered_by_tensorflow.js",
    "content": "registerEA(\n  \"test_xor_powered_by_tensorflow\",\n  \"A test EA to train XOR by using Tensorflow2.0 (v1.0)\",\n  [{ // parameters\n    name: \"tfjs\",\n    value: \"https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  },{\n    name: \"tfvisjs\",\n    value: \"https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  },{\n    name: \"epochs\",\n    value: 10000,\n    required: true,\n    type: PARAMETER_TYPE.INTEGER,\n    range: [1, 1000000]\n  }],\n  function (context) { // Init()\n    window.epochs = getEAParameter(context, \"epochs\")\n\n    if (typeof tf == \"undefined\") {\n      var tfjs = getEAParameter(context, \"tfjs\")\n      var tfvisjs = getEAParameter(context, \"tfvisjs\")\n\n      var tags = document.getElementsByTagName(\"script\")\n      for (var i = tags.length - 1; i >= 0; i--) {\n        if (tags[i] && tags[i].getAttribute(\"src\") != null && tags[i].getAttribute(\"src\") == tfjs && tags[i].getAttribute(\"src\") == tfvisjs) {\n          tags[i].parentNode.removeChild(tags[i])\n        }\n      }\n\n      var script1 = document.createElement(\"script\")\n      document.body.appendChild(script1)\n      script1.onload = function () {\n        var script2 = document.createElement(\"script\")\n\t      document.body.appendChild(script2)\n\t      script2.onload = function () {\n          window.buildCnn = function () {\n            return new Promise(function (resolve, reject) {\n              const model = tf.sequential()\n\n              model.add(tf.layers.inputLayer({\n                inputShape: [2, 1, 1],\n              }))\n\n              model.add(tf.layers.conv2d({\n                inputShape: [2, 1, 1],\n                kernelSize: 1,\n                filters: 2,\n                strides: 1,\n                use_bias: true,\n                activation: \"relu\",\n                kernelInitializer: \"VarianceScaling\"\n              }))\n\n              model.add(tf.layers.maxPooling2d({\n                poolSize: [1, 1],\n                strides: [1, 1]\n              }))\n\n              model.add(tf.layers.flatten({\n              }))\n\n              model.add(tf.layers.dense({\n                units: 2,\n                kernelInitializer: \"VarianceScaling\",\n                activation: \"softmax\"\n              }))\n\n              return resolve(model)\n            })\n          }\n\n          window.trainCnn = function (model, trainingSet) {\n            printMessage(\"Summary: \")\n            model.summary()\n\n            return new Promise(function (resolve, reject) {\n              try {\n                model.compile({\n                  optimizer: tf.train.adam(),\n                  loss: \"categoricalCrossentropy\",\n                  metrics: [\"accuracy\"]\n                })\n\n                model.fit(trainingSet.input, trainingSet.output, {\n                  epochs: window.epochs,\n                  shuffle: true,\n                  callbacks: tfvis.show.fitCallbacks({\n                    name: \"Model Training\", tab: \"Model\", styles: { height: \"500px\" }\n                  }, [\"loss\", \"val_loss\", \"acc\", \"val_acc\"])\n                }).then(function (result) {\n                  printMessage(\"Loss after last Epoch (\" + result.epoch.length + \") is: \" + result.history.loss[result.epoch.length-1])\n                  resolve(model)\n                })\n              } catch (ex) {\n                reject(ex)\n              }\n            })\n          }\n\n          window.doCnn = function () {\n            window.buildCnn().then(function (model) {\n              var trainingSet = {\n                input: tf.tensor4d([0, 0, 1, 1, 1, 0, 0, 1], [4, 2, 1, 1]),\n                output: tf.tensor2d([0, 1, 0, 1, 1, 0, 1, 0], [4, 2])\n              }\n\n              window.trainCnn(model, trainingSet).then(function (model) {\n                printMessage(model.predict(trainingSet.input))\n              })\n            })\n          }\n\n          window.doCnn()\n        }\n        script2.onerror = function () {}\n\t      script2.async = true\n\t      script2.src = tfvisjs\n      }\n      script1.onerror = function () {}\n      script1.async = true\n      script1.src = tfjs\n    } else {\n      window.doCnn()\n    }\n  },\n  function (context) { // Deinit()\n    delete window.epochs\n  },\n  function (context) { // OnTick()\n  }\n)\n"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/usage.txt",
    "content": "This is the most interesting part that we would like to present to our users.\n\nTensorflow is an AI framework that was utilized to construct the Go bot, AlphaGo. Typically, Market patterns identification is accomplished through neural networks. We can use this Tensorflow plugin to simulate this process, replicating the way our eyes detect market patterns.\n\nJust like the EAs that are included in NeuralNetwork folder, EAs that are based on this plugin must be separated into two parts. One piece for training the model, known as the convolutional neural network, and another is utilized to operate the model that has been trained by the previous element.\n"
  },
  {
    "path": "EA/Plugin-for-TradingView/plugin_for_tradingview.js",
    "content": "registerEA(\n  \"tradingview_widget\",\n  \"A plugin to embed the widget of TradingView(v1.0)\",\n  [],\n  function (context) { // Init()\n    // Disclaimer: we are not affiliated with the widget providers or the API providers.\n    if (getLayoutId() != 3) {\n\t\t\tchangeLayout(3)\n\t\t}\n\n    window.chartIds = getLayout(2)\n\t\tfor (var i in window.chartIds) {\n\t\t\tmoveLayout(window.chartIds[i], 1)\n\t\t}\n    embedHtml('<div class=\"tradingview-widget-container\"><div id=\"tradingview_8ac01\"></div><div class=\"tradingview-widget-copyright\"><a href=\"https://www.tradingview.com/symbols/NASDAQ-AAPL/\" rel=\"noopener\" target=\"_blank\"></div>', 2)\n\n    var script = document.createElement(\"script\")\n    document.body.appendChild(script)\n    script.onload = function () {\n      new TradingView.widget(\n        {\n          \"width\": \"100%\",\n          \"height\": \"105%\",\n          \"symbol\": \"NASDAQ:AAPL\",\n          \"interval\": \"D\",\n          \"timezone\": \"Etc/UTC\",\n          \"theme\": \"light\",\n          \"style\": \"1\",\n          \"locale\": \"en\",\n          \"toolbar_bg\": \"#f1f3f6\",\n          \"enable_publishing\": false,\n          \"allow_symbol_change\": true,\n          \"container_id\": \"tradingview_8ac01\"\n        }\n      )\n    }\n    script.onerror = function () {\n      alert(\"Failed to load required libs. Please re-run this EA again.\")\n    }\n    script.async = true\n    script.src = \"https://s3.tradingview.com/tv.js\"\n  },\n  function (context) { // Deinit()\n    embedHtml(\"\", 2)\n    for (var i in window.chartIds) {\n\t\t\tmoveLayout(window.chartIds[i], 2)\n\t\t}\n  },\n  function (context) { // OnTick()\n  }\n)\n"
  },
  {
    "path": "EA/Plugin-for-TrailingStop/plugin_for_trailingstop.js",
    "content": "registerEA(\n\"plugin_for_trailingstop\",\n\"A plugin to manage trailing stop(v1.02)\",\n[{\n\tname: \"symbolName\", // this parameter to set the symbols that you want to have trailing stops applied\n\tvalue: \"EUR/USD\", // e.g. EUR/USD,GBP/USD\n\trequired: true,\n\ttype: \"String\",\n\trange: null,\n\tstep: null\n}, {\n\tname: \"trailingStop\",\n\tvalue: 20,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [1, 10000],\n\tstep: null\n}],\nfunction (context) { // Init()\n\tcontext.openTrades = []\n\tvar account = getAccount(context, 0)\n\tvar brokerName = getBrokerNameOfAccount(account)\n\tvar accountId = getAccountIdOfAccount(account)\n\tvar symbolNames = getEAParameter(context, \"symbolName\").split(\",\")\n\n\tfor (var i in symbolNames) {\n\t\tvar symbolName = symbolNames[i]\n\t\tgetQuotes(context, brokerName, accountId, symbolName)\n\t}\n},\nfunction (context) { // Deinit()\n},\nfunction (context) { // OnTick()\n  var trailingStop = getEAParameter(context, \"trailingStop\")\n\n\tvar tick = getCurrentTick(context)\n\tvar cnt = context.openTrades.length\n\n\tfor (var i = cnt - 1; i >= 0; i--) {\n\t\tvar openTrade = context.openTrades[i]\n\n\t\tif (openTrade.brokerName == tick.brokerName && openTrade.accountId == tick.accountId && openTrade.symbolName == tick.symbolName) {\n\t\t\tvar toFixed = getSymbolInfo(openTrade.brokerName, openTrade.accountId, openTrade.symbolName).toFixed / 10\n\n\t\t\tif (openTrade.orderType == \"BUY\") {\n\t\t\t\tif (tick.bid - Math.max(openTrade.stopLoss, openTrade.price) > trailingStop / toFixed) {\n\t\t\t\t\topenTrade.stopLoss = tick.bid - trailingStop / toFixed\n\t\t\t\t} else if (tick.bid <= openTrade.stopLoss) {\n\t\t\t\t\tcloseTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0)\n\t\t\t\t\tcontext.openTrades.splice(i, 1)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Math.min(openTrade.stopLoss, openTrade.price) - tick.ask > trailingStop / toFixed) {\n\t\t\t\t\topenTrade.stopLoss = tick.ask + trailingStop / toFixed\n\t\t\t\t} else if (tick.ask >= openTrade.stopLoss) {\n\t\t\t\t\tcloseTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0)\n\t\t\t\t\tcontext.openTrades.splice(i, 1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n},\nfunction (context) { // OnTransaction()\n\tvar trailingStop = getEAParameter(context, \"trailingStop\")\n  var transType = getLatestTransType(context)\n\n  if (transType == \"Open Trade\") {\n\t\tvar trans = getLatestTrans(context)\n\t\tvar transTradeId = getTradeId(trans)\n\t\tvar transBrokerName = getBrokerName(trans)\n\t  var transAccountId = getAccountId(trans)\n\t  var transSymbolName = getSymbolName(trans)\n\t  var transOrderType = getOrderType(trans).split(\" \")[0]\n\t\tvar transPrice = getOpenPrice(trans)\n\t\tvar toFixed = getSymbolInfo(transBrokerName, transAccountId, transSymbolName).toFixed / 10\n\n\t\tcontext.openTrades.push({\n\t\t\ttradeId: transTradeId,\n\t\t\tbrokerName: transBrokerName,\n\t\t\taccountId: transAccountId,\n\t\t\tsymbolName: transSymbolName,\n\t\t\torderType: transOrderType,\n\t\t\tprice: transPrice,\n\t\t\tstopLoss: (transOrderType == \"BUY\" ? (transPrice - trailingStop / toFixed) : (transPrice + trailingStop / toFixed))\n\t\t})\n  }\n})\n"
  },
  {
    "path": "EA/Plugin-for-XCoinCH/market_maker_bot.js",
    "content": "registerEA(\n  \"market_maker_bot\",\n  \"Automated market maker(v1.0)\",\n  [{\n  \tname: \"basePlatform\",\n  \tvalue: \"eth\",\n  \trequired: true,\n  \ttype: \"String\",\n  \trange: null,\n  \tstep: null\n  }, {\n  \tname: \"baseCryptocurrency\",\n  \tvalue: \"WEENUS\",\n  \trequired: true,\n  \ttype: \"String\",\n  \trange: null,\n  \tstep: null\n  }, {\n  \tname: \"termPlatform\",\n  \tvalue: \"eos\",\n  \trequired: true,\n  \ttype: \"String\",\n  \trange: null,\n  \tstep: null\n  }, {\n  \tname: \"termCryptocurrency\",\n  \tvalue: \"JUNGLE\",\n  \trequired: true,\n  \ttype: \"String\",\n  \trange: null,\n  \tstep: null\n  }], // parameters\n  function (context) { // Init()\n    window.ethAccount = \"YOUR ETHEREUM ADDRESS\"\n    window.ethPrivateKey = \"YOUR ETHEREUM PRIVATE KEY\"\n    window.eosAccount = \"YOUR EOSIO ACCOUNT\"\n    window.eosPrivateKey = \"YOUR EOSIO PRIVATE KEY\"\n\n    window.mailAddr = \"test@xcoinch.com\"\n\n\t\twindow.basePlatform = getEAParameter(context, \"basePlatform\").toLowerCase()\n    window.baseCryptocurrency = getEAParameter(context, \"baseCryptocurrency\").toUpperCase()\n    window.termPlatform = getEAParameter(context, \"termPlatform\").toLowerCase()\n    window.termCryptocurrency = getEAParameter(context, \"termCryptocurrency\").toUpperCase()\n\n    window.queue = []\n    window.tradeInterval = 300000\n    window.oneHour = 3600000\n    window.contactId = \"0\"\n    window.dexConnected = false\n    window.testNet = 1\n    window.serverUrl = \"https://lmk2m8udud.execute-api.eu-central-1.amazonaws.com/v1\"\n    window.ethReceiptUrl = null\n    var ethRpcUrl = \"https://rinkeby.infura.io/v3/467e60929f46412f8ea456d04ab491da\"\n    var ethWeb3 = \"https://www.fintechee.com/js/wallet/web3.min.js\"\n    var eosRpcUrl = \"https://jungle3.cryptolions.io\"\n    var eosJsSig = \"https://www.fintechee.com/js/wallet/eosjs-jssig.min.js\"\n    var eosRpc = \"https://www.fintechee.com/js/wallet/eosjs-jsonrpc.min.js\"\n    var eosApi = \"https://www.fintechee.com/js/wallet/eosjs-api.min.js\"\n\n    if (window.basePlatform != \"eth\" && window.basePlatform != \"eos\") {\n      printErrorMessage(\"The base platforms is not correct.\")\n      return\n    }\n\n    if (window.termPlatform != \"eth\" && window.termPlatform != \"eos\") {\n      printErrorMessage(\"The term platforms is not correct.\")\n      return\n    }\n\n    if (window.ethAccount == null || window.ethAccount == \"\" || window.eosAccount == null || window.eosAccount == \"\") {\n      printErrorMessage(\"The account should not be empty.\")\n      return\n    }\n\n    if (window.ethPrivateKey == null || window.ethPrivateKey == \"\" || window.eosPrivateKey == null || window.eosPrivateKey == \"\") {\n      printErrorMessage(\"The private key should not be empty.\")\n      return\n    }\n\n    var tags = document.getElementsByTagName(\"script\")\n    for (var i = tags.length - 1; i >= 0; i--) {\n      if (tags[i] && tags[i].getAttribute(\"src\") != null &&\n        (tags[i].getAttribute(\"src\") == eosJsSig || tags[i].getAttribute(\"src\") == eosRpc || tags[i].getAttribute(\"src\") == eosApi || tags[i].getAttribute(\"src\") == ethWeb3)) {\n        tags[i].parentNode.removeChild(tags[i])\n      }\n    }\n\n    var script0 = document.createElement(\"script\")\n    document.body.appendChild(script0)\n    script0.onload = function () {\n      window.eth_api = new Web3(ethRpcUrl)\n      window.dexEthLibsLoaded = true\n    }\n    script0.onerror = function () {}\n    script0.async = true\n    script0.src = ethWeb3\n\n    var script1 = document.createElement(\"script\")\n    document.body.appendChild(script1)\n    script1.onload = function () {\n      var script2 = document.createElement(\"script\")\n      document.body.appendChild(script2)\n      script2.onload = function () {\n        var script3 = document.createElement(\"script\")\n        document.body.appendChild(script3)\n        script3.onload = function () {\n          window.eosjs_jsonrpc = eosjs_jsonrpc\n          window.eos_rpc = new eosjs_jsonrpc.JsonRpc(eosRpcUrl)\n          var eos_signatureProvider = new eosjs_jssig.JsSignatureProvider([eosPrivateKey])\n          window.eos_api = new eosjs_api.Api({rpc: window.eos_rpc, signatureProvider: eos_signatureProvider})\n          window.dexEosLibsLoaded = true\n        }\n        script3.onerror = function () {}\n        script3.async = true\n        script3.src = eosJsSig\n      }\n      script2.onerror = function () {}\n      script2.async = true\n      script2.src = eosRpc\n    }\n    script1.onerror = function () {}\n    script1.async = true\n    script1.src = eosApi\n\n    window.notifier = {\n      notificationTimeout: 10000,\n      notifyTransactionForModification: function (platform, modificationFeeTrxId, modificationFeeBlockNum, callback) {\n        var data = JSON.stringify({\n          platform: platform,\n          modificationFeeTrxId: modificationFeeTrxId,\n          modificationFeeBlockNum: modificationFeeBlockNum,\n          contactId: window.contactId\n        })\n\n        $.ajax({\n          type: \"POST\",\n          url: window.serverUrl + \"/notifications/modification\",\n          contentType: \"application/json; charset=utf-8\",\n          dataType: \"json\",\n          data: JSON.stringify({\n            type: \"M\",\n            data: data\n          }),\n          success: function (data) {\n            if (typeof data.res == \"string\" && data.res == \"success\") {\n              callback()\n            }\n          },\n          error: function (request, status, error) {\n            setTimeout(function () {\n              window.notifier.notifyTransactionForModification(platform, modificationFeeTrxId, modificationFeeBlockNum, callback)\n            }, window.notifier.notificationTimeout)\n          }\n        })\n      },\n      notifyTransactionForCancellation: function (platform, cancellationFeeTrxId, cancellationFeeBlockNum, callback) {\n        var data = JSON.stringify({\n          platform: platform,\n          cancellationFeeTrxId: cancellationFeeTrxId,\n          cancellationFeeBlockNum: cancellationFeeBlockNum,\n          contactId: window.contactId\n        })\n\n        $.ajax({\n          type: \"POST\",\n          url: window.serverUrl + \"/notifications/cancellation\",\n          contentType: \"application/json; charset=utf-8\",\n          dataType: \"json\",\n          data: JSON.stringify({\n            type: \"C\",\n            data: data\n          }),\n          success: function (data) {\n            if (typeof data.res == \"string\" && data.res == \"success\") {\n              callback()\n            }\n          },\n          error: function (request, status, error) {\n            setTimeout(function () {\n              window.notifier.notifyTransactionForCancellation(platform, cancellationFeeTrxId, cancellationFeeBlockNum, callback)\n            }, window.notifier.notificationTimeout)\n          }\n        })\n      },\n      notifyTransaction: function (mailAddress, platform, feeTrxId, feeBlockNum, trxId, blockNum, callback) {\n        var data = JSON.stringify({\n          mailAddr: mailAddress,\n          platform: platform,\n          feeTrxId: feeTrxId,\n          feeBlockNum: feeBlockNum,\n          trxId: trxId,\n          blockNum: blockNum,\n          contactId: window.contactId\n        })\n\n        $.ajax({\n          type: \"POST\",\n          url: window.serverUrl + \"/notifications/transaction\",\n          contentType: \"application/json; charset=utf-8\",\n          dataType: \"json\",\n          data: JSON.stringify({\n            type: \"O\",\n            data: data\n          }),\n          success: function (data) {\n            if (typeof data.res == \"string\" && data.res == \"success\") {\n              callback()\n            }\n          },\n          error: function (request, status, error) {\n            setTimeout(function () {\n              window.notifier.notifyTransaction(mailAddress, platform, feeTrxId, feeBlockNum, trxId, blockNum, callback)\n            }, window.notifier.notificationTimeout)\n          }\n        })\n      }\n    }\n\n    window.orderStore = {\n      storeAddedOrder: function (order) {\n        var dexOrders = []\n        if (typeof localStorage.dexOrders != \"undefined\") {\n          dexOrders = JSON.parse(localStorage.dexOrders)\n        }\n        dexOrders.push(order)\n        localStorage.dexOrders = JSON.stringify(dexOrders)\n      },\n      storeUpdatedOrder: function (order) {\n        if (typeof localStorage.dexOrders != \"undefined\") {\n          var dexOrders = JSON.parse(localStorage.dexOrders)\n\n          for (var i in dexOrders) {\n            if (isNaN(i)) continue\n\n            var oldOrder = dexOrders[i]\n\n            if (oldOrder.trxId == order.oldTrxId && oldOrder.blockNum == order.oldBlockNum) {\n              oldOrder.price = order.price\n              oldOrder.basePlatform = order.basePlatform\n              oldOrder.baseCryptocurrency = order.baseCryptocurrency\n              oldOrder.baseAmount = order.baseAmount\n              oldOrder.accuBaseAmountTraded = order.accuBaseAmountTraded\n              var currentAllowedTimesToTransfer = oldOrder.currentAllowedTimesToTransfer + order.currentAllowedTimesToTransfer\n              oldOrder.currentAllowedTimesToTransfer = currentAllowedTimesToTransfer\n              order.currentAllowedTimesToTransfer = currentAllowedTimesToTransfer\n              oldOrder.expiration = order.expiration\n              oldOrder.baseAccount = order.baseAccount\n              oldOrder.modificationFeeTrxId = order.modificationFeeTrxId\n              oldOrder.modificationFeeBlockNum = order.modificationFeeBlockNum\n              oldOrder.state = order.state\n\n              localStorage.dexOrders = JSON.stringify(dexOrders)\n\n              break\n            }\n          }\n        }\n      },\n      storeRemovedOrder: function (oldTrxId, oldBlockNum, cancellationFeeTrxId, cancellationFeeBlockNum) {\n        var currentAllowedTimesToTransfer = null\n\n        if (typeof localStorage.dexOrders != \"undefined\") {\n          var dexOrders = JSON.parse(localStorage.dexOrders)\n\n          for (var i in dexOrders) {\n            if (isNaN(i)) continue\n\n            var oldOrder = dexOrders[i]\n\n            if (oldOrder.trxId == oldTrxId && oldOrder.blockNum == oldBlockNum) {\n              oldOrder.cancellationFeeTrxId = cancellationFeeTrxId\n              oldOrder.cancellationFeeBlockNum = cancellationFeeBlockNum\n              oldOrder.currentAllowedTimesToTransfer--\n              currentAllowedTimesToTransfer = oldOrder.currentAllowedTimesToTransfer\n              oldOrder.state = \"PC\"\n              localStorage.dexOrders = JSON.stringify(dexOrders)\n\n              break\n            }\n          }\n        }\n\n        return currentAllowedTimesToTransfer\n      }\n    }\n\n    window.platforms = []\n\n    window.platforms[\"eth\"] = {}\n    window.platforms[\"eth\"].checkBlockInterval = 20000\n    window.platforms[\"eth\"].cryptocurrencies = []\n    window.platforms[\"eth\"].latestContext = null\n    window.platforms[\"eth\"].notifications = []\n\n    window.platforms[\"eth\"].getSmartContract = function (cryptocurrency) {\n      if (typeof this.cryptocurrencies[cryptocurrency] != \"undefined\") {\n        return this.cryptocurrencies[cryptocurrency].smartContract.toLowerCase()\n      } else if (cryptocurrency == \"ETH\") {\n        return \"ETH\"\n      }\n\n      return null\n    }\n\n    window.platforms[\"eth\"].getActionName = function (cryptocurrency) {\n      var actionName = null\n\n      if (typeof this.cryptocurrencies[cryptocurrency] != \"undefined\") {\n        actionName = this.cryptocurrencies[cryptocurrency].actionName\n      } else if (cryptocurrency == \"ETH\") {\n        actionName = []\n      }\n\n      return actionName\n    }\n\n    window.platforms[\"eth\"].getPlatformCurrency = function () {\n      return \"ETH\"\n    }\n\n    window.platforms[\"eth\"].getFeeAmountRequired = function () {\n      return this.feeAmountRequired * 2.0\n    }\n\n    window.platforms[\"eth\"].getFeeAmountRequiredForOperation = function () {\n      return this.feeAmountRequired\n    }\n\n    window.platforms[\"eth\"].makeAmountAccurate = function (currency, amount) {\n      if (typeof this.cryptocurrencies[currency] != \"undefined\") {\n        if (this.cryptocurrencies[currency].accuracy > 0) {\n          return Math.round(amount * Math.pow(10, this.cryptocurrencies[currency].accuracy)) + \"\"\n        } else if (this.cryptocurrencies[currency].accuracy < 0) {\n          return amount.toFixed(Math.abs(this.cryptocurrencies[currency].accuracy))\n        } else {\n          return Math.round(amount) + \"\"\n        }\n      } else if (currency == \"ETH\") {\n        return Math.round(amount * 1e18) + \"\"\n      }\n\n      return null\n    }\n\n    window.platforms[\"eth\"].getNonce = function (address) {\n      return new Promise((resolve, reject) => {\n        window.eth_api.eth.getTransactionCount(address, (err, data) => {\n          if(err)\n            reject(err)\n          else\n            resolve(parseInt(data))\n        })\n      })\n    }\n\n    window.platforms[\"eth\"].getGasPrice = function () {\n      return new Promise((resolve, reject) => {\n        window.eth_api.eth.getGasPrice((err, data) => {\n          if(err)\n            reject(err)\n          else\n            resolve(data)\n        })\n      })\n    }\n\n    window.platforms[\"eth\"].estimateGas = function (txOptions) {\n      return new Promise((resolve, reject) => {\n        window.eth_api.eth.estimateGas(txOptions, (err, data) => {\n          if(err)\n            reject(err)\n          else\n            resolve(data)\n        })\n      })\n    }\n\n    window.platforms[\"eth\"].generateNonce = function () {\n      return Math.floor(Math.random() * 10000000000) + \"\"\n    }\n\n    window.platforms[\"eth\"].checkBlock = function (context, callback) {\n      $.ajax({\n        type: \"GET\",\n        url: window.ethReceiptUrl + window.ethAccount,\n        contentType: \"application/json; charset=utf-8\",\n        success: function (data) {\n          (async () => {\n            if (typeof data.result != \"undefined\") {\n              var result = data.result\n\n              if (Array.isArray(result)) {\n                for (var i in result) {\n                  if (isNaN(i)) continue\n\n                  var receipt = result[i]\n\n                  if (typeof receipt.from != \"undefined\" && receipt.from.toLowerCase() == window.ethAccount.toLowerCase() && receipt.to.toLowerCase() == context.that.exchange.toLowerCase()) {\n                    var memo = window.eth_api.utils.toUtf8(result[i].input).split(\":\")\n                    var nonce = memo[memo.length - 1]\n\n                    if (context.nonce == nonce) {\n\n                      if (receipt.blockNumber) {\n                        context.feeTrxId = receipt.hash\n                        context.feeBlockNum = parseInt(receipt.blockNumber)\n                      }\n\n                      break\n                    }\n                  }\n                }\n\n                if (!context.feeBlockNum) {\n                  await new Promise(resolve => setTimeout(resolve, context.that.checkBlockInterval))\n\n                  context.that.checkBlock(context, callback)\n                } else {\n                  callback(context)\n                }\n              }\n            }\n          })()\n        },\n        error: function (request, status, error) {\n          setTimeout(function () {\n            context.that.checkBlock(context, callback)\n          }, context.that.checkBlockInterval)\n        }\n      })\n    }\n\n    window.platforms[\"eth\"].notifyOrderbook = function () {\n      for (var i in window.platforms[\"eth\"].notifications) {\n        if (isNaN(i)) continue\n\n        var notification = window.platforms[\"eth\"].notifications[i]\n        var context = notification.context\n\n        if (!notification.done && typeof context != \"undefined\") {\n          if (context.mode == \"sendOrder\") {\n            context.that.checkBlock(context, function (ctx) {\n              var notification2 = window.platforms[\"eth\"].notifications[ctx.nonce]\n\n              if (!notification2.done) {\n                window.notifier.notifyTransaction(ctx.mailAddr, \"eth\", ctx.feeTrxId, ctx.feeBlockNum, ctx.trxId, ctx.blockNum, function () {\n                  printMessage(\"Transaction to pay for the fee is pushed! Pending to list on the orderbook.\")\n\n                  var order = {\n                    price: ctx.price,\n                    basePlatform: ctx.basePlatform,\n                    baseCryptocurrency: ctx.baseCryptocurrency,\n                    baseAmount: ctx.baseAmountTmp,\n                    accuBaseAmountTraded: 0,\n                    termPlatform: ctx.termPlatform,\n                    termCryptocurrency: ctx.termCryptocurrency,\n                    termAmount: ctx.termAmountTmp,\n                    termCurrentAmount: ctx.termAmountTmp,\n                    currentAllowedTimesToTransfer: ctx.currentAllowedTimesToTransfer,\n                    expiration: ctx.expiration,\n                    baseAccount: ctx.baseAccount,\n                    trxId: ctx.trxId,\n                    blockNum: ctx.blockNum,\n                    feeTrxId: ctx.feeTrxId,\n                    feeBlockNum: ctx.feeBlockNum,\n                    modificationFeeTrxId: null,\n                    modificationFeeBlockNum: null,\n                    cancellationFeeTrxId: null,\n                    cancellationFeeBlockNum: null,\n                    mailAddr: ctx.mailAddr,\n                    state: \"PO\"\n                  }\n\n                  window.orderStore.storeAddedOrder(order)\n                })\n\n                notification2.done = true\n              }\n            })\n          } else if (context.mode == \"modifyOrder\") {\n            context.that.checkBlock(context, function (ctx) {\n              var notification2 = window.platforms[\"eth\"].notifications[ctx.nonce]\n\n              if (!notification2.done) {\n                window.notifier.notifyTransactionForModification(\"eth\", ctx.feeTrxId, ctx.feeBlockNum, function () {\n                  printMessage(\"Transaction to modify the order is pushed! Pending to update on the orderbook.\")\n\n                  var order = {\n                    price: ctx.price,\n                    basePlatform: ctx.basePlatform,\n                    baseCryptocurrency: ctx.baseCryptocurrency,\n                    baseAmount: ctx.baseAmountTmp,\n                    accuBaseAmountTraded: 0,\n                    currentAllowedTimesToTransfer: ctx.currentAllowedTimesToTransfer,\n                    expiration: ctx.expiration,\n                    baseAccount: ctx.baseAccount,\n                    oldTrxId: ctx.oldTrxId,\n                    oldBlockNum: ctx.oldBlockNum,\n                    modificationFeeTrxId: ctx.feeTrxId,\n                    modificationFeeBlockNum: ctx.feeBlockNum,\n                    state: \"PU\"\n                  }\n\n                  window.orderStore.storeUpdatedOrder(order)\n                })\n\n                notification2.done = true\n              }\n            })\n          } else if (context.mode == \"cancelOrder\") {\n            context.that.checkBlock(context, function (ctx) {\n              var notification2 = window.platforms[\"eth\"].notifications[ctx.nonce]\n\n              if (!notification2.done) {\n                window.notifier.notifyTransactionForCancellation(\"eth\", ctx.feeTrxId, ctx.feeBlockNum, function () {\n                  printMessage(\"Transaction to cancel the order is pushed! Pending to remove the order from the orderbook.\")\n\n                  window.orderStore.storeRemovedOrder(ctx.oldTrxId, ctx.oldBlockNum, ctx.feeTrxId, ctx.feeBlockNum)\n                })\n\n                notification2.done = true\n              }\n            })\n          }\n        }\n      }\n    }\n\n    window.platforms[\"eth\"].sendOrder = async function (mailAddr, smartContract, actionName, termAmount, termCryptocurrency, feeAmount, platformCurrency, memo,\n                                                        basePlatform, baseAccount, baseCryptocurrency, baseAmount, termPlatform, price, currentAllowedTimesToTransfer, expiration,\n                                                        baseAmountTmp, termAmountTmp) {\n      if (!window.dexEthLibsLoaded) return\n\n      var context = {\n        mode: \"sendOrder\",\n        that: this,\n        mailAddr: mailAddr,\n        smartContract: smartContract,\n        actionName: actionName,\n        termAmount: termAmount,\n        termAmountTmp: termAmountTmp,\n        termCryptocurrency: termCryptocurrency,\n        feeAmount: feeAmount,\n        platformCurrency: platformCurrency,\n        memo: \"O:\" + memo,\n        trxId: null,\n        blockNum: null,\n        feeTrxId: null,\n        feeBlockNum: null,\n        basePlatform: basePlatform,\n        baseAccount: baseAccount,\n        baseCryptocurrency: baseCryptocurrency,\n        baseAmount: baseAmount,\n        baseAmountTmp: baseAmountTmp,\n        termPlatform: termPlatform,\n        price: price,\n        currentAllowedTimesToTransfer: currentAllowedTimesToTransfer,\n        expiration: expiration\n      }\n\n      if (context.smartContract == \"ETH\") {\n        var txParams = {\n          to: this.exchange,\n          value: termAmount,\n          gasPrice: await getGasPrice(),\n          nonce: await this.getNonce(window.ethAccount)\n        }\n\n        var gasLimit = await this.estimateGas(txParams)\n        txParams.gas = Math.round(gasLimit * 1.5)\n\n        const signed = await window.eth_api.eth.accounts.signTransaction(txParams, window.ethPrivateKey)\n\n        window.eth_api.eth.sendSignedTransaction(signed.rawTransaction)\n        .then(async function (receipt) {\n          var context2 = context\n          context.trxId = receipt.transactionHash\n          context.blockNum = receipt.blockNumber\n\n          printMessage(\"Transaction to transfer the collateral is pushed!\")\n\n          var funcTmp = async function () {\n            var context3 = context2\n\n            while (!context2.blockNum) {\n              await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval))\n\n              const result = await window.eth_api.eth.getTransaction(context2.trxId)\n\n              if (result.blockNumber) {\n                context2.blockNum = result.blockNumber\n                break\n              }\n            }\n\n            var nonce = context2.that.generateNonce()\n            context2.nonce = nonce\n            context2.that.notifications[nonce] = {\n              context: context2,\n              done: false\n            }\n\n            var feeTxParams = {\n              to: context2.that.feeRecipient,\n              value: context2.feeAmount,\n              gasPrice: await context2.that.getGasPrice(),\n              nonce: await context2.that.getNonce(window.ethAccount),\n              data: window.eth_api.utils.toHex(context2.memo + \":\" + nonce)\n            }\n\n            var feeGasLimit = await context2.that.estimateGas(feeTxParams)\n            feeTxParams.gas = Math.round(feeGasLimit * 1.5)\n\n            const feeSigned = await window.eth_api.eth.accounts.signTransaction(feeTxParams, window.ethPrivateKey)\n\n            window.eth_api.eth.sendSignedTransaction(feeSigned.rawTransaction)\n            .then(receipt => {})\n            .catch(err => {})\n\n            await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval))\n\n            context2.that.notifyOrderbook()\n          }\n\n          await funcTmp()\n        }).catch(err => {\n          printErrorMessage(\"Error while sending transaction(ETH platform): \", err)\n        })\n      } else {\n        var contract = new window.eth_api.eth.Contract(actionName, smartContract)\n        var extraData = await contract.methods.transfer(this.exchange, termAmount)\n\n        const signed = await window.eth_api.eth.accounts.signTransaction({\n          to: smartContract,\n          value: \"0\",\n          data: extraData.encodeABI(),\n          gasPrice: await this.getGasPrice(),\n          gas: Math.round((await extraData.estimateGas({from: window.ethAccount})) * 1.5),\n          nonce: await this.getNonce(window.ethAccount)\n        }, window.ethPrivateKey)\n\n        window.eth_api.eth.sendSignedTransaction(signed.rawTransaction)\n        .then(async function (receipt) {\n          var context2 = context\n          context.trxId = receipt.transactionHash\n          context.blockNum = receipt.blockNumber\n\n          printMessage(\"Transaction to transfer the collateral is pushed!\")\n\n          var funcTmp = async function () {\n            var context3 = context2\n\n            while (!context2.blockNum) {\n              await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval))\n\n              const result = await window.eth_api.eth.getTransaction(context2.trxId)\n\n              if (result.blockNumber) {\n                context2.blockNum = result.blockNumber\n                break\n              }\n            }\n\n            var nonce = context2.that.generateNonce()\n            context2.nonce = nonce\n            context2.that.notifications[nonce] = {\n              context: context2,\n              done: false\n            }\n\n            var feeTxParams = {\n              to: context2.that.feeRecipient,\n              value: context2.feeAmount,\n              gasPrice: await context2.that.getGasPrice(),\n              nonce: await context2.that.getNonce(window.ethAccount),\n              data: window.eth_api.utils.toHex(context2.memo + \":\" + nonce)\n            }\n\n            var feeGasLimit = await context2.that.estimateGas(feeTxParams)\n            feeTxParams.gas = Math.round(feeGasLimit * 1.5)\n\n            const feeSigned = await window.eth_api.eth.accounts.signTransaction(feeTxParams, window.ethPrivateKey)\n\n            window.eth_api.eth.sendSignedTransaction(feeSigned.rawTransaction)\n            .then(receipt => {})\n            .catch(err => {})\n\n            await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval))\n\n            context2.that.notifyOrderbook()\n          }\n\n          await funcTmp()\n        })\n        .catch(err => {\n          printErrorMessage(\"Error while sending transaction(ETH platform): \", err)\n        })\n      }\n    }\n\n    window.platforms[\"eth\"].modifyOrder = async function (feeAmount, platformCurrency, memo,\n        oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmount, price, currentAllowedTimesToTransfer, expiration, baseAmountTmp) {\n      if (!window.dexEthLibsLoaded) return\n\n      var context = {\n        mode: \"modifyOrder\",\n        that: this,\n        feeAmount: feeAmount,\n        platformCurrency: platformCurrency,\n        memo: \"U:\" + memo,\n        feeTrxId: null,\n        feeBlockNum: null,\n        oldTrxId: oldTrxId,\n        oldBlockNum: oldBlockNum,\n        basePlatform: basePlatform,\n        baseAccount: baseAccount,\n        baseCryptocurrency: baseCryptocurrency,\n        baseAmount: baseAmount,\n        baseAmountTmp: baseAmountTmp,\n        price: price,\n        currentAllowedTimesToTransfer: currentAllowedTimesToTransfer,\n        expiration: expiration\n      }\n\n      var nonce = this.generateNonce()\n      context.nonce = nonce\n      this.notifications[nonce] = {\n        context: context,\n        done: false\n      }\n\n      var txParams = {\n        to: this.feeRecipient,\n        value: feeAmount,\n        gasPrice: await this.getGasPrice(),\n        nonce: await this.getNonce(window.ethAccount),\n        data: window.eth_api.utils.toHex(context.memo + \":\" + nonce)\n      }\n\n      var gasLimit = await this.estimateGas(txParams)\n      txParams.gas = Math.round(gasLimit * 1.5)\n\n      const signed = await window.eth_api.eth.accounts.signTransaction(txParams, window.ethPrivateKey)\n\n      window.eth_api.eth.sendSignedTransaction(signed.rawTransaction)\n      .then(receipt => {})\n      .catch(err => {})\n\n      await new Promise(resolve => setTimeout(resolve, this.checkBlockInterval))\n\n      this.notifyOrderbook()\n    }\n\n    window.platforms[\"eth\"].cancelOrder = async function (feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum) {\n      if (!window.dexEthLibsLoaded) return\n\n      var context = {\n        mode: \"cancelOrder\",\n        that: this,\n        feeAmount: feeAmount,\n        platformCurrency: platformCurrency,\n        memo: \"C:\" + memo,\n        feeTrxId: null,\n        feeBlockNum: null,\n        oldTrxId: oldTrxId,\n        oldBlockNum: oldBlockNum\n      }\n\n      var nonce = this.generateNonce()\n      context.nonce = nonce\n      this.notifications[nonce] = {\n        context: context,\n        done: false\n      }\n\n      var txParams = {\n        to: this.feeRecipient,\n        value: feeAmount,\n        gasPrice: await this.getGasPrice(),\n        nonce: await this.getNonce(window.ethAccount),\n        data: window.eth_api.utils.toHex(context.memo + \":\" + nonce)\n      }\n\n      var gasLimit = await this.estimateGas(txParams)\n      txParams.gas = Math.round(gasLimit * 1.5)\n\n      const signed = await window.eth_api.eth.accounts.signTransaction(txParams, window.ethPrivateKey)\n\n      window.eth_api.eth.sendSignedTransaction(signed.rawTransaction)\n      .then(receipt => {})\n      .catch(err => {})\n\n      await new Promise(resolve => setTimeout(resolve, this.checkBlockInterval))\n\n      this.notifyOrderbook()\n    }\n\n    window.platforms[\"eos\"] = {}\n    window.platforms[\"eos\"].checkBlockInterval = 3000\n    window.platforms[\"eos\"].cryptocurrencies = []\n\n    window.platforms[\"eos\"].getSmartContract = function (cryptocurrency) {\n      if (typeof this.cryptocurrencies[cryptocurrency] != \"undefined\") {\n        return this.cryptocurrencies[cryptocurrency].smartContract\n      } else if (cryptocurrency == \"EOS\") {\n        return \"eosio.token\"\n      }\n\n      return null\n    }\n\n    window.platforms[\"eos\"].getActionName = function (cryptocurrency) {\n      if (typeof this.cryptocurrencies[cryptocurrency] != \"undefined\") {\n        return this.cryptocurrencies[cryptocurrency].actionName\n      } else if (cryptocurrency == \"EOS\") {\n        return \"transfer\"\n      }\n\n      return null\n    }\n\n    window.platforms[\"eos\"].getPlatformCurrency = function () {\n      return \"EOS\"\n    }\n\n    window.platforms[\"eos\"].getFeeAmountRequired = function () {\n      return this.feeAmountRequired * 2.0\n    }\n\n    window.platforms[\"eos\"].getFeeAmountRequiredForOperation = function () {\n      return this.feeAmountRequired\n    }\n\n    window.platforms[\"eos\"].makeAmountAccurate = function (currency, amount) {\n      if (typeof this.cryptocurrencies[currency] != \"undefined\") {\n        if (this.cryptocurrencies[currency].accuracy < 0) {\n          return amount.toFixed(Math.abs(this.cryptocurrencies[currency].accuracy))\n        } else {\n          return Math.round(amount) + \"\"\n        }\n      } else if (currency == \"EOS\") {\n        return amount.toFixed(4)\n      }\n\n      return null\n    }\n\n    window.platforms[\"eos\"].sendOrder = function (mailAddr, smartContract, actionName, termAmount, termCryptocurrency, feeAmount, platformCurrency, memo,\n                                                  basePlatform, baseAccount, baseCryptocurrency, baseAmount, termPlatform, price, currentAllowedTimesToTransfer, expiration,\n                                                  baseAmountTmp, termAmountTmp) {\n      if (!window.dexEosLibsLoaded) return\n\n      var context = {\n        that: this,\n        mailAddr: mailAddr,\n        smartContract: smartContract,\n        actionName: actionName,\n        termAmount: termAmount,\n        termAmountTmp: termAmountTmp,\n        termCryptocurrency: termCryptocurrency,\n        feeAmount: feeAmount,\n        platformCurrency: platformCurrency,\n        memo: memo,\n        trxId: null,\n        blockNum: null,\n        feeTrxId: null,\n        feeBlockNum: null,\n        basePlatform: basePlatform,\n        baseAccount: baseAccount,\n        baseCryptocurrency: baseCryptocurrency,\n        baseAmount: baseAmount,\n        baseAmountTmp: baseAmountTmp,\n        termPlatform: termPlatform,\n        price: price,\n        currentAllowedTimesToTransfer: currentAllowedTimesToTransfer,\n        expiration: expiration\n      }\n\n      var context2 = context;\n\n      (async () => {\n        try {\n          const result = await window.eos_api.transact({\n            actions: [{\n                account: \"eosio.token\",\n                name: \"transfer\",\n                authorization: [{\n                    actor: window.eosAccount,\n                    permission: \"active\",\n                }],\n                data: {\n                    from: window.eosAccount,\n                    to: context2.that.feeRecipient,\n                    quantity: context2.feeAmount + \" \" + context2.platformCurrency,\n                    memo: \"O:\" + context2.memo\n                }\n            }]\n          }, {\n            blocksBehind: 3,\n            expireSeconds: 30\n          })\n\n          printMessage(\"Transaction to pay for the fee is pushed!\")\n          context2.feeTrxId = result.transaction_id\n          var context3 = context2\n\n          var funcTmp = async function () {\n            while (!context3.feeBlockNum) {\n              await new Promise(resolve => setTimeout(resolve, context3.that.checkBlockInterval))\n\n              const res = await window.eos_rpc.history_get_transaction(context3.feeTrxId)\n              printMessage(\"Fee trx EOS new block number: \" + context3.feeTrxId + \" \" +  + res.block_num)\n\n              if (res != null && typeof res.trx != \"undefined\" && typeof res.trx.receipt != \"undefined\" &&\n                  typeof res.trx.receipt.status == \"string\" && res.trx.receipt.status == \"executed\" &&\n                  typeof res.block_num != \"undefined\" && Number.isInteger(res.block_num)) {\n                context3.feeBlockNum = res.block_num\n                break\n              }\n            }\n          }\n\n          await funcTmp();\n\n          (async () => {\n            try {\n              const result = await window.eos_api.transact({\n                actions: [{\n                    account: context3.smartContract,\n                    name: context3.actionName,\n                    authorization: [{\n                        actor: window.eosAccount,\n                        permission: \"active\",\n                    }],\n                    data: {\n                        from: window.eosAccount,\n                        to: context3.that.exchange,\n                        quantity: context3.termAmount + \" \" + context3.termCryptocurrency,\n                        memo: \"\"\n                    }\n                }]\n              }, {\n                blocksBehind: 3,\n                expireSeconds: 30\n              })\n\n              context3.trxId = result.transaction_id\n              var context0 = context3\n\n              var funcTmp2 = async function () {\n                while (!context0.blockNum) {\n                  await new Promise(resolve => setTimeout(resolve, context0.that.checkBlockInterval))\n\n                  const res = await window.eos_rpc.history_get_transaction(context0.trxId)\n                  printMessage(\"Trx EOS new block number: \" + context0.trxId + \" \" + res.block_num)\n\n                  if (res != null && typeof res.trx != \"undefined\" && typeof res.trx.receipt != \"undefined\" &&\n                      typeof res.trx.receipt.status == \"string\" && res.trx.receipt.status == \"executed\" &&\n                      typeof res.block_num != \"undefined\" && Number.isInteger(res.block_num)) {\n                    context0.blockNum = res.block_num\n                    break\n                  }\n                }\n              }\n\n              await funcTmp2()\n\n              window.notifier.notifyTransaction(context3.mailAddr, \"eos\", context3.feeTrxId, context3.feeBlockNum, context3.trxId, context3.blockNum, function () {\n                printMessage(\"Transaction to transfer the collateral is pushed! Pending to list on the orderbook.\")\n\n                var order = {\n                  price: context0.price,\n                  basePlatform: context0.basePlatform,\n                  baseCryptocurrency: context0.baseCryptocurrency,\n                  baseAmount: context0.baseAmountTmp,\n                  accuBaseAmountTraded: 0,\n                  termPlatform: context0.termPlatform,\n                  termCryptocurrency: context0.termCryptocurrency,\n                  termAmount: context0.termAmountTmp,\n                  termCurrentAmount: context0.termAmountTmp,\n                  currentAllowedTimesToTransfer: context0.currentAllowedTimesToTransfer,\n                  expiration: context0.expiration,\n                  baseAccount: context0.baseAccount,\n                  trxId: context0.trxId,\n                  blockNum: context0.blockNum,\n                  feeTrxId: context0.feeTrxId,\n                  feeBlockNum: context0.feeBlockNum,\n                  modificationFeeTrxId: null,\n                  modificationFeeBlockNum: null,\n                  cancellationFeeTrxId: null,\n                  cancellationFeeBlockNum: null,\n                  mailAddr: context0.mailAddr,\n                  state: \"PO\"\n                }\n\n                window.orderStore.storeAddedOrder(order)\n              })\n            } catch (e) {\n              printErrorMessage(\"Caught exception while sending transaction(EOS platform): \" + e)\n\n              if (e instanceof window.eosjs_jsonrpc.RpcError) {\n                printErrorMessage(JSON.stringify(e.json, null, 2))\n              }\n            }\n          })()\n        } catch (e) {\n          printErrorMessage(\"Caught exception while sending transaction(EOS platform): \" + e)\n\n          if (e instanceof window.eosjs_jsonrpc.RpcError) {\n            printErrorMessage(JSON.stringify(e.json, null, 2))\n          }\n        }\n      })()\n    }\n\n    window.platforms[\"eos\"].modifyOrder = function (feeAmount, platformCurrency, memo,\n        oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmount, price, currentAllowedTimesToTransfer, expiration, baseAmountTmp) {\n      if (!window.dexEosLibsLoaded) return\n\n      var context = {\n        that: this,\n        feeAmount: feeAmount,\n        platformCurrency: platformCurrency,\n        memo: memo,\n        feeTrxId: null,\n        feeBlockNum: null,\n        oldTrxId: oldTrxId,\n        oldBlockNum: oldBlockNum,\n        basePlatform: basePlatform,\n        baseAccount: baseAccount,\n        baseCryptocurrency: baseCryptocurrency,\n        baseAmount: baseAmount,\n        baseAmountTmp: baseAmountTmp,\n        price: price,\n        currentAllowedTimesToTransfer: currentAllowedTimesToTransfer,\n        expiration: expiration\n      }\n\n      var context2 = context;\n\n      (async () => {\n        try {\n          const result = await window.eos_api.transact({\n            actions: [{\n                account: \"eosio.token\",\n                name: \"transfer\",\n                authorization: [{\n                    actor: window.eosAccount,\n                    permission: \"active\",\n                }],\n                data: {\n                    from: window.eosAccount,\n                    to: context2.that.feeRecipient,\n                    quantity: context2.feeAmount + \" \" + context2.platformCurrency,\n                    memo: \"U:\" + context2.memo\n                }\n            }]\n          }, {\n            blocksBehind: 3,\n            expireSeconds: 30\n          })\n\n          printMessage(\"Transaction to modify the order is pushed! Pending to update on the orderbook.\")\n          context2.feeTrxId = result.transaction_id\n          var context3 = context2\n\n          var funcTmp = async function () {\n            while (!context3.feeBlockNum) {\n              await new Promise(resolve => setTimeout(resolve, context3.that.checkBlockInterval))\n\n              const res = await window.eos_rpc.history_get_transaction(context3.feeTrxId)\n\n              if (res != null && typeof res.trx != \"undefined\" && typeof res.trx.receipt != \"undefined\" &&\n                  typeof res.trx.receipt.status == \"string\" && res.trx.receipt.status == \"executed\" &&\n                  typeof res.block_num != \"undefined\" && Number.isInteger(res.block_num)) {\n                context3.feeBlockNum = res.block_num\n                break\n              }\n            }\n          }\n\n          await funcTmp()\n\n          window.notifier.notifyTransactionForModification(\"eos\", context2.feeTrxId, context2.feeBlockNum, function () {\n            var order = {\n              price: context3.price,\n              basePlatform: context3.basePlatform,\n              baseCryptocurrency: context3.baseCryptocurrency,\n              baseAmount: context3.baseAmountTmp,\n              accuBaseAmountTraded: 0,\n              currentAllowedTimesToTransfer: context3.currentAllowedTimesToTransfer,\n              expiration: context3.expiration,\n              baseAccount: context3.baseAccount,\n              oldTrxId: context3.oldTrxId,\n              oldBlockNum: context3.oldBlockNum,\n              modificationFeeTrxId: context3.feeTrxId,\n              modificationFeeBlockNum: context3.feeBlockNum,\n              state: \"PU\"\n            }\n\n            window.orderStore.storeUpdatedOrder(order)\n          })\n        } catch (e) {\n          printErrorMessage(\"Caught exception while sending transaction(EOS platform): \" + e)\n\n          if (e instanceof window.eosjs_jsonrpc.RpcError) {\n            printErrorMessage(JSON.stringify(e.json, null, 2))\n          }\n        }\n      })()\n    }\n\n    window.platforms[\"eos\"].cancelOrder = function (feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum) {\n      if (!window.dexEosLibsLoaded) return\n\n      var context = {\n        that: this,\n        feeAmount: feeAmount,\n        platformCurrency: platformCurrency,\n        memo: memo,\n        feeTrxId: null,\n        feeBlockNum: null,\n        oldTrxId: oldTrxId,\n        oldBlockNum: oldBlockNum\n      }\n\n      var context2 = context;\n\n      (async () => {\n        try {\n          const result = await window.eos_api.transact({\n            actions: [{\n                account: \"eosio.token\",\n                name: \"transfer\",\n                authorization: [{\n                    actor: window.eosAccount,\n                    permission: \"active\",\n                }],\n                data: {\n                    from: window.eosAccount,\n                    to: context2.that.feeRecipient,\n                    quantity: context2.feeAmount + \" \" + context2.platformCurrency,\n                    memo: \"C:\" + context2.memo\n                }\n            }]\n          }, {\n            blocksBehind: 3,\n            expireSeconds: 30\n          })\n\n          printMessage(\"Transaction to cancel the order is pushed! Pending to remove the order from the orderbook.\")\n          context2.feeTrxId = result.transaction_id\n          var context3 = context2\n\n          var funcTmp = async function () {\n            while (!context3.feeBlockNum) {\n              await new Promise(resolve => setTimeout(resolve, context3.that.checkBlockInterval))\n\n              const res = await window.eos_rpc.history_get_transaction(context3.feeTrxId)\n\n              if (res != null && typeof res.trx != \"undefined\" && typeof res.trx.receipt != \"undefined\" &&\n                  typeof res.trx.receipt.status == \"string\" && res.trx.receipt.status == \"executed\" &&\n                  typeof res.block_num != \"undefined\" && Number.isInteger(res.block_num)) {\n                context3.feeBlockNum = res.block_num\n                break\n              }\n            }\n          }\n\n          await funcTmp()\n\n          window.notifier.notifyTransactionForCancellation(\"eos\", context2.feeTrxId, context2.feeBlockNum, function () {\n            window.orderStore.storeRemovedOrder(context3.oldTrxId, context3.oldBlockNum, context3.feeTrxId, context3.feeBlockNum)\n          })\n        } catch (e) {\n          printErrorMessage(\"Caught exception while sending transaction(EOS platform): \" + e)\n\n          if (e instanceof window.eosjs_jsonrpc.RpcError) {\n            printErrorMessage(JSON.stringify(e.json, null, 2))\n          }\n        }\n      })()\n    }\n\n    window.marketMaker = {\n      sendOrder: function (mailAddr, basePlatform, baseAccount, baseCryptocurrency, baseAmountTmp, termPlatform, termCryptocurrency, termAmountTmp, feeAmountTmp, orderExpirationTmp) {\n        var basePlatformObj = window.platforms[basePlatform]\n        var termPlatformObj = window.platforms[termPlatform]\n        var smartContract = termPlatformObj.getSmartContract(termCryptocurrency)\n        if (smartContract == null || smartContract == \"\") {\n          printErrorMessage(\"The smart contract doesn't exist.\")\n          return\n        }\n        var actionName = termPlatformObj.getActionName(termCryptocurrency)\n        if (actionName == null) {\n          printErrorMessage(\"The action name doesn't exist.\")\n          return\n        }\n        if (baseAmountTmp <= 0) {\n          printErrorMessage(\"The amount of the base cryptocurrency should be greater than zero.\")\n          return\n        }\n        var baseAmount = basePlatformObj.makeAmountAccurate(baseCryptocurrency, baseAmountTmp)\n        if (baseAmount == null) {\n          printErrorMessage(\"The base cryptocurrency is not supported.\")\n          return\n        }\n        if (termAmountTmp <= 0) {\n          printErrorMessage(\"The amount of the term cryptocurrency should be greater than zero.\")\n          return\n        }\n        var termAmount = termPlatformObj.makeAmountAccurate(termCryptocurrency, termAmountTmp)\n        if (termAmount == null) {\n          printErrorMessage(\"The term cryptocurrency is not supported.\")\n          return\n        }\n        var platformCurrency = termPlatformObj.getPlatformCurrency()\n        if (platformCurrency == null) {\n          printErrorMessage(\"The platform currency doesn't exist.\")\n          return\n        }\n        var feeAmountRequired = termPlatformObj.getFeeAmountRequired()\n        if (feeAmountTmp < feeAmountRequired) {\n          printErrorMessage(\"The fee shouldn't be less than \" + feeAmountRequired + \" \" + platformCurrency + \".\")\n          return\n        }\n        var feeAmount = termPlatformObj.makeAmountAccurate(platformCurrency, feeAmountTmp)\n        var orderExpiration = Math.floor(orderExpirationTmp * window.oneHour)\n        if (orderExpiration < window.oneHour) {\n          printErrorMessage(\"The expiration of the order should be greater than or equal to one hour.\")\n          return\n        }\n        if (window.platforms[termPlatform].exchange == null || window.platforms[termPlatform].feeRecipient == null || !window.dexConnected) {\n          printErrorMessage(\"The server side is not connected yet.\")\n          return\n        }\n\n        var expiration = Math.round(new Date().getTime() + orderExpiration)\n        var memo = baseCryptocurrency + \":\" + baseAmount + \":\" + termCryptocurrency + \":\" + termAmount + \":\" + expiration + \":\" + basePlatform + \":\" + baseAccount\n\n        termPlatformObj.sendOrder(mailAddr, smartContract, actionName, termAmount, termCryptocurrency, feeAmount, platformCurrency, memo,\n                                  basePlatform, baseAccount, baseCryptocurrency, baseAmount, termPlatform, termAmountTmp / baseAmountTmp,\n                                  Math.round(feeAmountTmp / termPlatformObj.getFeeAmountRequiredForOperation()), expiration, baseAmountTmp, termAmountTmp)\n      },\n      modifyOrder: function (oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmountTmp, termPlatform, termCryptocurrency, termAmountTmp, oldBasePlatform, oldBaseCryptocurrency, feeAmountTmp, orderExpirationTmp) {\n        var termPlatformObj = window.platforms[termPlatform]\n\n        if (baseAmountTmp <= 0) {\n          printErrorMessage(\"The amount of the base cryptocurrency should be greater than zero.\")\n          return\n        }\n        var basePlatformObj = window.platforms[basePlatform]\n        var termPlatformObj = window.platforms[termPlatform]\n        var baseAmount = basePlatformObj.makeAmountAccurate(baseCryptocurrency, baseAmountTmp)\n        if (baseAmount == null) {\n          printErrorMessage(\"The base cryptocurrency is not supported.\")\n          return\n        }\n        var platformCurrency = termPlatformObj.getPlatformCurrency()\n        if (platformCurrency == null) {\n          printErrorMessage(\"The platform currency doesn't exist.\")\n          return\n        }\n        var feeAmountRequired = termPlatformObj.getFeeAmountRequiredForOperation()\n        if (feeAmountTmp < feeAmountRequired) {\n          printErrorMessage(\"The fee shouldn't be less than \" + feeAmountRequired + \" \" + platformCurrency + \".\")\n          return\n        }\n        var feeAmount = termPlatformObj.makeAmountAccurate(platformCurrency, feeAmountTmp)\n        var orderExpiration = Math.floor(orderExpirationTmp * window.oneHour)\n        if (orderExpiration < window.oneHour) {\n          printErrorMessage(\"The expiration of the order should be greater than or equal to one hour.\")\n          return\n        }\n        if (window.platforms[termPlatform].exchange == null || window.platforms[termPlatform].feeRecipient == null || !window.dexConnected) {\n          printErrorMessage(\"The server side is not connected yet.\")\n          return\n        }\n\n        var expiration = Math.round(new Date().getTime() + orderExpiration)\n        var memo = baseCryptocurrency + \":\" + baseAmount + \":\" + termCryptocurrency + \":\" + oldBasePlatform + \":\" + oldBaseCryptocurrency + \":\" + oldTrxId + \":\" + oldBlockNum + \":\" +\n                  expiration + \":\" + basePlatform + \":\" + baseAccount\n\n        termPlatformObj.modifyOrder(feeAmount, platformCurrency, memo,\n            oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmount, termAmountTmp / baseAmountTmp,\n            Math.round(feeAmountTmp / feeAmountRequired), expiration, baseAmountTmp)\n      },\n      cancelOrder: function (basePlatform, baseCryptocurrency, termPlatform, termCryptocurrency, oldExpiration, trxId, blockNum) {\n        var expiration = new Date(oldExpiration).getTime()\n\n        var termPlatformObj = window.platforms[termPlatform]\n\n        if (expiration <= new Date().getTime()) {\n          printErrorMessage(\"The order has expired.\")\n          return\n        }\n        var platformCurrency = termPlatformObj.getPlatformCurrency()\n        if (platformCurrency == null) {\n          printErrorMessage(\"The platform currency doesn't exist.\")\n          return\n        }\n        var feeAmount = termPlatformObj.makeAmountAccurate(platformCurrency, termPlatformObj.getFeeAmountRequiredForOperation())\n        if (window.platforms[termPlatform].exchange == null || window.platforms[termPlatform].feeRecipient == null || !window.dexConnected) {\n          printErrorMessage(\"The server side is not connected yet.\")\n          return\n        }\n\n        var memo = basePlatform + \":\" + baseCryptocurrency + \":\" + termCryptocurrency + \":\" + trxId + \":\" + blockNum\n\n        termPlatformObj.cancelOrder(feeAmount, platformCurrency, memo, trxId, blockNum)\n      }\n    }\n\n    function getDex (state) {\n      return new Promise((res, rej) => {\n        $.ajax({\n          type: \"POST\",\n          url: window.serverUrl + \"/contacts/listing\",\n          headers: {\"Authorization\": \"Basic \" + btoa(\"guest:guest\")},\n          contentType: \"application/json; charset=utf-8\",\n          dataType: \"json\",\n          data: JSON.stringify({\n            state: state,\n            contactId: window.contactId\n          }),\n          success: function (data) {\n                      if (Array.isArray(data.res)) {\n                        if (data.res.length > 0) {\n                          res(data.res)\n                        } else {\n                          res([])\n                        }\n                      } else {\n                        rej()\n                      }\n                    }\n        })\n      })\n    }\n\n    function getCryptocurrencies (state) {\n      return new Promise((res, rej) => {\n        $.ajax({\n          type: \"POST\",\n          url: window.serverUrl + \"/cryptocurrencies/listing\",\n          headers: {\"Authorization\": \"Basic \" + btoa(\"guest:guest\")},\n          contentType: \"application/json; charset=utf-8\",\n          dataType: \"json\",\n          data: JSON.stringify({\n            state: state,\n            contactId: window.contactId\n          }),\n          success: function (data) {\n                      if (Array.isArray(data.res)) {\n                        if (data.res.length > 0) {\n                          res(data.res)\n                        } else {\n                          res([])\n                        }\n                      } else {\n                        rej()\n                      }\n                    }\n        })\n      })\n    }\n\n    getDex(\"A\")\n    .then(function (dex) {\n      if (dex.length <= 0) {\n        return\n      }\n\n      var dx = dex[0]\n\n      if (parseInt(window.contactId) != dx.dexKey) {\n        return\n      }\n\n      window.platforms[\"eth\"].feeRecipient = dx.ethFeeRecipient\n      window.platforms[\"eth\"].exchange = dx.ethRecipient\n      window.platforms[\"eth\"].feeAmountRequired = dx.ethFeeAmountRequired\n      window.platforms[\"eos\"].feeRecipient = dx.eosFeeRecipient\n      window.platforms[\"eos\"].exchange = dx.eosRecipient\n      window.platforms[\"eos\"].feeAmountRequired = dx.eosFeeAmountRequired\n      window.ethReceiptUrl = window.testNet == 1 ? dx.ethReceiptUrl1 : dx.ethReceiptUrl\n      window.dexConnected = dx.connected\n    })\n    .catch(function () {})\n\n    getCryptocurrencies(\"A\")\n    .then(function (cryptocurrencies) {\n      for (var i in cryptocurrencies) {\n        if (isNaN(i)) continue\n\n        var cryptocurrency = cryptocurrencies[i]\n        var platform = window.platforms[cryptocurrency.platform]\n\n        if (cryptocurrency.platform == \"eth\") {\n          cryptocurrency.actionName = JSON.parse(cryptocurrency.actionName)\n        }\n        platform.cryptocurrencies[cryptocurrency.cryptocurrency] = cryptocurrency\n      }\n    })\n    .catch(function () {})\n\n    // This strategy is based on random values.\n    window.runStrategy1 = function () {\n      var orderType = Math.random() > 0.5 ? \"B\" : \"S\"\n      var order = null\n\n      if (orderType == \"B\") {\n        order = {\n          basePlatform: window.basePlatform,\n          baseCryptocurrency: window.baseCryptocurrency,\n          termPlatform: window.termPlatform,\n          termCryptocurrency: window.termCryptocurrency\n        }\n\n        platform = window.platforms[order.termPlatform]\n      } else {\n        order = {\n          basePlatform: window.termPlatform,\n          baseCryptocurrency: window.termCryptocurrency,\n          termPlatform: window.basePlatform,\n          termCryptocurrency: window.baseCryptocurrency\n        }\n      }\n\n      var platform = window.platforms[order.termPlatform]\n\n      order.baseAccount = order.basePlatform == \"eth\" ? window.ethAccount : window.eosAccount\n      order.baseAmount = 0.1\n      order.termAmount = Math.round(order.baseAmount * Math.random() * 100) / 100\n      order.termAmount = order.termAmount < 0.01 ? 0.01 : order.termAmount\n      order.feeAmount = platform.getFeeAmountRequiredForOperation() * 2\n      order.orderExpiration = 30\n\n      window.marketMaker.sendOrder(window.mailAddr, order.basePlatform, order.baseAccount, order.baseCryptocurrency, order.baseAmount,\n        order.termPlatform, order.termCryptocurrency, order.termAmount, order.feeAmount, order.orderExpiration)\n\n      setTimeout(window.runStrategy1, window.tradeInterval)\n    }\n    setTimeout(window.runStrategy1, window.tradeInterval)\n  },\n  function (context) { // Deinit()\n  },\n  function (context) { // OnTick()\n  }\n)\n"
  },
  {
    "path": "EA/Plugin-for-XCoinCH/usage.txt",
    "content": "XCoinCH is another product developed by the Fintechee team, with X standing for cross and CH for clearing house. XCoinCH is a semi-decentralized platform for exchanging cryptocurrency tokens, such as USDT, across multiple chains.\n\nThis plugin is intended for use with XCoinCH, providing users with a portal to interact with the platform directly from our WEB trader.\n"
  },
  {
    "path": "EA/PriceAction/price_action.js",
    "content": "// This EA has a built-in trailing stop management system, so, DO NOT use plugin_for_trailingstop at the same time.\nregisterEA(\n\"price_action\",\n\"A strategy based on price action(v1.07)\",\n[{\n\tname: \"symbolName\", // this parameter to set the symbols that you want to have trailing stops applied\n\tvalue: \"EUR/USD\", // e.g. EUR/USD,GBP/USD\n\trequired: true,\n\ttype: \"String\",\n\trange: null,\n\tstep: null\n}, {\n\tname: \"timeFrame\",\n\tvalue: TIME_FRAME.M5,\n\trequired: true,\n\ttype: \"String\",\n\trange: null,\n\tstep: null\n}, {\n\tname: \"candleStickNum\",\n\tvalue: 8,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100],\n\tstep: null\n}, {\n\tname: \"trailingStop\",\n\tvalue: 20,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [1, 10000],\n\tstep: null\n}, {\n\tname: \"volume\",\n\tvalue: 0.01,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [0.01, 10],\n\tstep: null\n}],\nfunction (context) { // Init()\n\tvar account = getAccount(context, 0)\n\tvar brokerName = getBrokerNameOfAccount(account)\n\tvar accountId = getAccountIdOfAccount(account)\n\tvar symbolNames = getEAParameter(context, \"symbolName\").split(\",\")\n\tvar timeFrame = getEAParameter(context, \"timeFrame\")\n\tvar candleStickNum = getEAParameter(context, \"candleStickNum\")\n\tvar trailingStop = getEAParameter(context, \"trailingStop\")\n\tvar volume = getEAParameter(context, \"volume\")\n\n\tcontext.priceAction = {\n\t\tchartHandles: [],\n\t\tcandleStickNum: candleStickNum,\n\t\ttrailingStop: trailingStop,\n\t\tvolume: volume,\n\t\ttrendUp: [],\n\t\ttrendDown: [],\n\t\ttrendUpLines: [],\n\t\ttrendDownLines: [],\n\t\ttrailingStopLines: [],\n\t\topenTrades: [],\n\t\tcheckTrailingStop: function (tick) {\n\t\t\tvar cnt = this.openTrades.length\n\n\t\t\tfor (var i = cnt - 1; i >= 0; i--) {\n\t\t\t\tvar openTrade = this.openTrades[i]\n\t\t\t\tvar symbolName = openTrade.symbolName\n\n\t\t\t\tif (openTrade.brokerName == tick.brokerName && openTrade.accountId == tick.accountId && symbolName == tick.symbolName) {\n\t\t\t\t\tif (openTrade.orderType == \"BUY\") {\n\t\t\t\t\t\tif (tick.bid - Math.max(openTrade.stopLoss, openTrade.price) > openTrade.trailingStop) {\n\t\t\t\t\t\t\topenTrade.stopLoss = tick.bid - openTrade.trailingStop\n\t\t\t\t\t\t\topenTrade.bSlChanged = true\n\n\t\t\t\t\t\t\tvar chartHandle = this.chartHandles[symbolName]\n\t\t\t\t\t\t\tvar trailingStopId = this.trailingStopLines[openTrade.tradeId]\n\t\t\t\t\t\t\tsetObjectPropPrice1(chartHandle, trailingStopId, openTrade.stopLoss)\n\t\t\t\t\t\t\tsetObjectPropPrice2(chartHandle, trailingStopId, openTrade.stopLoss)\n\t\t\t\t\t\t} else if (tick.bid <= openTrade.stopLoss && openTrade.bSlChanged) {\n\t\t\t\t\t\t\tcloseTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0)\n\t\t\t\t\t\t\tif (typeof this.openTrades[i] != \"undefined\" && openTrade.tradeId == this.openTrades[i].tradeId) { // The reason I added this condition is that during backtesting, closeTrade may trigger onTransaction, which could potentially remove the item after calling syncOpenTrades.\n\t\t\t\t\t\t\t\tthis.openTrades.splice(i, 1)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (Math.min(openTrade.stopLoss, openTrade.price) - tick.ask > openTrade.trailingStop) {\n\t\t\t\t\t\t\topenTrade.stopLoss = tick.ask + openTrade.trailingStop\n\t\t\t\t\t\t\topenTrade.bSlChanged = true\n\n\t\t\t\t\t\t\tvar chartHandle = this.chartHandles[symbolName]\n\t\t\t\t\t\t\tvar trailingStopId = this.trailingStopLines[openTrade.tradeId]\n\t\t\t\t\t\t\tsetObjectPropPrice1(chartHandle, trailingStopId, openTrade.stopLoss)\n\t\t\t\t\t\t\tsetObjectPropPrice2(chartHandle, trailingStopId, openTrade.stopLoss)\n\t\t\t\t\t\t} else if (tick.ask >= openTrade.stopLoss && openTrade.bSlChanged) {\n\t\t\t\t\t\t\tcloseTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0)\n\t\t\t\t\t\t\tif (typeof this.openTrades[i] != \"undefined\" && openTrade.tradeId == this.openTrades[i].tradeId) { // The reason I added this condition is that during backtesting, closeTrade may trigger onTransaction, which could potentially remove the item after calling syncOpenTrades.\n\t\t\t\t\t\t\t\tthis.openTrades.splice(i, 1)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcloseTrades: function (tick, orderType) {\n\t\t\tvar cnt = this.openTrades.length\n\t\t\tvar reverseCnt = 0\n\n\t\t\tfor (var i = cnt - 1; i >= 0; i--) {\n\t\t\t\tvar openTrade = this.openTrades[i]\n\n\t\t\t\tif (openTrade.brokerName == tick.brokerName && openTrade.accountId == tick.accountId && openTrade.symbolName == tick.symbolName) {\n\t\t\t\t\tif (openTrade.orderType == orderType) {\n\t\t\t\t\t\tcloseTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0)\n\t\t\t\t\t\tif (typeof this.openTrades[i] != \"undefined\" && openTrade.tradeId == this.openTrades[i].tradeId) { // The reason I added this condition is that during backtesting, closeTrade may trigger onTransaction, which could potentially remove the item after calling syncOpenTrades.\n\t\t\t\t\t\t\tthis.openTrades.splice(i, 1)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treverseCnt++\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn reverseCnt\n\t\t},\n\t\tsyncOpenTrades: function (tradeId) {\n\t\t\tvar cnt = this.openTrades.length\n\n\t\t\tfor (var i = cnt - 1; i >= 0; i--) {\n\t\t\t\tvar openTrade = this.openTrades[i]\n\t\t\t\tif (openTrade.tradeId == tradeId) {\n\t\t\t\t\tthis.openTrades.splice(i, 1)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcheckSignals: function (chartHandle, tick, arrTime, arrOpen, arrHigh, arrLow, arrClose) {\n\t\t\tvar symbolName = tick.symbolName\n\t\t\tvar arrLen = arrOpen.length\n\n\t\t\tif (arrClose[arrLen - 2] > arrOpen[arrLen - 2] && arrClose[arrLen - 3] < arrOpen[arrLen - 3] && arrClose[arrLen - 4] < arrOpen[arrLen - 4] && arrClose[arrLen - 2] < arrOpen[arrLen - 4]) {\n\t\t\t\tif (typeof this.trendUp[symbolName] == \"undefined\") {\n\t\t\t\t\tthis.trendUpLines[symbolName] = addTrendLine(chartHandle, chartHandle + \"_trendUp\", arrTime[arrLen - 60], arrHigh[arrLen - 4], arrTime[arrLen - 58], arrHigh[arrLen - 4])\n\t\t\t\t} else {\n\t\t\t\t\tvar trendLineId = this.trendUpLines[symbolName]\n\t\t\t\t\tsetObjectPropTime1(chartHandle, trendLineId, arrTime[arrLen - 60])\n\t\t\t\t\tsetObjectPropPrice1(chartHandle, trendLineId, arrHigh[arrLen - 4])\n\t\t\t\t\tsetObjectPropTime2(chartHandle, trendLineId, arrTime[arrLen - 58])\n\t\t\t\t\tsetObjectPropPrice2(chartHandle, trendLineId, arrHigh[arrLen - 4])\n\t\t\t\t}\n\n\t\t\t\tthis.trendUp[symbolName] = arrHigh[arrLen - 4]\n\t\t\t} else if (arrClose[arrLen - 2] < arrOpen[arrLen - 2] && arrClose[arrLen - 3] > arrOpen[arrLen - 3] && arrClose[arrLen - 4] > arrOpen[arrLen - 4] && arrClose[arrLen - 2] > arrOpen[arrLen - 4]) {\n\t\t\t\tif (typeof this.trendDown[symbolName] == \"undefined\") {\n\t\t\t\t\tthis.trendDownLines[symbolName] = addTrendLine(chartHandle, chartHandle + \"_trendDown\", arrTime[arrLen - 60], arrLow[arrLen - 4], arrTime[arrLen - 58], arrLow[arrLen - 4])\n\t\t\t\t} else {\n\t\t\t\t\tvar trendLineId = this.trendDownLines[symbolName]\n\t\t\t\t\tsetObjectPropTime1(chartHandle, trendLineId, arrTime[arrLen - 60])\n\t\t\t\t\tsetObjectPropPrice1(chartHandle, trendLineId, arrLow[arrLen - 4])\n\t\t\t\t\tsetObjectPropTime2(chartHandle, trendLineId, arrTime[arrLen - 58])\n\t\t\t\t\tsetObjectPropPrice2(chartHandle, trendLineId, arrLow[arrLen - 4])\n\t\t\t\t}\n\n\t\t\t\tthis.trendDown[symbolName] = arrLow[arrLen - 4]\n\t\t\t}\n\n\t\t\tif (typeof this.trendUp[symbolName] == \"undefined\" || typeof this.trendDown[symbolName] == \"undefined\") {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (arrClose[arrLen - 2] >= this.trendUp[symbolName] && arrClose[arrLen - 3] < this.trendUp[symbolName]) {\n\t\t\t\tvar reverseCnt = this.closeTrades(tick, \"SELL\")\n\n\t\t\t\tif (reverseCnt == 0) {\n\t\t\t\t\tvar support = Number.MAX_VALUE\n\t\t\t\t\tvar scope = arrLen - this.candleStickNum\n\t\t\t\t\tfor (var i = arrLen - 1; i >= scope; i--) {\n\t\t\t\t\t\tif (arrLow[i] < support) {\n\t\t\t\t\t\t\tsupport = arrLow[i]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tick.bid - support > 2 / (getSymbolInfo(tick.brokerName, tick.accountId, symbolName).toFixed / 10)) {\n\t\t\t\t\t\tsendOrder(tick.brokerName, tick.accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, this.volume, 0, support, \"\", 0, 0)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (arrClose[arrLen - 2] <= this.trendDown[symbolName] && arrClose[arrLen - 3] > this.trendDown[symbolName]) {\n\t\t\t\tvar reverseCnt = this.closeTrades(tick, \"BUY\")\n\n\t\t\t\tif (reverseCnt == 0) {\n\t\t\t\t\tvar resistance = -Number.MAX_VALUE\n\t\t\t\t\tvar scope = arrLen - this.candleStickNum\n\t\t\t\t\tfor (var i = arrLen - 1; i >= scope; i--) {\n\t\t\t\t\t\tif (arrHigh[i] > resistance) {\n\t\t\t\t\t\t\tresistance = arrHigh[i]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (resistance - tick.ask > 2 / (getSymbolInfo(tick.brokerName, tick.accountId, symbolName).toFixed / 10)) {\n\t\t\t\t\t\tsendOrder(tick.brokerName, tick.accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, this.volume, 0, resistance, \"\", 0, 0)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (var i in symbolNames) {\n\t\tvar symbolName = symbolNames[i]\n\t\tgetQuotes(context, brokerName, accountId, symbolName)\n\t\tcontext.priceAction.chartHandles[symbolName] = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n\t}\n},\nfunction (context) { // Deinit()\n\tfor (var i in context.priceAction.chartHandles) {\n\t\tvar chartHandle = context.priceAction.chartHandles[i]\n\t\tif (typeof context.priceAction.trendUpLines[i] != \"undefined\") {\n\t\t\tremoveObject(chartHandle, context.priceAction.trendUpLines[i])\n\t\t}\n\t\tif (typeof context.priceAction.trendDownLines[i] != \"undefined\") {\n\t\t\tremoveObject(chartHandle, context.priceAction.trendDownLines[i])\n\t\t}\n\n\t\tfor (var j in context.priceAction.trailingStopLines) {\n\t\t\tremoveObject(chartHandle, context.priceAction.trailingStopLines[j])\n\t\t}\n\t}\n},\nfunction (context) { // OnTick()\n\tvar tick = getCurrentTick(context)\n\tcontext.priceAction.checkTrailingStop(tick)\n\n\tvar symbolName = tick.symbolName\n\tvar chartHandle = context.priceAction.chartHandles[symbolName]\n\tvar arrTime = getData(context, chartHandle, DATA_NAME.TIME)\n\tvar arrOpen = getData(context, chartHandle, DATA_NAME.OPEN)\n\tvar arrHigh = getData(context, chartHandle, DATA_NAME.HIGH)\n\tvar arrLow = getData(context, chartHandle, DATA_NAME.LOW)\n\tvar arrClose = getData(context, chartHandle, DATA_NAME.CLOSE)\n\n\tcontext.priceAction.checkSignals(chartHandle, tick, arrTime, arrOpen, arrHigh, arrLow, arrClose)\n},\nfunction (context) { // OnTransaction()\n  var transType = getLatestTransType(context)\n\n  if (transType == \"Open Trade\") {\n\t\tvar trans = getLatestTrans(context)\n\t\tvar transTradeId = getTradeId(trans)\n\t\tvar transBrokerName = getBrokerName(trans)\n\t  var transAccountId = getAccountId(trans)\n\t  var transSymbolName = getSymbolName(trans)\n\t  var transOrderType = getOrderType(trans).split(\" \")[0]\n\t\tvar transPrice = getOpenPrice(trans)\n\t\tvar transSl = getStopLoss(trans)\n\n\t\tcontext.priceAction.openTrades.push({\n\t\t\ttradeId: transTradeId,\n\t\t\tbrokerName: transBrokerName,\n\t\t\taccountId: transAccountId,\n\t\t\tsymbolName: transSymbolName,\n\t\t\torderType: transOrderType,\n\t\t\tprice: transPrice,\n\t\t\tstopLoss: transSl,\n\t\t\ttrailingStop: context.priceAction.trailingStop / (getSymbolInfo(transBrokerName, transAccountId, transSymbolName).toFixed / 10),\n\t\t\tbSlChanged: false\n\t\t})\n\n\t\tvar chartHandle = context.priceAction.chartHandles[transSymbolName]\n\t\tvar arrTime = getData(context, chartHandle, DATA_NAME.TIME)\n\t\tvar arrLen = arrTime.length\n\t\tcontext.priceAction.trailingStopLines[transTradeId] = addTrendLine(chartHandle, transTradeId + \"_trailingStop\", arrTime[arrLen - 2], transSl, arrTime[arrLen - 1], transSl)\n\t} else if (transType == \"Trade Closed\") {\n\t\tvar trans = getLatestTrans(context)\n\t\tcontext.priceAction.syncOpenTrades(getTradeId(trans))\n\n\t\tvar chartHandle = context.priceAction.chartHandles[getSymbolName(trans)]\n\t\tremoveObject(chartHandle, context.priceAction.trailingStopLines[getTradeId(trans)])\n\t\tdelete context.priceAction.trailingStopLines[getTradeId(trans)]\n  }\n})\n"
  },
  {
    "path": "EA/Sample-for-Workflow/callee.js",
    "content": "registerEA(\n  \"callee\",\n  \"A test EA playing the role as a step in the workflow(v1.0)\",\n  [{\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function(context) { // Init()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n\n    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M5)\n  },\n  function(context) { // Deinit()\n  },\n  function(context) { // OnTick()\n  },\n  function(context) { // OnTransaction()\n  }\n)\n"
  },
  {
    "path": "EA/Sample-for-Workflow/caller.js",
    "content": "registerEA(\n  \"caller\",\n  \"A test EA to launch the callee EA(v1.0)\",\n  [{\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function(context) { // Init()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n\n    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M5)\n    launchEA(\"callee\", [{name: \"symbolName\", value: \"EUR/USD\"}])\n  },\n  function(context) { // Deinit()\n  },\n  function(context) { // OnTick()\n  },\n  function(context) { // OnTransaction()\n  }\n)\n"
  },
  {
    "path": "EA/Tips/about_API_getData.txt",
    "content": "Let me share a very important point to use the API getData.\nWe didn't update this API's specs, so, no need to sync your codes.\n\nWe have an API to set the shift value for indicators to make the indicator shift to the left or to the right.\nThe API is called setIndiShift.\n\nEven if you call this API - setIndiShift in your custom indicator codes,  the data received by calling getData in your EA codes will have no difference.\n\nFor example:\nYou call setIndiShift(context, \"sma\", 5) in your custom moving average codes to make the MA shift to the right by 5 units.\nAnd then you call getData in your EA codes to get the edited MA's data.\nThe return array data will be the same as the return array from calling a custom MA with setIndiShift(context, \"sma\", 0)\n\nWhy?\nBecause Fintechee ignores the effect of setIndiShift when getData is called.\nSo, if you want to get the latest value of the MA with setIndiShift(context, \"sma\", 5), you need to specify the index reduced by 5(such as arrData[arrLen - 1 - 5]).\narrData[arrLen - 1] will get the latest value of the MA with setIndiShift(context, \"sma\", 0).\n\nNot clear?\nOkay, let me give a detailed example.\nWe have an indicator xxx that contains an array of ten values, 1, 2, 3,..., 7, 8, 9, 10.\nWhen we call setIndiShift(context, \"xxx\", 3) to make xxx shift to the right by 3 units, the array of the data still is the same as xxx with setIndiShift(context, \"xxx\", 0).\nSo, if we want to get the latest value of xxx with setIndiShift(context, \"xxx\", 0), we use arrData[arrLen - 1] and get 10.\nIf we want to get the latest value of xxx with setIndiShift(context, \"xxx\", 3), then we use arrData[arrLen - 1 - 3] and get 7.\nNo matter what shift is entered when we call setIndiShift, the return array of getData is the same.\n"
  },
  {
    "path": "EA/Tips/how_to_rename.txt",
    "content": "Why rename the specific EA and indicator?\n\nThis is very important to know before you customize your own EA/indicator by referencing the EA/indicator we(Fintechee) provide. Because Fintechee has built-in EAs/indicators, so these built-in programs may be updated automatically when you use the WEB trader. To avoid being overwritten, you need to rename the programs.\n\nHow to rename?\n\nYou can't rename the programs by simply changing the file names of the programs you find via our Github repo. You need to open the file and find the keyword \"registerEA\" and \"registerIndicator\"(actually the keywords are API names). Please change the first parameters of \"registerEA\" and \"registerIndicator\"(the first parameter is the name) and then run it on the console panel. This operation will make a copy of the source codes that you want to reference.\n"
  },
  {
    "path": "EA/Utility/historical_data_cleaner.js",
    "content": "registerEA(\n\t\t\"historical_data_cleaner\",\n\t\t\"An EA only used for clearing historical data stored on your local browser(v1.01)\",\n\t\t[],\n\t\tfunction (context) { // Init()\n\t\t\tvar myDB = null\n\t\t\tvar requestOpen = window.indexedDB.open(\"Chart-Coaster\")\n\n\t\t\trequestOpen.onsuccess = function (e) {\n\t\t\t\tmyDB = requestOpen.result\n\n\t\t\t\t// var requestClear =myDB.transaction(\"k_o\", \"readwrite\").objectStore(\"k_o\").clear() // not working\n\t\t\t\tvar requestClear = window.indexedDB.deleteDatabase(\"Chart-Coaster\")\n\n\t\t\t\trequestClear.onsuccess = function () {\n\t\t\t\t\tpopupMessage(\"The data store has been cleared successfully.\")\n\t\t\t\t}\n\n\t\t\t\trequestClear.onerror = function (err) {\n\t\t\t\t\tpopupErrorMessage(\"Failed to clear the data store.\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trequestOpen.onerror = function (err) {\n\t\t\t\tpopupErrorMessage(\"Failed to open the data store.\")\n\t\t\t}\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t},\n\t\tfunction (context) { // OnTransaction()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Utility/historical_data_viewer.js",
    "content": "registerEA(\n\t\t\"historical_data_viewer\",\n\t\t\"An EA only used for watching historical data in the backtesting mode(v1.0)\",\n\t\t[{ // parameters\n\t\t\tname: \"symbolName\",\n\t    value: \"EUR/USD\",\n\t    required: true,\n\t    type: PARAMETER_TYPE.STRING,\n\t    range: null\n\t  },{\n\t\t\tname: \"timeFrame\",\n\t    value: TIME_FRAME.H1,\n\t    required: true,\n\t    type: PARAMETER_TYPE.STRING,\n\t    range: null\n\t\t}],\n\t\tfunction (context) { // Init()\n\t\t\tvar account = getAccount(context, 0)\n\t\t\tvar brokerName = getBrokerNameOfAccount(account)\n\t\t\tvar accountId = getAccountIdOfAccount(account)\n\t\t\tvar symbolName = getEAParameter(context, \"symbolName\")\n\t\t\tvar timeFrame = getEAParameter(context, \"timeFrame\")\n\n\t\t\tcontext.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n\t\t},\n\t\tfunction (context) { // Deinit()\n\t\t},\n\t\tfunction (context) { // OnTick()\n\t\t},\n\t\tfunction (context) { // OnTransaction()\n\t\t}\n\t)\n"
  },
  {
    "path": "EA/Utility/usage.txt",
    "content": "The “historical_data_cleaner” is designed to clear the OHLC data within the IndexedDB stored on your browser.\n\nOn the other hand, the “historical_data_viewer” is solely used during strategy backtesting procedures. It functions by downloading historical data into the platform and replays it to simulate the operation of such data.\n"
  },
  {
    "path": "Indicators/Built-in/README.md",
    "content": "The indicators in this folder will be updated automatically when you open the WEB trader.\n\nIf you customize the indicators in this folder, please rename them to avoid being overwritten.\n"
  },
  {
    "path": "Indicators/Built-in/ac.js",
    "content": "registerIndicator(\n\"ac\",\n\"Accelerator Oscillator(v1.0)\",\nfunction (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tvar dataUp = getDataOutput(context, \"up\")\n\t\tvar dataDown = getDataOutput(context, \"down\")\n\t\tvar dataFSMA = getDataOutput(context, \"fastSMA\")\n\t\tvar dataSSMA = getDataOutput(context, \"slowSMA\")\n\t\tvar dataOutputMain = getDataOutput(context, \"main\")\n\t\tvar dataOutputSignal = getDataOutput(context, \"signal\")\n\n\t\tvar fSMA = 5\n\t\tvar sSMA = 34\n\t\tvar sgnlSMA = 5\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\n\t\tif (i == 0) {\n\t\t\tdataFSMA[0] = dataInput[0]\n\t\t\tdataSSMA[0] = dataInput[0]\n\t\t\tdataOutputMain[0] = 0\n\t\t\ti++\n\t\t} else if (i == 1) {\n\t\t} else {\n\t\t\ti--\n\t\t}\n\n\t\tsma(dataInput, dataFSMA, calculatedLength, fSMA)\n\t\tsma(dataInput, dataSSMA, calculatedLength, sSMA)\n\n\t\twhile (i < dataInput.length) {\n\t\t\tdataOutputMain[i] = dataFSMA[i] - dataSSMA[i]\n\t\t\ti++\n\t\t}\n\n\t\tsma(dataOutputMain, dataOutputSignal, calculatedLength, sgnlSMA)\n\n\t\ti = calculatedLength\n\n\t\tif (i == 0) {\n\t\t\ti++\n\t\t} else if (i == 1) {\n\t\t} else {\n\t\t\ti--\n\t\t}\n\n\t\tvar prev, curr\n\n\t\twhile (i < dataInput.length) {\n\t\t\tprev = dataOutputMain[i - 1] - dataOutputSignal[i - 1]\n\t\t\tcurr = dataOutputMain[i] - dataOutputSignal[i]\n\n\t\t\tif (prev <= curr) {\n\t\t\t\tdataUp[i] = curr\n\t\t\t\tdataDown[i] = 0\n\t\t\t} else {\n\t\t\t\tdataUp[i] = 0\n\t\t\t\tdataDown[i] = curr\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\t},\n[], [{\n\tname: \"HL2\",\n\tindex: 0\n}], [{\n\tname: \"up\",\n\tvisible: true,\n\trenderType: \"Histogram\",\n\tcolor: \"#6CBA81\"\n}, {\n\tname: \"down\",\n\tvisible: true,\n\trenderType: \"Histogram\",\n\tcolor: \"#ECAE93\"\n}, {\n\tname: \"fastSMA\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"slowSMA\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"main\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"signal\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/adx.js",
    "content": "registerIndicator(\n    \"adx\", \"Average directional index(v1.0)\", function (context) {\n        var dataInputClose = getDataInput(context, 0)\n\t\tvar dataInputHigh = getDataInput(context, 1)\n\t\tvar dataInputLow = getDataInput(context, 2)\n\n\t\tvar tmpLine = getDataOutput(context, \"tmp\")\n\t\tvar plusSdiTmp = getDataOutput(context, \"plusSdiTmp\")\n\t\tvar minusSdiTmp = getDataOutput(context, \"minusSdiTmp\")\n\n\t\tvar dataOutputAdx = getDataOutput(context, \"adx\")\n\t\tvar dataOutputPlusDi = getDataOutput(context, \"plusDi\")\n\t\tvar dataOutputMinusDi = getDataOutput(context, \"minusDi\")\n\n\t\tvar period = getIndiParameter(context, \"period\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\n\t\tif (i > 0) {\n\t\t\ti--\n\t\t} else {\n\t\t\tplusSdiTmp[i] = 0\n\t\t\tminusSdiTmp[i] = 0\n\t\t\ti = 1\n\t\t}\n\n\t\tvar plusDM = null\n\t\tvar minusDM = null\n\t\tvar trueRange = null\n\t\tvar currH = null\n\t\tvar currL = null\n\t\tvar prevH = null\n\t\tvar prevL = null\n\t\tvar prevC = null\n\n\t\twhile (i < dataInputClose.length) {\n\t\t\tcurrH = dataInputHigh[i]\n\t\t\tcurrL = dataInputLow[i]\n\t\t\tprevH = dataInputHigh[i - 1]\n\t\t\tprevL = dataInputLow[i - 1]\n\t\t\tprevC = dataInputClose[i - 1]\n\n\t\t\tplusDM = currH - prevH\n\t\t\tminusDM = prevL - currL\n\t\t\tif (0 > plusDM) {\n\t\t\t\tplusDM = 0\n\t\t\t}\n\t\t\tif (0 > minusDM) {\n\t\t\t\tminusDM = 0\n\t\t\t}\n\t\t\tif (plusDM == minusDM) {\n\t\t\t\tplusDM = 0\n\t\t\t\tminusDM = 0\n\t\t\t} else if (plusDM < minusDM) {\n\t\t\t\tplusDM = 0\n\t\t\t} else if (plusDM > minusDM) {\n\t\t\t\tminusDM = 0\n\t\t\t}\n\n\t\t\ttrueRange = Math.max(Math.abs(currH - currL), Math.abs(currH - prevC))\n\t\t\ttrueRange = Math.max(trueRange, Math.abs(currL - prevC))\n\n\t\t\tif (0 == trueRange) {\n\t\t\t\tplusSdiTmp[i] = 0\n\t\t\t\tminusSdiTmp[i] = 0\n\t\t\t}else{\n\t\t\t\tplusSdiTmp[i] = 100 * plusDM / trueRange\n\t\t\t\tminusSdiTmp[i] = 100 * minusDM / trueRange\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\n\t\tema(plusSdiTmp, dataOutputPlusDi, calculatedLength, period)\n\t\tema(minusSdiTmp, dataOutputMinusDi, calculatedLength, period)\n\n\t\ti = calculatedLength\n\t\tif (i > 0) {\n\t\t\ti--\n\t\t}\n\n\t\twhile (i < dataInputClose.length) {\n\t\t\tvar tmp = Math.abs(dataOutputPlusDi[i] + dataOutputMinusDi[i])\n\n\t\t\tif (0 == tmp) {\n\t\t\t\ttmpLine[i] = 0\n\t\t\t} else {\n\t\t\t\ttmpLine[i] = 100 * (Math.abs(dataOutputPlusDi[i] - dataOutputMinusDi[i]) / tmp)\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\n\t\tema(tmpLine, dataOutputAdx, calculatedLength, period)\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 14,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t},{\n\t\tname: DATA_NAME.HIGH,\n\t\tindex: 1\n\t},{\n\t\tname: DATA_NAME.LOW,\n\t\tindex: 2\n\t}],\n\t[{\n        name: \"tmp\",\n        visible: false\n    },{\n        name: \"plusSdiTmp\",\n        visible: false\n    },{\n        name: \"minusSdiTmp\",\n        visible: false\n    },{\n        name: \"adx\",\n        visible: true,\n        renderType: RENDER_TYPE.DASHARRAY,\n        color: \"#CCCCCC\"\n    },{\n        name: \"plusDi\",\n        visible: true,\n        renderType: RENDER_TYPE.LINE,\n        color: \"#4EC2B4\"\n    },{\n        name: \"minusDi\",\n        visible: true,\n        renderType: RENDER_TYPE.LINE,\n        color: \"#DE5029\"\n    }],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/alligator.js",
    "content": "registerIndicator(\n    \"alligator\", \"A series of Bill Williams' indicators(v1.02)\", function (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tvar dataOutputJaws = getDataOutput(context, \"jaws\")\n\t\tvar dataOutputTeeth = getDataOutput(context, \"teeth\")\n\t\tvar dataOutputLips = getDataOutput(context, \"lips\")\n\n\t\tvar method = getIndiParameter(context, \"method\")\n\t\tvar jawsPeriod = getIndiParameter(context, \"jawsPeriod\")\n\t\tvar jawsShift = getIndiParameter(context, \"jawsShift\")\n\t\tvar teethPeriod = getIndiParameter(context, \"teethPeriod\")\n\t\tvar teethShift = getIndiParameter(context, \"teethShift\")\n\t\tvar lipsPeriod = getIndiParameter(context, \"lipsPeriod\")\n\t\tvar lipsShift = getIndiParameter(context, \"lipsShift\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tif (\"smma\" == method) {\n\t\t\tsmma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)\n\t\t\tsmma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)\n\t\t\tsmma(dataInput, dataOutputLips, calculatedLength, lipsPeriod)\n\t\t} else if (\"sma\" == method) {\n\t\t\tsma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)\n\t\t\tsma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)\n\t\t\tsma(dataInput, dataOutputLips, calculatedLength, lipsPeriod)\n\t\t} else if(\"ema\" == method) {\n\t\t\tema(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)\n\t\t\tema(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)\n\t\t\tema(dataInput, dataOutputLips, calculatedLength, lipsPeriod)\n\t\t} else {\n\t\t\tlwma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod)\n\t\t\tlwma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod)\n\t\t\tlwma(dataInput, dataOutputLips, calculatedLength, lipsPeriod)\n\t\t}\n\n\t\tif (calculatedLength == 0) {\n\t\t\tsetIndiShift(context, \"jaws\", jawsShift)\n\t\t\tsetIndiShift(context, \"teeth\", teethShift)\n\t\t\tsetIndiShift(context, \"lips\", lipsShift)\n\t\t}\n\t},[{\n\t\tname: \"jawsPeriod\",\n\t\tvalue: 13,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"jawsShift\",\n\t\tvalue: 8,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t},{\n\t\tname: \"teethPeriod\",\n\t\tvalue: 8,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"teethShift\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t},{\n\t\tname: \"lipsPeriod\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"lipsShift\",\n\t\tvalue: 3,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t},{\n\t\tname: \"method\",\n\t\tvalue: \"smma\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING\n\t}],\n\t[{\n\t\tname: DATA_NAME.HL2,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"jaws\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"steelblue\"\n\t},{\n\t\tname: \"teeth\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"#DE5029\"\n\t},{\n\t\tname: \"lips\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"#4EC2B4\"\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/ao.js",
    "content": "registerIndicator(\n\"ao\",\n\"Awesome Oscillator(v1.0)\",\nfunction (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tvar dataUp = getDataOutput(context, \"up\")\n\t\tvar dataDown = getDataOutput(context, \"down\")\n\t\tvar dataFSMA = getDataOutput(context, \"fastSMA\")\n\t\tvar dataSSMA = getDataOutput(context, \"slowSMA\")\n\n\t\tvar fSMA = 5\n\t\tvar sSMA = 34\n\t\tvar sgnlSMA = 5\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\n\t\tif (i == 0) {\n\t\t\tdataFSMA[0] = dataInput[0]\n\t\t\tdataSSMA[0] = dataInput[0]\n\t\t\ti++\n\t\t} else if (i == 1) {\n\t\t} else {\n\t\t\ti--\n\t\t}\n\n\t\tsma(dataInput, dataFSMA, calculatedLength, fSMA)\n\t\tsma(dataInput, dataSSMA, calculatedLength, sSMA)\n\n\t\tvar prev, curr\n\n\t\twhile (i < dataInput.length) {\n\t\t\tprev = dataFSMA[i - 1] - dataSSMA[i - 1]\n\t\t\tcurr = dataFSMA[i] - dataSSMA[i]\n\n\t\t\tif (prev <= curr) {\n\t\t\t\tdataUp[i] = curr\n\t\t\t\tdataDown[i] = 0\n\t\t\t} else {\n\t\t\t\tdataUp[i] = 0\n\t\t\t\tdataDown[i] = curr\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\t},\n[], [{\n\tname: \"HL2\",\n\tindex: 0\n}], [{\n\tname: \"up\",\n\tvisible: true,\n\trenderType: \"Histogram\",\n\tcolor: \"#6CBA81\"\n}, {\n\tname: \"down\",\n\tvisible: true,\n\trenderType: \"Histogram\",\n\tcolor: \"#ECAE93\"\n}, {\n\tname: \"fastSMA\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"slowSMA\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/atr.js",
    "content": "registerIndicator(\n    \"atr\", \"Average true range(v1.0)\", function (context) {\n\t\tvar dataInputClose = getDataInput(context, 0)\n\t\tvar dataInputHigh = getDataInput(context, 1)\n\t\tvar dataInputLow = getDataInput(context, 2)\n\t\tvar tmpLine = getDataOutput(context, \"tmp\")\n\t\tvar dataOutput = getDataOutput(context, \"atr\")\n\n\t\tvar period = getIndiParameter(context, \"period\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\t\tvar high = null\n\t\tvar low = null\n\t\tvar prevClose = null\n\n\t\tif (i > 0) {\n\t\t\ti--\n\t\t} else {\n\t\t\ttmpLine[i] = 0\n\t\t\ti = 1\n\t\t}\n\n\t\twhile (i < dataInputClose.length) {\n\t\t\thigh = dataInputHigh[i]\n\t\t\tlow = dataInputLow[i]\n\t\t\tprevClose = dataInputClose[i - 1]\n\n\t\t\ttmpLine[i] = Math.max(high, prevClose) - Math.min(low, prevClose)\n\n\t\t\ti++\n\t\t}\n\n\t\tsma(tmpLine, dataOutput, calculatedLength, period)\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 14,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t},{\n\t\tname: DATA_NAME.HIGH,\n\t\tindex: 1\n\t},{\n\t\tname: DATA_NAME.LOW,\n\t\tindex: 2\n\t}],\n\t[{\n        name: \"tmp\",\n        visible: false\n    },{\n        name: \"atr\",\n        visible: true,\n        renderType: RENDER_TYPE.LINE,\n        color: \"steelblue\"\n    }],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/bands.js",
    "content": "registerIndicator(\n\"bands\",\n\"Bollinger Bands(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t    var dataOutput = getDataOutput(context, \"ma\")\n\t    var dataOutputUpper = getDataOutput(context, \"upper\")\n\t    var dataOutputLower = getDataOutput(context, \"lower\")\n\n\t    var method = getIndiParameter(context, \"method\")\n\t    var period = getIndiParameter(context, \"period\")\n\t    var deviations = getIndiParameter(context, \"deviations\")\n\t    var shift = getIndiParameter(context, \"shift\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    if (\"smma\" == method) {\n\t        smma(dataInput, dataOutput, calculatedLength, period)\n\t    } else if(\"ema\" == method) {\n\t        ema(dataInput, dataOutput, calculatedLength, period)\n\t    } else if (\"lwma\" == method) {\n\t        lwma(dataInput, dataOutput, calculatedLength, period)\n\t    } else {\n\t        sma(dataInput, dataOutput, calculatedLength, period)\n\t    }\n\n\t    var ptr = null\n\t    var ptr2 = null\n\n\t    if (calculatedLength > 0) {\n\t        ptr = calculatedLength - 1\n\t    } else {\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutputUpper[i] = 0\n\t            dataOutputLower[i] = 0\n\t        }\n\n\t\t\tptr = period - 1\n\t    }\n\n\t    var devVal, sum, midVal, tmp\n\n\t\twhile (ptr < dataInput.length) {\n\t\t\tsum = 0\n\t\t\tptr2 = ptr - period + 1\n\t\t\tmidVal = dataOutput[ptr]\n\t\t\twhile (ptr2 <= ptr) {\n\t\t\t\ttmp = dataInput[ptr2] - midVal\n\t\t\t\tsum += tmp * tmp\n\t\t\t\tptr2++\n\t\t\t}\n\t\t\tdevVal = deviations * Math.sqrt(sum / period)\n\t\t\tdataOutputUpper[ptr] = midVal + devVal\n\t\t\tdataOutputLower[ptr] = midVal - devVal\n\n\t\t\tptr++\n\t\t}\n\n\t    if (calculatedLength == 0) {\n\t        setIndiShift(context, \"ma\", shift)\n\t        setIndiShift(context, \"upper\", shift)\n\t        setIndiShift(context, \"lower\", shift)\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 5,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"deviations\",\n\tvalue: 2,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [0, 10]\n}, {\n\tname: \"shift\",\n\tvalue: 0,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [-30, 30]\n}, {\n\tname: \"method\",\n\tvalue: \"sma\",\n\trequired: true,\n\ttype: \"String\",\n\trange: null\n}], [{\n\tname: \"Close\",\n\tindex: 0\n}], [{\n\tname: \"ma\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"upper\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"lower\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"steelblue\"\n}],\n\"CHART_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/bears.js",
    "content": "registerIndicator(\n\"bears\",\n\"Bears Power(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t    var dataInputLow = getDataInput(context, 1)\n\t    var dataOutput = getDataOutput(context, \"bears\")\n\t    var dataOutputEma = getDataOutput(context, \"ema\")\n\t    var period = getIndiParameter(context, \"period\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period - 1\n\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutput[i] = 0\n\t        }\n\t    }\n\n\t    ema(dataInput, dataOutputEma, calculatedLength, period)\n\n\t    while (ptr < dataInput.length) {\n\t        dataOutput[ptr] = dataInputLow[ptr] - dataOutputEma[ptr]\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}], [{\n\tname: \"Close\",\n\tindex: 0\n}, {\n\tname: \"Low\",\n\tindex: 1\n}], [{\n\tname: \"bears\",\n\tvisible: true,\n\trenderType: \"Histogram\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"ema\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/bidask.js",
    "content": "registerIndicator(\n\"bidask\", \"Bid and Ask(v1.01)\", function (context) {\n\tvar dataInput = getDataInput(context, 0)\n\tif (dataInput.length == 0) return\n\tvar dataOutputBid = getDataOutput(context, \"bid\")\n\tvar dataOutputAsk = getDataOutput(context, \"ask\")\n\tvar spread = getIndiParameter(context, \"spread\")\n\n\tvar currPrice = dataInput[dataInput.length - 1]\n\tvar bid = currPrice - spread / 2\n\tvar ask = currPrice + spread / 2\n\tvar dataLen = dataInput.length\n\tvar barNum = typeof context.barNum == \"undefined\" ? dataInput.length : context.barNum\n\n\tfor (var i = dataLen - 1; i >= dataLen - 1 - barNum; i--) {\n\t\tdataOutputBid[i] = bid\n\t\tdataOutputAsk[i] = ask\n\t}\n},[{\n\tname: \"spread\",\n\tvalue: 0.0001,\n\trequired: true,\n\ttype: PARAMETER_TYPE.NUMBER,\n\trange: [0, 0.1]\n}],\n[{\n\tname: DATA_NAME.CLOSE,\n\tindex: 0\n}],\n[{\n\tname: \"bid\",\n\tvisible: true,\n\trenderType: RENDER_TYPE.DASHARRAY,\n\tcolor: \"red\"\n},{\n\tname: \"ask\",\n\tvisible: true,\n\trenderType: RENDER_TYPE.DASHARRAY,\n\tcolor: \"green\"\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init()\n},\nfunction (context) { // Deinit()\n},\nfunction (context) { // Render()\n  context.barNum = getBarNum(context)\n})\n"
  },
  {
    "path": "Indicators/Built-in/bulls.js",
    "content": "registerIndicator(\n\"bulls\",\n\"Bulls Power(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t    var dataInputHigh = getDataInput(context, 1)\n\t    var dataOutput = getDataOutput(context, \"bulls\")\n\t    var dataOutputEma = getDataOutput(context, \"ema\")\n\t    var period = getIndiParameter(context, \"period\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period - 1\n\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutput[i] = 0\n\t        }\n\t    }\n\n\t    ema(dataInput, dataOutputEma, calculatedLength, period)\n\n\t    while (ptr < dataInput.length) {\n\t        dataOutput[ptr] = dataInputHigh[ptr] - dataOutputEma[ptr]\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}], [{\n\tname: \"Close\",\n\tindex: 0\n}, {\n\tname: \"High\",\n\tindex: 1\n}], [{\n\tname: \"bulls\",\n\tvisible: true,\n\trenderType: \"Histogram\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"ema\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/cci.js",
    "content": "registerIndicator(\n\"cci\",\n\"Commodity Channel Index(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t    var dataOutput = getDataOutput(context, \"cci\")\n\t    var dataOutputHL = getDataOutput(context, \"cciHighLevel\")\n\t    var dataOutputLL = getDataOutput(context, \"cciLowLevel\")\n\t    var dataOutputSma = getDataOutput(context, \"sma\")\n\t    var highLevel = getIndiParameter(context, \"highLevel\")\n\t    var lowLevel = getIndiParameter(context, \"lowLevel\")\n\t    var period = getIndiParameter(context, \"period\")\n\t    var cciFactor = 0.015 / period;\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period - 1\n\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutput[i] = 0\n\t            dataOutputHL[i] = highLevel\n\t            dataOutputLL[i] = lowLevel\n\t        }\n\t    }\n\n\t    sma(dataInput, dataOutputSma, calculatedLength, period)\n\n\t    var sum, tmp, ptr2\n\n\t    while (ptr < dataInput.length) {\n\t        sum = 0\n\t\t\tptr2 = ptr - period + 1\n\t\t\twhile (ptr2 <= ptr) {\n\t\t\t\tsum += Math.abs(dataInput[ptr2] - dataOutputSma[ptr])\n\t\t\t\tptr2++\n\t\t\t}\n\t\t\ttmp = sum * cciFactor\n\n\t\t\tif (0 == tmp) {\n\t\t\t\tdataOutput[ptr] = 0\n\t\t\t} else {\n\t\t\t\tdataOutput[ptr] = (dataInput[ptr] - dataOutputSma[ptr]) / tmp\n\t\t\t}\n\n\t        dataOutputHL[ptr] = highLevel\n\t        dataOutputLL[ptr] = lowLevel\n\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"highLevel\",\n\tvalue: 100,\n\trequired: false,\n\ttype: \"Number\",\n\trange: [1, 200]\n}, {\n\tname: \"lowLevel\",\n\tvalue: -100,\n\trequired: false,\n\ttype: \"Number\",\n\trange: [-200, -1]\n}], [{\n\tname: \"HLC3\",\n\tindex: 0\n}], [{\n\tname: \"cci\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"cciHighLevel\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#AAAAAA\"\n}, {\n\tname: \"cciLowLevel\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#AAAAAA\"\n}, {\n\tname: \"sma\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/common.js",
    "content": "function getHighestOnArray (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (calculatedLength > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar highest = -Number.MAX_VALUE\n\n\tfor (var j = i - period + 1; j < i; j++) {\n\t\tif (dataInput[j] > highest) {\n\t\t\thighest = dataInput[j]\n\t\t}\n\t}\n\n\tfor (var j = i; j < dataInput.length; j++) {\n\t\tif (dataInput[j] > highest) {\n\t\t\thighest = dataInput[j]\n\t\t}\n\t\tdataOutput[j] = highest\n\t\tif (dataInput[j - period + 1] == highest) {\n\t\t\thighest = -Number.MAX_VALUE\n\n\t\t\tfor (var k = j - period + 1 + 1; k <= j; k++) {\n\t\t\t\tif (dataInput[k] > highest) {\n\t\t\t\t\thighest = dataInput[k]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction getLowestOnArray (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (calculatedLength > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar lowest = Number.MAX_VALUE\n\n\tfor (var j = i - period + 1; j < i; j++) {\n\t\tif (dataInput[j] < lowest) {\n\t\t\tlowest = dataInput[j]\n\t\t}\n\t}\n\n\tfor (var j = i; j < dataInput.length; j++) {\n\t\tif (dataInput[j] < lowest) {\n\t\t\tlowest = dataInput[j]\n\t\t}\n\t\tdataOutput[j] = lowest\n\t\tif (dataInput[j - period + 1] == lowest) {\n\t\t\tlowest = Number.MAX_VALUE\n\n\t\t\tfor (var k = j - period + 1 + 1; k <= j; k++) {\n\t\t\t\tif (dataInput[k] < lowest) {\n\t\t\t\t\tlowest = dataInput[k]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction sumOnArray (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (calculatedLength > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar sum = 0\n\n\tfor (var j = i - period + 1; j < i; j++) {\n\t\tsum += dataInput[j]\n\t}\n\n\tfor (var j = i; j < dataInput.length; j++) {\n\t\tsum += dataInput[j]\n\t\tdataOutput[j] = sum\n\t\tsum -= dataInput[j - period + 1]\n\t}\n}\n\nfunction sma (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (calculatedLength > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar sum = 0\n\n\tfor (var j = i - period + 1; j < i; j++) {\n\t\tsum += dataInput[j]\n\t}\n\n\tfor (var j = i; j < dataInput.length; j++) {\n\t\tsum += dataInput[j]\n\t\tdataOutput[j] = sum / period\n\t\tsum -= dataInput[j - period + 1]\n\t}\n}\n\nfunction ema (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\tvar smthFctr = 2.0 / (period + 1)\n\n\tif (i == 0) {\n\t\tdataOutput[0] = dataInput[0]\n\t\ti++\n\t} else if (i == 1) {\n\t} else {\n\t\ti--\n\t}\n\n\twhile (i < dataInput.length) {\n\t\tdataOutput[i] = dataInput[i] * smthFctr + dataOutput[i - 1] * (1 - smthFctr)\n\t\ti++\n\t}\n}\n\nfunction smma (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\tvar sum = 0\n\n\tif (i > 0) {\n\t\ti--\n\t} else {\n\t\ti = period - 1\n\n\t\tfor (var j = 1; j < period; j++) {\n\t\t\tdataOutput[i - j] = 0\n\t\t\tsum += dataInput[i - j]\n\t\t}\n\n\t\tsum += dataInput[i]\n\t\tdataOutput[i] = sum / period\n\t\ti++\n\t}\n\n\twhile (i < dataInput.length) {\n\t\tsum = dataOutput[i - 1] * period - dataOutput[i - 1] + dataInput[i]\n\t\tdataOutput[i] = sum / period\n\t\ti++\n\t}\n}\n\nfunction lwma (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (i > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar sum = 0\n\tvar diffsum = 0\n\tvar weight = 0\n\n\tfor (var j = 1; j < period; j++) {\n\t\tsum += dataInput[i - j] * (period - j)\n\t\tdiffsum += dataInput[i - j]\n\t\tweight += j\n\t}\n\tweight += period\n\n\twhile (i < dataInput.length) {\n\t\tsum += dataInput[i] * period\n\t\tdataOutput[i] = sum / weight\n\t\tdiffsum += dataInput[i]\n\t\tsum -= diffsum\n\t\tdiffsum -= dataInput[i - period + 1]\n\t\ti++\n\t}\n}\n"
  },
  {
    "path": "Indicators/Built-in/demarker.js",
    "content": "registerIndicator(\n\"demarker\",\n\"DeMarker(v1.0)\",\nfunction (context) {\n\t    var dataInputHigh = getDataInput(context, 0)\n\t    var dataInputLow = getDataInput(context, 1)\n\t    var dataOutput = getDataOutput(context, \"demarker\")\n\t    var dataOutputHL = getDataOutput(context, \"highLevel\")\n\t    var dataOutputLL = getDataOutput(context, \"lowLevel\")\n\t    var dataOutputMax = getDataOutput(context, \"max\")\n\t    var dataOutputMin = getDataOutput(context, \"min\")\n\t    var dataOutputMaMax = getDataOutput(context, \"maMax\")\n\t    var dataOutputMaMin = getDataOutput(context, \"maMin\")\n\t    var highLevel = getIndiParameter(context, \"highLevel\")\n\t    var lowLevel = getIndiParameter(context, \"lowLevel\")\n\t    var period = getIndiParameter(context, \"period\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = 1\n\n\t        dataOutputMax[0] = 0;\n\t\t\tdataOutputMin[0] = 0;\n\t    }\n\n\t    var tmp = 0\n\n\t    while (ptr < dataInputHigh.length) {\n\t\t\ttmp = dataInputHigh[ptr] - dataInputHigh[ptr - 1]\n\t\t\tif (0 > tmp) {\n\t\t\t\ttmp = 0\n\t\t\t}\n\t\t\tdataOutputMax[ptr] = tmp\n\n\t\t\ttmp = dataInputLow[ptr - 1] - dataInputLow[ptr]\n\t\t\tif (0 > tmp) {\n\t\t\t\ttmp = 0\n\t\t\t}\n\t\t\tdataOutputMin[ptr] = tmp\n\n\t\t\tptr++\n\t\t}\n\n\t    sma(dataOutputMax, dataOutputMaMax, calculatedLength, period)\n\t    sma(dataOutputMin, dataOutputMaMin, calculatedLength, period)\n\n\t    ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period - 1\n\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutput[i] = 0\n\t            dataOutputHL[i] = highLevel\n\t            dataOutputLL[i] = lowLevel\n\t        }\n\t    }\n\n\t    while (ptr < dataInputHigh.length) {\n\t        tmp = dataOutputMaMax[ptr] + dataOutputMaMin[ptr]\n\n\t\t\tif (0 == tmp) {\n\t\t\t\tdataOutput[ptr] = 0\n\t\t\t} else {\n\t\t\t\tdataOutput[ptr] = dataOutputMaMax[ptr] / tmp\n\t\t\t}\n\n\t        dataOutputHL[ptr] = highLevel\n\t        dataOutputLL[ptr] = lowLevel\n\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"highLevel\",\n\tvalue: 0.7,\n\trequired: false,\n\ttype: \"Number\",\n\trange: [0, 1]\n}, {\n\tname: \"lowLevel\",\n\tvalue: 0.3,\n\trequired: false,\n\ttype: \"Number\",\n\trange: [0, 1]\n}], [{\n\tname: \"High\",\n\tindex: 0\n}, {\n\tname: \"Low\",\n\tindex: 1\n}], [{\n\tname: \"demarker\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"highLevel\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#AAAAAA\"\n}, {\n\tname: \"lowLevel\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#AAAAAA\"\n}, {\n\tname: \"max\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"min\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"maMax\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"maMin\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/ema.js",
    "content": "registerIndicator(\n    \"ema\", \"Exponential moving average(v1.0)\", function (context) {\n        var dataInput = getDataInput(context, 0)\n\t\tvar dataOutput = getDataOutput(context, \"ema\")\n\t\tvar period = getIndiParameter(context, \"period\")\n\t\tvar shift = getIndiParameter(context, \"shift\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tema(dataInput, dataOutput, calculatedLength, period)\n\n\t\tif (shift != null && calculatedLength == 0) {\n\t\t\tsetIndiShift(context, \"ema\", shift)\n\t\t}\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"shift\",\n\t\tvalue: 0,\n\t\trequired: false,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"ema\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"steelblue\"\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/envelopes.js",
    "content": "registerIndicator(\n\"envelopes\",\n\"Envelopes(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t    var dataOutput = getDataOutput(context, \"ma\")\n\t    var dataOutputUpper = getDataOutput(context, \"upper\")\n\t    var dataOutputLower = getDataOutput(context, \"lower\")\n\n\t    var method = getIndiParameter(context, \"method\")\n\t    var period = getIndiParameter(context, \"period\")\n\t    var deviations = getIndiParameter(context, \"deviations\")\n\t    var shift = getIndiParameter(context, \"shift\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    if (\"smma\" == method) {\n\t        smma(dataInput, dataOutput, calculatedLength, period)\n\t    } else if(\"ema\" == method) {\n\t        ema(dataInput, dataOutput, calculatedLength, period)\n\t    } else if (\"lwma\" == method) {\n\t        lwma(dataInput, dataOutput, calculatedLength, period)\n\t    } else {\n\t        sma(dataInput, dataOutput, calculatedLength, period)\n\t    }\n\n\t    var ptr = null\n\n\t    if (calculatedLength > 0) {\n\t        ptr = calculatedLength - 1\n\t    } else {\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutputUpper[i] = 0\n\t            dataOutputLower[i] = 0\n\t        }\n\n\t        ptr = period - 1\n\t    }\n\n\t    while (ptr < dataInput.length) {\n\t        dataOutputUpper[ptr] = (1 + deviations / 100) * dataOutput[ptr]\n\t\t\tdataOutputLower[ptr] = (1 - deviations / 100) * dataOutput[ptr]\n\n\t        ptr++\n\t    }\n\n\t    if (calculatedLength == 0) {\n\t        setIndiShift(context, \"ma\", shift)\n\t        setIndiShift(context, \"upper\", shift)\n\t        setIndiShift(context, \"lower\", shift)\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 5,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"deviations\",\n\tvalue: 0.05,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [0, 10]\n}, {\n\tname: \"shift\",\n\tvalue: 0,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [-30, 30]\n}, {\n\tname: \"method\",\n\tvalue: \"sma\",\n\trequired: true,\n\ttype: \"String\",\n\trange: null\n}], [{\n\tname: \"Close\",\n\tindex: 0\n}], [{\n\tname: \"ma\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"upper\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"lower\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"steelblue\"\n}],\n\"CHART_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/fractals.js",
    "content": "registerIndicator(\n\"fractals\",\n\"Fractals(v1.02)\",\nfunction (context) {\n\t    var dataInputHigh = getDataInput(context, 0)\n\t    var dataInputLow = getDataInput(context, 1)\n\t    var dataOutputUp = getDataOutput(context, \"fractalsUp\")\n\t    var dataOutputDown = getDataOutput(context, \"fractalsDown\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = null\n\n\t    if (calculatedLength > 0) {\n\t        ptr = calculatedLength - 3\n\t    } else {\n\t        for (var i = 0; i < dataInputHigh.length; i++) {\n\t            dataOutputUp[i] = 0\n\t            dataOutputDown[i] = 0\n\t        }\n\n\t        ptr = 2\n\t    }\n\n\t    var bHFound = false\n\t\t\tvar bLFound = false\n\t    var highest = null\n\t    var lowest = null\n\n\t    while (ptr < dataInputHigh.length - 2) {\n\t        bHFound = false\n\t        highest = dataInputHigh[ptr]\n\n\t        if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {\n\t            bHFound = true\n\t            dataOutputUp[ptr] = highest\n\t        }\n\n\t        bLFound = false\n\t        lowest = dataInputLow[ptr]\n\n\t        if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {\n\t            bLFound = true\n\t            dataOutputDown[ptr] = lowest\n\t        }\n\n\t        ptr++\n\t    }\n\n\t\t\tif (!bHFound) {\n\t\t\t\tdataOutputUp[dataInputHigh.length - 3] = 0\n\t\t\t}\n\t\t\tif (!bLFound) {\n\t\t\t\tdataOutputDown[dataInputLow.length - 3] = 0\n\t\t\t}\n\t},[],\n\t[{\n\t    name: DATA_NAME.HIGH,\n\t    index: 0\n\t},{\n\t    name: DATA_NAME.LOW,\n\t    index: 1\n\t}],\n\t[{\n\t    name: \"fractalsUp\",\n\t    visible: true,\n\t    renderType: RENDER_TYPE.ROUND,\n\t    color: \"green\"\n\t},{\n\t    name: \"fractalsDown\",\n\t    visible: true,\n\t    renderType: RENDER_TYPE.ROUND,\n\t    color: \"red\"\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/heikin-ashi.js",
    "content": "registerIndicator(\"heikin-ashi\", \"Heikin-Ashi(v1.01)\", function (context) {\n  var dataInputO = getDataInput(context, 0)\n  var dataInputH = getDataInput(context, 1)\n  var dataInputL = getDataInput(context, 2)\n  var dataInputC = getDataInput(context, 3)\n  var dataOutputO = getDataOutput(context, \"ha_open\")\n  var dataOutputH = getDataOutput(context, \"ha_high\")\n  var dataOutputL = getDataOutput(context, \"ha_low\")\n  var dataOutputC = getDataOutput(context, \"ha_close\")\n\n  var calculatedLength = getCalculatedLength(context)\n\n  var i = calculatedLength\n\n  if (i > 0) {\n    i--\n  } else {\n    dataOutputC[i] = (dataInputO[i] + dataInputH[i] + dataInputL[i] + dataInputC[i]) / 4\n    dataOutputO[i] = (dataInputO[i] + dataInputC[i]) / 2\n    dataOutputH[i] = Math.max(dataInputH[i], dataOutputO[i], dataOutputC[i])\n    dataOutputL[i] = Math.max(dataInputL[i], dataOutputO[i], dataOutputC[i])\n    i = 1\n  }\n\n  while (i < dataInputC.length) {\n    dataOutputC[i] = (dataInputO[i] + dataInputH[i] + dataInputL[i] + dataInputC[i]) / 4\n    dataOutputO[i] = (dataOutputO[i - 1] + dataOutputC[i - 1]) / 2\n    dataOutputH[i] = Math.max(dataInputH[i], dataOutputO[i], dataOutputC[i])\n    dataOutputL[i] = Math.max(dataInputL[i], dataOutputO[i], dataOutputC[i])\n\n    i++\n  }\n},[{\n  name: \"colorLong\",\n  value: \"green\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}, {\n  name: \"colorShort\",\n  value: \"red\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}],\n[{\n\tname: DATA_NAME.OPEN,\n\tindex: 0\n}, {\n\tname: DATA_NAME.HIGH,\n\tindex: 1\n}, {\n\tname: DATA_NAME.LOW,\n\tindex: 2\n}, {\n\tname: DATA_NAME.CLOSE,\n\tindex: 3\n}],\n[{\n  name: \"ha_open\",\n  visible: false\n}, {\n  name: \"ha_high\",\n  visible: false\n}, {\n  name: \"ha_low\",\n  visible: false\n}, {\n  name: \"ha_close\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init()\n  var colorLong = getIndiParameter(context, \"colorLong\")\n  var colorShort = getIndiParameter(context, \"colorShort\")\n  var chartHandle = getChartHandleByContext(context)\n\n  context.heikinAshi = {\n    colorLong: colorLong,\n    colorShort: colorShort,\n    canvas: getSvgCanvas(chartHandle)\n  }\n},\nfunction (context) { // Deinit()\n  var chartHandle = getChartHandleByContext(context)\n  var canvas = context.heikinAshi.canvas\n\n  canvas.selectAll(\".haHL\").select(function() { return this.parentNode; }).select(function() { return this.parentNode; }).each(function (d, i) {\n    if (i == 0) {\n      d3.select(this).selectAll(\".cc_k_c_oc\").attr(\"opacity\", 1)\n      d3.select(this).selectAll(\".cc_k_c_hl\").attr(\"opacity\", 1)\n    }\n  })\n\tcanvas.selectAll(\".haHL\").data([]).exit().remove()\n  canvas.selectAll(\".haOC\").data([]).exit().remove()\n},\nfunction (context) { // Render()\n  var dataOutputO = getDataOutput(context, \"ha_open\")\n  var dataOutputH = getDataOutput(context, \"ha_high\")\n  var dataOutputL = getDataOutput(context, \"ha_low\")\n  var dataOutputC = getDataOutput(context, \"ha_close\")\n  var barNum = getBarNum(context)\n  var cursor = getCursor(context)\n  var width = getCanvasWidth(context)\n  var height = getCanvasHeight(context)\n  var xScale = getXScale(context)\n  var yScale = getYScale(context)\n\n  var ha = []\n  var cursor2 = Math.min(cursor + barNum, dataOutputC.length)\n\n  for (var i = cursor; i < cursor2; i++) {\n    ha.push({\n      o: dataOutputO[i],\n      h: dataOutputH[i],\n      l: dataOutputL[i],\n      c: dataOutputC[i]\n    })\n  }\n\n  var colorLong = context.heikinAshi.colorLong\n  var colorShort = context.heikinAshi.colorShort\n\tvar canvas = context.heikinAshi.canvas\n\n  var haHL = canvas.selectAll(\".haHL\").data(ha)\n\n  haHL.attr(\"x1\", function (d, i) {\n      return xScale(i)\n    })\n    .attr(\"x2\", function (d, i) {\n      return xScale(i)\n    })\n    .attr(\"y1\", function (d) {\n      return yScale(d.h)\n    })\n    .attr(\"y2\", function (d) {\n      return yScale(d.l)\n    })\n    .attr(\"stroke\", function (d) {\n      return d.o > d.c ? colorShort : colorLong\n    })\n\n  haHL.enter().append(\"line\")\n    .attr(\"class\", \"haHL\")\n    .attr(\"x1\", function (d, i) {\n      return xScale(i)\n    })\n    .attr(\"x2\", function (d, i) {\n      return xScale(i)\n    })\n    .attr(\"y1\", function (d) {\n      return yScale(d.h)\n    })\n    .attr(\"y2\", function (d) {\n      return yScale(d.l)\n    })\n    .attr(\"stroke\", function (d) {\n      return d.o > d.c ? colorShort : colorLong\n    })\n\n  haHL.exit().remove()\n\n  var barWidth = Math.floor(0.8 * width / barNum)\n  var halfWidth = barWidth / 2\n\n  var haOC = canvas.selectAll(\".haOC\").data(ha)\n\n  haOC.attr(\"x\", function (d, i) {\n      return xScale(i) - halfWidth\n    })\n    .attr(\"y\", function (d) {\n      return yScale(Math.max(d.o, d.c))\n    })\n    .attr(\"width\", barWidth)\n    .attr(\"height\", function (d) {\n      return d.o == d.c ? 1 :\n        (yScale(Math.min(d.o, d.c)) - yScale(Math.max(d.o, d.c)))\n    })\n    .attr(\"fill\", function (d) {\n      if (d.o == d.c)\n        return \"black\"\n      else\n        return d.o > d.c ? colorShort : colorLong\n    })\n    .attr(\"stroke\", function (d) {\n      if (d.o == d.c)\n        return \"black\"\n      else\n        return d.o > d.c ? colorShort : colorLong\n    })\n\n  haOC.enter().append(\"rect\")\n    .attr(\"class\", \"haOC\")\n    .attr(\"x\", function (d, i) {\n      return xScale(i) - halfWidth\n    })\n    .attr(\"y\", function (d) {\n      return yScale(Math.max(d.o, d.c))\n    })\n    .attr(\"width\", barWidth)\n    .attr(\"height\", function (d) {\n      return d.o == d.c ? 1 :\n        (yScale(Math.min(d.o, d.c)) - yScale(Math.max(d.o, d.c)))\n    })\n    .attr(\"fill\", function (d) {\n      if (d.o == d.c)\n        return \"black\"\n      else\n        return d.o > d.c ? colorShort : colorLong\n    })\n    .attr(\"stroke\", function (d) {\n      if (d.o == d.c)\n        return \"black\"\n      else\n        return d.o > d.c ? colorShort : colorLong\n    })\n    .attr(\"strokeWidth\", 2)\n\n  haOC.exit().remove()\n\n  canvas.selectAll(\".haHL\").select(function() { return this.parentNode; }).select(function() { return this.parentNode; }).each(function (d, i) {\n    if (i == 0) {\n      d3.select(this).selectAll(\".cc_k_c_oc\").attr(\"opacity\", 0)\n      d3.select(this).selectAll(\".cc_k_c_hl\").attr(\"opacity\", 0)\n    }\n  })\n})\n"
  },
  {
    "path": "Indicators/Built-in/ichimoku.js",
    "content": "registerIndicator(\n\"ichimoku\",\n\"Ichimoku Kinko Hyo(v1.0)\",\nfunction (context) {\n\t    var dataInputHigh = getDataInput(context, 0)\n\t    var dataInputLow = getDataInput(context, 1)\n\t    var dataInputClose = getDataInput(context, 2)\n\t    var dataOutputTenkan = getDataOutput(context, \"tenkan\")\n\t    var dataOutputKijun = getDataOutput(context, \"kijun\")\n\t    var dataOutputChikou = getDataOutput(context, \"chikou\")\n\t    var dataOutputSpanA = getDataOutput(context, \"spana\")\n\t    var dataOutputSpanB = getDataOutput(context, \"spanb\")\n\n\t    var tenkan = getIndiParameter(context, \"tenkan\")\n\t    var kijun = getIndiParameter(context, \"kijun\")\n\t    var senkou = getIndiParameter(context, \"senkou\")\n\t\tvar spanA;\n\t\tif (kijun < tenkan) {\n\t\t\tspanA = tenkan;\n\t\t}else{\n\t\t\tspanA = kijun;\n\t\t}\n\n\t    var calculatedLength = getCalculatedLength(context)\n\t    var ptr = calculatedLength\n\t    var maxParam = Math.max(tenkan, kijun, spanA, senkou)\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = maxParam - 1\n\n\t        for (var i = 1; i < maxParam; i++) {\n\t\t\t\tdataOutputTenkan[ptr - i] = 0\n\t\t\t\tdataOutputKijun[ptr - i] = 0\n\t\t\t\tdataOutputChikou[ptr - i] = 0\n\t\t\t\tdataOutputSpanA[ptr - i] = 0\n\t\t\t\tdataOutputSpanB[ptr - i] = 0\n\t\t\t}\n\t    }\n\n\t\tvar ptr2, tmp, highest, lowest\n\n\t\twhile (ptr < dataInputHigh.length) {\n\t        tmp = null\n\t        highest = -Number.MAX_VALUE\n\t        lowest = Number.MAX_VALUE\n\n\t\t\tptr2 = ptr - tenkan + 1\n\n\t\t\twhile (ptr2 <= ptr) {\n\t\t\t\ttmp = dataInputHigh[ptr2]\n\t\t\t\tif (highest < tmp) {\n\t\t\t\t\thighest = tmp\n\t\t\t\t}\n\n\t\t\t\ttmp = dataInputLow[ptr2]\n\t\t\t\tif (lowest > tmp) {\n\t\t\t\t\tlowest = tmp\n\t\t\t\t}\n\n\t\t\t\tptr2++\n\t\t\t}\n\n\t\t\tdataOutputTenkan[ptr] = (highest + lowest) / 2\n\n\t        tmp = null\n\t        highest = -Number.MAX_VALUE\n\t        lowest = Number.MAX_VALUE\n\n\t\t\tptr2 = ptr - kijun + 1\n\n\t\t\twhile (ptr2 <= ptr) {\n\t            tmp = dataInputHigh[ptr2]\n\t\t\t\tif (highest < tmp) {\n\t\t\t\t\thighest = tmp\n\t\t\t\t}\n\n\t\t\t\ttmp = dataInputLow[ptr2]\n\t\t\t\tif (lowest > tmp) {\n\t\t\t\t\tlowest = tmp\n\t\t\t\t}\n\n\t\t\t\tptr2++\n\t\t\t}\n\n\t\t\tdataOutputKijun[ptr] = (highest + lowest) / 2\n\n\t\t\tdataOutputSpanA[ptr] = (dataOutputTenkan[ptr] + dataOutputKijun[ptr]) / 2\n\n\t        tmp = null\n\t        highest = -Number.MAX_VALUE\n\t        lowest = Number.MAX_VALUE\n\n\t\t\tptr2 = ptr - senkou + 1\n\n\t        while (ptr2 <= ptr) {\n\t            tmp = dataInputHigh[ptr2]\n\t\t\t\tif (highest < tmp) {\n\t\t\t\t\thighest = tmp\n\t\t\t\t}\n\n\t\t\t\ttmp = dataInputLow[ptr2]\n\t\t\t\tif (lowest > tmp) {\n\t\t\t\t\tlowest = tmp\n\t\t\t\t}\n\n\t\t\t\tptr2++\n\t\t\t}\n\n\t\t\tdataOutputSpanB[ptr] = (highest + lowest) / 2\n\n\t\t\tdataOutputChikou[ptr] = dataInputClose[ptr]\n\n\t\t\tptr++\n\t\t}\n\n\t    if (calculatedLength == 0) {\n\t        setIndiShift(context, \"chikou\", -kijun)\n\t        setIndiShift(context, \"spana\", kijun)\n\t        setIndiShift(context, \"spanb\", kijun)\n\t    }\n\t},\n[{\n\tname: \"tenkan\",\n\tvalue: 9,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"kijun\",\n\tvalue: 26,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"senkou\",\n\tvalue: 52,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}], [{\n\tname: \"High\",\n\tindex: 0\n}, {\n\tname: \"Low\",\n\tindex: 1\n}, {\n\tname: \"Close\",\n\tindex: 2\n}], [{\n\tname: \"tenkan\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"#DE5029\"\n}, {\n\tname: \"kijun\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"chikou\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#4EC2B4\"\n}, {\n\tname: \"spana\",\n\tvisible: true,\n\trenderType: \"Round\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"spanb\",\n\tvisible: true,\n\trenderType: \"Round\",\n\tcolor: \"#CCCCCC\"\n}],\n\"CHART_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/lwma.js",
    "content": "registerIndicator(\n    \"lwma\", \"Linear weighted moving average(v1.0)\", function (context) {\n        var dataInput = getDataInput(context, 0)\n\t\tvar dataOutput = getDataOutput(context, \"lwma\")\n\t\tvar period = getIndiParameter(context, \"period\")\n\t\tvar shift = getIndiParameter(context, \"shift\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tlwma(dataInput, dataOutput, calculatedLength, period)\n\n\t\tif (shift != null && calculatedLength == 0) {\n\t\t\tsetIndiShift(context, \"lwma\", shift)\n\t\t}\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"shift\",\n\t\tvalue: 0,\n\t\trequired: false,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"lwma\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"steelblue\"\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/macd.js",
    "content": "registerIndicator(\n    \"macd\", \"MACD(v1.01)\", function (context) {\n        var dataInput = getDataInput(context, 0)\n\t\tvar dataFEMA = getDataOutput(context, \"fastEMA\")\n\t\tvar dataSEMA = getDataOutput(context, \"slowEMA\")\n\t\tvar dataOutputMain = getDataOutput(context, \"main\")\n\t\tvar dataOutputSignal = getDataOutput(context, \"signal\")\n\n\t\tvar fEMA = getIndiParameter(context, \"fastEMA\")\n\t\tvar sEMA = getIndiParameter(context, \"slowEMA\")\n\t\tvar sgnlSMA = getIndiParameter(context, \"signalSMA\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\n\t\tif (i == 0) {\n\t\t\tdataFEMA[0] = dataInput[0]\n\t\t\tdataSEMA[0] = dataInput[0]\n\t\t\tdataOutputMain[0] = 0\n\t\t\ti++\n\t\t} else if (i == 1) {\n\t\t} else {\n\t\t\ti--\n\t\t}\n\n\t\tema(dataInput, dataFEMA, calculatedLength, fEMA)\n\t\tema(dataInput, dataSEMA, calculatedLength, sEMA)\n\n\t\twhile (i < dataInput.length) {\n\t\t\tdataOutputMain[i] = dataFEMA[i] - dataSEMA[i]\n\t\t\ti++\n\t\t}\n\n\t\tsma(dataOutputMain, dataOutputSignal, calculatedLength, sgnlSMA)\n\t},[{\n\t\tname: \"fastEMA\",\n\t\tvalue: 12,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"slowEMA\",\n\t\tvalue: 26,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"signalSMA\",\n\t\tvalue: 9,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"fastEMA\",\n\t\tvisible: false\n\t},{\n\t\tname: \"slowEMA\",\n\t\tvisible: false\n\t},{\n        name: \"main\",\n        visible: true,\n        renderType: RENDER_TYPE.HISTOGRAM,\n        color: \"#4EC2B4\"\n    },{\n        name: \"signal\",\n        visible: true,\n        renderType: RENDER_TYPE.LINE,\n        color: \"#CCCCCC\"\n    }],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/mfi.js",
    "content": "registerIndicator(\"mfi\", \"Market Facilitation Index(v1.01)\", function (context) {\n\t\tvar dataInputHigh = getDataInput(context, 0)\n\t\tvar dataInputLow = getDataInput(context, 1)\n\t\tvar dataInputVol = getDataInput(context, 2)\n\t\tvar dataOutput = getDataOutput(context, \"mfi\")\n\t\tvar dataOutputH = getDataOutput(context, \"highestTmp\")\n\t\tvar dataOutputL = getDataOutput(context, \"lowestTmp\")\n\t\tvar dataOutputV = getDataOutput(context, \"volSumTmp\")\n\t\tvar period = getIndiParameter(context, \"period\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tgetHighestOnArray(dataInputHigh, dataOutputH, calculatedLength, period)\n\t\tgetLowestOnArray(dataInputLow, dataOutputL, calculatedLength, period)\n\t\tsumOnArray(dataInputVol, dataOutputV, calculatedLength, period)\n\n\t\tvar i = calculatedLength\n\n\t\tif (i != 0) {\n\t\t\ti--\n\t\t}\n\n\t\twhile (i < dataInputVol.length) {\n\t\t\tif (dataOutputV[i] == 0) {\n\t\t\t\tdataOutput[i] = 0\n\t\t\t} else {\n\t\t\t\tdataOutput[i] = (dataOutputH[i] - dataOutputL[i]) / dataOutputV[i]\n\t\t\t}\n\n\t\t\ti++\n\t\t}\n\t},[{\n    name: \"period\",\n    value: 1,\n    required: false,\n    type: PARAMETER_TYPE.INTEGER,\n    range: [1, 100]\n\t}],\n\t[{\n    name: DATA_NAME.HIGH,\n    index: 0\n\t},{\n    name: DATA_NAME.LOW,\n    index: 1\n\t},{\n\t\tname: DATA_NAME.VOLUME,\n\t\tindex: 2\n\t}],\n\t[{\n\t\tname: \"mfi\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.HISTOGRAM,\n\t\tcolor: \"steelblue\"\n\t},{\n\t\tname: \"highestTmp\",\n\t\tvisible: false\n\t},{\n\t\tname: \"lowestTmp\",\n\t\tvisible: false\n\t},{\n\t\tname: \"volSumTmp\",\n\t\tvisible: false\n\t}],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/momentum.js",
    "content": "registerIndicator(\n\"momentum\",\n\"Momentum(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t    var dataOutput = getDataOutput(context, \"momentum\")\n\t    var period = getIndiParameter(context, \"period\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period - 1\n\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutput[i] = 0\n\t        }\n\t    }\n\n\t    while (ptr < dataInput.length) {\n\t        dataOutput[ptr] = dataInput[ptr] * 100 / dataInput[ptr - period]\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}], [{\n\tname: \"Close\",\n\tindex: 0\n}], [{\n\tname: \"momentum\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/rsi.js",
    "content": "registerIndicator(\n    \"rsi\", \"Relative strength index(v1.01)\", function (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tvar dataOutput = getDataOutput(context, \"rsi\")\n\t\tvar dataOutputHL = getDataOutput(context, \"rsiHighLevel\")\n\t\tvar dataOutputLL = getDataOutput(context, \"rsiLowLevel\")\n\t\tvar gainTmp = getDataOutput(context, \"gainTmp\")\n\t\tvar lossTmp = getDataOutput(context, \"lossTmp\")\n\n\t\tvar period = getIndiParameter(context, \"period\")\n\t\tvar highLevel = getIndiParameter(context, \"highLevel\")\n\t\tvar lowLevel = getIndiParameter(context, \"lowLevel\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tvar ptr = null\n\t\tvar ptr2 = null\n\n\t\tvar diff = null\n\t\tvar gain = null\n\t\tvar loss = null\n\t\tvar gainSum = 0\n\t\tvar lossSum = 0\n\n\t\tif (calculatedLength > 0) {\n\t\t\tptr = calculatedLength - 1\n\t\t\tptr2 = calculatedLength - period\n\t\t} else {\n\t\t\tfor (var i = 0; i < period; i++) {\n\t\t\t\tdataOutput[i] = 0\n\t\t\t\tdataOutputHL[i] = highLevel\n\t\t\t\tdataOutputLL[i] = lowLevel\n\t\t\t}\n\n\t\t\tptr = period\n\t\t\tptr2 = 1\n\n\t\t\twhile (ptr2 <= ptr) {\n\t\t\t\tdiff = dataInput[ptr2] - dataInput[ptr2 - 1]\n\t\t\t\tif (0 < diff) {\n\t\t\t\t\tgainSum += diff\n\t\t\t\t} else {\n\t\t\t\t\tlossSum -= diff\n\t\t\t\t}\n\t\t\t\tptr2++\n\t\t\t}\n\t\t\tgain = gainSum / period\n\t\t\tloss = lossSum / period\n\t\t\tif (0 == (gain + loss)) {\n\t\t\t\tdataOutput[ptr] = 0\n\t\t\t} else {\n\t\t\t\tdataOutput[ptr] = 100 * gain / (gain + loss)\n\t\t\t}\n\t\t\tdataOutputHL[ptr] = highLevel\n\t\t\tdataOutputLL[ptr] = lowLevel\n\t\t\tgainTmp[ptr] = gain\n\t\t\tlossTmp[ptr] = loss\n\t\t\tptr++\n\t\t}\n\n\t\twhile (ptr < dataInput.length) {\n\t\t\tgain = gainTmp[ptr - 1] * (period - 1)\n\t\t\tloss = lossTmp[ptr - 1] * (period - 1)\n\n\t\t\tdiff = dataInput[ptr] - dataInput[ptr - 1]\n\t\t\tif (0 < diff) {\n\t\t\t\tgain += diff\n\t\t\t} else {\n\t\t\t\tloss -= diff\n\t\t\t}\n\t\t\tgain = gain / period\n\t\t\tloss = loss / period\n\n\t\t\tif (0 == (gain + loss)) {\n\t\t\t\tdataOutput[ptr] = 0\n\t\t\t} else {\n\t\t\t\tdataOutput[ptr] = 100 * gain / (gain + loss)\n\t\t\t}\n\t\t\tdataOutputHL[ptr] = highLevel\n\t\t\tdataOutputLL[ptr] = lowLevel\n\t\t\tgainTmp[ptr] = gain\n\t\t\tlossTmp[ptr] = loss\n\t\t\tptr++\n\t\t}\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 14,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"highLevel\",\n\t\tvalue: 70,\n\t\trequired: false,\n\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"lowLevel\",\n\t\tvalue: 30,\n\t\trequired: false,\n\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\trange: [1, 100]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"rsi\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"steelblue\"\n\t},{\n\t\tname: \"rsiHighLevel\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.DASHARRAY,\n\t\tcolor: \"#AAAAAA\"\n\t},{\n\t\tname: \"rsiLowLevel\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.DASHARRAY,\n\t\tcolor: \"#AAAAAA\"\n\t},{\n        name: \"gainTmp\",\n        visible: false\n    },{\n        name: \"lossTmp\",\n        visible: false\n    }],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/rvi.js",
    "content": "registerIndicator(\n\"rvi\",\n\"Relative Vigor Index(v1.0)\",\nfunction (context) {\n\t    var dataInputOpen = getDataInput(context, 0)\n\t    var dataInputHigh = getDataInput(context, 1)\n\t    var dataInputLow = getDataInput(context, 2)\n\t    var dataInputClose = getDataInput(context, 3)\n\t    var dataOutputMain = getDataOutput(context, \"main\")\n\t    var dataOutputSignal = getDataOutput(context, \"signal\")\n\t    var period = getIndiParameter(context, \"period\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period + 2\n\n\t        for (var i = 0; i < period + 2; i++) {\n\t            dataOutputMain[i] = 0\n\t            dataOutputSignal[i] = 0\n\t        }\n\t    }\n\n\t    var upTmp, downTmp, tmp, dTmp\n\n\t    while (ptr < dataInputOpen.length) {\n\t        tmp = 0\n\t\t\tdTmp = 0\n\n\t\t\tfor (var i = ptr; i > ptr - period; i--) {\n\t\t\t\tupTmp = ((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\n\t\t\t\tdownTmp = ((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\n\n\t\t\t\ttmp += upTmp\n\t\t\t\tdTmp += downTmp\n\t\t\t}\n\n\t\t\tif (0 == dTmp) {\n\t\t\t\tdataOutputMain[ptr] = tmp\n\t\t\t} else {\n\t\t\t\tdataOutputMain[ptr] = tmp / dTmp\n\t\t\t}\n\n\t        ptr++\n\t    }\n\n\t    ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period + 2\n\t    }\n\n\t    while (ptr < dataInputOpen.length) {\n\t        dataOutputSignal[ptr] = (dataOutputMain[ptr] + 2 * dataOutputMain[ptr - 1] + 2 * dataOutputMain[ptr - 2] + dataOutputMain[ptr - 3]) / 6\n\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}], [{\n\tname: \"Open\",\n\tindex: 0\n}, {\n\tname: \"High\",\n\tindex: 1\n}, {\n\tname: \"Low\",\n\tindex: 2\n}, {\n\tname: \"Close\",\n\tindex: 3\n}], [{\n\tname: \"main\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"#6CBA81\"\n}, {\n\tname: \"signal\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"#ECAE93\"\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/sar.js",
    "content": "registerIndicator(\n\"sar\",\n\"Parabolic SAR(v1.01)\",\nfunction (context) {\n\t\tvar dataInputHigh = getDataInput(context, 0)\n\t\tvar dataInputLow = getDataInput(context, 1)\n\n\t\tvar dataOutput = getDataOutput(context, \"sar\")\n\t\tvar dataOutputIsLong = getDataOutput(context, \"isLong\")\n\t\tvar dataOutputAf = getDataOutput(context, \"af\")\n\t\tvar dataOutputEp = getDataOutput(context, \"ep\")\n\n\t\tvar acceleration = getIndiParameter(context, \"acceleration\")\n\t\tvar afMax = getIndiParameter(context, \"afMax\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\n\t\tvar prevH = null\n\t\tvar prevL = null\n\t\tvar currH = null\n\t\tvar currL = null\n\t\tvar sar = null\n\t\tvar isLong = null\n\t\tvar af = acceleration\n\t\tvar ep = null\n\n\t\tif (i > 0) {\n\t\t\ti -= 2\n\t\t\tprevH = dataInputHigh[i - 1]\n\t\t\tprevL = dataInputLow[i - 1]\n\t\t\tisLong = dataOutputIsLong[i]\n\t\t\tsar = dataOutput[i]\n\t\t\taf = dataOutputAf[i]\n\t\t\tep = dataOutputEp[i]\n\t\t} else {\n\t\t\tdataOutput[i] = 0\n\t\t\tdataOutputIsLong[i] = true\n\t\t\tdataOutputAf[i] = af\n\t\t\tdataOutputEp[i] = 0\n\n\t\t\ti = 1\n\n\t\t\tprevH = dataInputHigh[i - 1]\n\t\t\tprevL = dataInputLow[i - 1]\n\t\t\tisLong = true\n\t\t\tsar = prevL\n\t\t\tep = prevH\n\t\t}\n\n\t\twhile (i < dataInputHigh.length) {\n\t\t\tcurrH = dataInputHigh[i]\n\t\t\tcurrL = dataInputLow[i]\n\n\t\t\tif (isLong) {\n\t\t\t\tif (currL <= sar) {\n\t\t\t\t\tisLong = false\n\t\t\t\t\tsar = Math.max(ep, currH, prevH)\n\n\t\t\t\t\tdataOutput[i] = sar\n\n\t\t\t\t\taf = acceleration\n\t\t\t\t\tep = currL\n\t\t\t\t\tsar = sar + af * (ep - sar)\n\t\t\t\t\tsar = Math.max(sar, currH, prevH)\n\t\t\t\t} else {\n\t\t\t\t\tdataOutput[i] = sar\n\n\t\t\t\t\tif (currH > ep) {\n\t\t\t\t\t\tep = currH\n\t\t\t\t\t\tif (af - dataOutputAf[i - 1] <= 0) {\n\t\t\t\t\t\t\taf += acceleration\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (af > afMax) {\n\t\t\t\t\t\t\taf = afMax\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsar = sar + af * (ep - sar)\n\t\t\t\t\tsar = Math.min(sar, currL, prevL)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (currH >= sar) {\n\t\t\t\t\tisLong = true\n\t\t\t\t\tsar = Math.min(ep, currL, prevL)\n\n\t\t\t\t\tdataOutput[i] = sar\n\n\t\t\t\t\taf = acceleration\n\t\t\t\t\tep = currH\n\t\t\t\t\tsar = sar + af * (ep - sar)\n\t\t\t\t\tsar = Math.min(sar, currL, prevL)\n\t\t\t\t} else {\n\t\t\t\t\tdataOutput[i] = sar\n\n\t\t\t\t\tif (currL < ep) {\n\t\t\t\t\t\tep = currL\n\t\t\t\t\t\tif (af - dataOutputAf[i - 1] <= 0) {\n\t\t\t\t\t\t\taf += acceleration\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (af > afMax) {\n\t\t\t\t\t\t\taf = afMax\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsar = sar + af * (ep - sar)\n\t\t\t\t\tsar = Math.max(sar, currH, prevH)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdataOutputIsLong[i] = isLong\n\t\t\tdataOutputAf[i] = af\n\t\t\tdataOutputEp[i] = ep\n\n\t\t\ti++\n\n\t\t\tprevH = currH\n\t\t\tprevL = currL\n\t\t}\n\t},\n[{\n\tname: \"acceleration\",\n\tvalue: 0.02,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [0.01, 0.1]\n}, {\n\tname: \"afMax\",\n\tvalue: 0.2,\n\trequired: true,\n\ttype: \"Number\",\n\trange: [0.1, 1]\n}], [{\n\tname: \"High\",\n\tindex: 0\n}, {\n\tname: \"Low\",\n\tindex: 1\n}], [{\n\tname: \"sar\",\n\tvisible: true,\n\trenderType: \"Round\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"isLong\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"af\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}, {\n\tname: \"ep\",\n\tvisible: false,\n\trenderType: null,\n\tcolor: null\n}],\n\"CHART_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/sma.js",
    "content": "registerIndicator(\n\t\"sma\", \"Simple moving average(v1.0)\", function (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tvar dataOutput = getDataOutput(context, \"sma\")\n\t\tvar period = getIndiParameter(context, \"period\")\n\t\tvar shift = getIndiParameter(context, \"shift\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tsma(dataInput, dataOutput, calculatedLength, period)\n\n\t\tif (shift != null && calculatedLength == 0) {\n\t\t\tsetIndiShift(context, \"sma\", shift)\n\t\t}\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"shift\",\n\t\tvalue: 0,\n\t\trequired: false,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"sma\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"steelblue\"\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/smma.js",
    "content": "registerIndicator(\n    \"smma\", \"Smoothed moving average(v1.0)\", function (context) {\n        var dataInput = getDataInput(context, 0)\n\t\tvar dataOutput = getDataOutput(context, \"smma\")\n\t\tvar period = getIndiParameter(context, \"period\")\n\t\tvar shift = getIndiParameter(context, \"shift\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\n\t\tsmma(dataInput, dataOutput, calculatedLength, period)\n\n\t\tif (shift != null && calculatedLength == 0) {\n\t\t\tsetIndiShift(context, \"smma\", shift)\n\t\t}\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"shift\",\n\t\tvalue: 0,\n\t\trequired: false,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [-30, 30]\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"smma\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.LINE,\n\t\tcolor: \"steelblue\"\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/stochastic.js",
    "content": "registerIndicator(\n    \"stochastic\", \"Stochastic oscillator(v1.01)\", function (context) {\n\t\tvar dataInputClose = getDataInput(context, 0)\n\t\tvar dataInputHigh = getDataInput(context, 1)\n\t\tvar dataInputLow = getDataInput(context, 2)\n\n\t\tvar highestTmp = getDataOutput(context, \"highestTmp\")\n\t\tvar lowestTmp = getDataOutput(context, \"lowestTmp\")\n\n\t\tvar dataOutputMain = getDataOutput(context, \"main\")\n\t\tvar dataOutputSignal = getDataOutput(context, \"signal\")\n\n\t\tvar kP = getIndiParameter(context, \"KPeriod\")\n\t\tvar slowing = getIndiParameter(context, \"slowing\")\n\t\tvar dP = getIndiParameter(context, \"DPeriod\")\n\t\tvar method = getIndiParameter(context, \"method\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar ptr = calculatedLength\n\t\tvar maxParam = Math.max(kP + slowing - 1, dP)\n\n\t\tif (ptr > 0) {\n\t\t\tptr--\n\t\t} else {\n\t\t\tptr = maxParam - 1\n\n\t\t\tfor (var i = 1; i < maxParam; i++) {\n\t\t\t\tdataOutputMain[ptr - i] = 0\n\t\t\t\thighestTmp[ptr - i] = 0\n\t\t\t\tlowestTmp[ptr - i] = 0\n\t\t\t}\n\t\t}\n\n\t\twhile (ptr < dataInputClose.length) {\n\t\t\tvar tmp = null\n\t\t\tvar highest = Number.MIN_VALUE\n\t\t\tvar lowest = Number.MAX_VALUE\n\n\t\t\tfor (var ptr2 = (ptr - kP + 1); ptr2 <= ptr; ptr2++){\n\t\t\t\ttmp = dataInputHigh[ptr2]\n\t\t\t\tif (highest < tmp) {\n\t\t\t\t\thighest = tmp\n\t\t\t\t}\n\n\t\t\t\ttmp = dataInputLow[ptr2]\n\t\t\t\tif (lowest > tmp) {\n\t\t\t\t\tlowest = tmp\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thighestTmp[ptr] = highest\n\t\t\tlowestTmp[ptr] = lowest\n\n\t\t\tptr++\n\t\t}\n\n\t\tptr = calculatedLength\n\n\t\tif (ptr > 0) {\n\t\t\tptr--\n\t\t} else {\n\t\t\tptr = maxParam - 1\n\t\t}\n\n\t\twhile (ptr < dataInputClose.length) {\n\t\t\tvar highestSum = 0\n\t\t\tvar lowestSum = 0\n\n\t\t\tfor (var ptr2 = ptr - slowing + 1; ptr2 <= ptr; ptr2++) {\n\t\t\t\thighestSum += highestTmp[ptr2] - lowestTmp[ptr2]\n\t\t\t\tlowestSum += dataInputClose[ptr2] - lowestTmp[ptr2]\n\t\t\t}\n\n\t\t\tif (0 == highestSum) {\n\t\t\t\tdataOutputMain[ptr] = 100\n\t\t\t}else{\n\t\t\t\tdataOutputMain[ptr] = lowestSum / highestSum * 100\n\t\t\t}\n\n\t\t\tptr++\n\t\t}\n\n\t\tif (\"sma\" == method) {\n\t\t\tsma(dataOutputMain, dataOutputSignal, calculatedLength, dP)\n\t\t} else if (\"ema\" == method) {\n\t\t\tema(dataOutputMain, dataOutputSignal, calculatedLength, dP)\n\t\t} else if (\"smma\" == method) {\n\t\t\tsmma(dataOutputMain, dataOutputSignal, calculatedLength, dP)\n\t\t} else {\n\t\t\tlwma(dataOutputMain, dataOutputSignal, calculatedLength, dP)\n\t\t}\n\t},[{\n\t\tname: \"KPeriod\",\n\t\tvalue: 5,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"slowing\",\n\t\tvalue: 3,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"DPeriod\",\n\t\tvalue: 3,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t},{\n\t\tname: \"method\",\n\t\tvalue: \"sma\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t},{\n\t\tname: DATA_NAME.HIGH,\n\t\tindex: 1\n\t},{\n\t\tname: DATA_NAME.LOW,\n\t\tindex: 2\n\t}],\n\t[{\n        name: \"highestTmp\",\n        visible: false\n    },{\n        name: \"lowestTmp\",\n        visible: false\n    },{\n        name: \"main\",\n        visible: true,\n        renderType: RENDER_TYPE.LINE,\n        color: \"#DE5029\"\n    },{\n        name: \"signal\",\n        visible: true,\n        renderType: RENDER_TYPE.DASHARRAY,\n        color: \"#4EC2B4\"\n    }],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/volume.js",
    "content": "registerIndicator(\"volume\", \"Volume of OHLC(v1.0)\", function (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tvar dataOutput = getDataOutput(context, \"volume\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\n\t\tif (i != 0) {\n\t\t\ti--\n\t\t}\n\n\t\twhile (i < dataInput.length) {\n\t\t\tdataOutput[i] = dataInput[i]\n\t\t\ti++\n\t\t}\n\t},[],\n\t[{\n\t\tname: DATA_NAME.VOLUME,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"volume\",\n\t\tvisible: true,\n\t\trenderType: RENDER_TYPE.HISTOGRAM,\n\t\tcolor: \"steelblue\"\n\t}],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/Built-in/wpr.js",
    "content": "registerIndicator(\n\"wpr\",\n\"Williams' Percent Range(v1.0)\",\nfunction (context) {\n\t    var dataInputClose = getDataInput(context, 0)\n\t    var dataInputHigh = getDataInput(context, 1)\n\t    var dataInputLow = getDataInput(context, 2)\n\t    var dataOutput = getDataOutput(context, \"wpr\")\n\t    var dataOutputHL = getDataOutput(context, \"wprHighLevel\")\n\t    var dataOutputLL = getDataOutput(context, \"wprLowLevel\")\n\t    var highLevel = getIndiParameter(context, \"highLevel\")\n\t    var lowLevel = getIndiParameter(context, \"lowLevel\")\n\t    var period = getIndiParameter(context, \"period\")\n\n\t    var calculatedLength = getCalculatedLength(context)\n\n\t    var ptr = calculatedLength\n\n\t    if (ptr > 0) {\n\t        ptr--\n\t    } else {\n\t        ptr = period - 1\n\n\t        for (var i = 0; i < period - 1; i++) {\n\t            dataOutput[i] = 0\n\t            dataOutputHL[i] = highLevel\n\t            dataOutputLL[i] = lowLevel\n\t        }\n\t    }\n\n\t    while (ptr < dataInputClose.length) {\n\t        var maxArr = []\n\n\t\t\tfor (var i = 0; i < period; i++) {\n\t\t\t\tmaxArr.push(dataInputHigh[ptr - i])\n\t\t\t}\n\n\t\t\tvar highest = Math.max.apply(null, maxArr)\n\n\t\t\tvar minArr = []\n\t\t\tfor (var i = 0; i < period; i++) {\n\t\t\t\tminArr.push(dataInputLow[ptr - i])\n\t\t\t}\n\n\t\t\tvar lowest = Math.min.apply(null, minArr)\n\n\t\t\tif (0 == highest - lowest) {\n\t\t\t\tdataOutput[ptr] = 0\n\t\t\t} else {\n\t\t\t\tdataOutput[ptr] = -100 * (highest - dataInputClose[ptr]) / (highest - lowest)\n\t\t\t}\n\n\t        dataOutputHL[ptr] = highLevel\n\t        dataOutputLL[ptr] = lowLevel\n\n\t        ptr++\n\t    }\n\t},\n[{\n\tname: \"period\",\n\tvalue: 14,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: [1, 100]\n}, {\n\tname: \"highLevel\",\n\tvalue: -20,\n\trequired: false,\n\ttype: \"Number\",\n\trange: [-100, 0]\n}, {\n\tname: \"lowLevel\",\n\tvalue: -80,\n\trequired: false,\n\ttype: \"Number\",\n\trange: [-100, 0]\n}], [{\n\tname: \"Close\",\n\tindex: 0\n}, {\n\tname: \"High\",\n\tindex: 1\n}, {\n\tname: \"Low\",\n\tindex: 2\n}], [{\n\tname: \"wpr\",\n\tvisible: true,\n\trenderType: \"Line\",\n\tcolor: \"steelblue\"\n}, {\n\tname: \"wprHighLevel\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#AAAAAA\"\n}, {\n\tname: \"wprLowLevel\",\n\tvisible: true,\n\trenderType: \"Dasharray\",\n\tcolor: \"#AAAAAA\"\n}],\n\"SEPARATE_WINDOW\")\n"
  },
  {
    "path": "Indicators/Built-in/zigzag.js",
    "content": "registerIndicator(\"zigzag\", \"ZigZag based on SAR(v1.03)\", function (context) {\n  var dataInputHigh = getDataInput(context, 0)\n  var dataInputLow = getDataInput(context, 1)\n\n  var dataOutputZZLine = getDataOutput(context, \"zigzagLine\")\n  var dataOutputZZ = getDataOutput(context, \"zigzag\")\n  var dataOutput = getDataOutput(context, \"sar\")\n  var dataOutputIsLong = getDataOutput(context, \"isLong\")\n  var dataOutputAf = getDataOutput(context, \"af\")\n  var dataOutputEp = getDataOutput(context, \"ep\")\n\n  var acceleration = getIndiParameter(context, \"acceleration\")\n  var afMax = getIndiParameter(context, \"afMax\")\n\n  var arrLen = dataInputHigh.length\n  var calculatedLength = getCalculatedLength(context)\n  var i = calculatedLength\n\n  var prevH = null\n  var prevL = null\n  var currH = null\n  var currL = null\n  var sar = null\n  var isLong = null\n  var af = acceleration\n  var ep = null\n\n  if (i > 0) {\n    i -= 2\n    prevH = dataInputHigh[i - 1]\n    prevL = dataInputLow[i - 1]\n    isLong = dataOutputIsLong[i]\n    sar = dataOutput[i]\n    af = dataOutputAf[i]\n    ep = dataOutputEp[i]\n  } else {\n    dataOutput[i] = 0\n    dataOutputIsLong[i] = true\n    dataOutputAf[i] = af\n    dataOutputEp[i] = 0\n\n    i = 1\n\n    prevH = dataInputHigh[i - 1]\n    prevL = dataInputLow[i - 1]\n    isLong = true\n    sar = prevL\n    ep = prevH\n  }\n\n  while (i < arrLen) {\n    currH = dataInputHigh[i]\n    currL = dataInputLow[i]\n\n    if (isLong) {\n      if (currL <= sar) {\n        isLong = false\n        sar = Math.max(ep, currH, prevH)\n\n        dataOutput[i] = sar\n\n        af = acceleration\n        ep = currL\n        sar = sar + af * (ep - sar)\n        sar = Math.max(sar, currH, prevH)\n      } else {\n        dataOutput[i] = sar\n\n        if (currH > ep) {\n          ep = currH\n          if (af - dataOutputAf[i - 1] <= 0) {\n            af += acceleration\n          }\n          if (af > afMax) {\n            af = afMax\n          }\n        }\n        sar = sar + af * (ep - sar)\n        sar = Math.min(sar, currL, prevL)\n      }\n    } else {\n      if (currH >= sar) {\n        isLong = true\n        sar = Math.min(ep, currL, prevL)\n\n        dataOutput[i] = sar\n\n        af = acceleration\n        ep = currH\n        sar = sar + af * (ep - sar)\n        sar = Math.min(sar, currL, prevL)\n      } else {\n        dataOutput[i] = sar\n\n        if (currL < ep) {\n          ep = currL\n          if (af - dataOutputAf[i - 1] <= 0) {\n            af += acceleration\n          }\n          if (af > afMax) {\n            af = afMax\n          }\n        }\n        sar = sar + af * (ep - sar)\n        sar = Math.max(sar, currH, prevH)\n      }\n    }\n\n    dataOutputIsLong[i] = isLong\n    dataOutputAf[i] = af\n    dataOutputEp[i] = ep\n\n    i++\n\n    prevH = currH\n    prevL = currL\n  }\n\n  var zigzag = []\n  var latestZZ = null\n  var latestZZIdx = -1\n\n  if (calculatedLength > 0) {\n    dataOutputZZ[calculatedLength - 1] = 0\n    dataOutputZZLine[calculatedLength - 1] = 0\n\n    for (i = arrLen - 1; i >= 0; i--) {\n      if (dataOutputZZ[i] != 0) {\n        latestZZ = {\n          value: dataOutputZZ[i],\n          index: i\n        }\n\n        latestZZIdx = i\n\n        break\n      }\n    }\n  } else {\n    dataOutputZZ[0] = (dataInputHigh[0] + dataInputLow[0]) / 2\n    dataOutputZZLine[0] = dataOutputZZ[0]\n\n    for (i = 1; i < arrLen; i++) {\n      dataOutputZZ[i] = 0\n    }\n\n    latestZZ = {\n      value: dataOutputZZ[0],\n      index: 0\n    }\n\n    latestZZIdx = 0\n  }\n\n  i = arrLen - 1\n\n  var foundIdx = -1\n  var lowestZZ = Number.MAX_VALUE\n  var highestZZ = -Number.MAX_VALUE\n\n  var bNextLong = dataOutputIsLong[i]\n\n  while (i >= 0 && i >= latestZZIdx) {\n    if (dataOutputIsLong[i]) {\n      if (bNextLong && i != 0) {\n        if (dataInputHigh[i] > highestZZ) {\n          foundIdx = i\n          highestZZ = dataInputHigh[i]\n        }\n      } else {\n        if (foundIdx != -1) {\n          zigzag.splice(0, 0, {\n            value: lowestZZ,\n            index: foundIdx\n          })\n        }\n\n        foundIdx = i\n        lowestZZ = Number.MAX_VALUE\n        highestZZ = dataInputHigh[i]\n\n        bNextLong = true\n      }\n    } else {\n      if (!bNextLong && i != 0) {\n        if (dataInputLow[i] < lowestZZ) {\n          foundIdx = i\n          lowestZZ = dataInputLow[i]\n        }\n      } else {\n        if (foundIdx != -1) {\n          zigzag.splice(0, 0, {\n            value: highestZZ,\n            index: foundIdx\n          })\n        }\n\n        foundIdx = i\n        lowestZZ = dataInputLow[i]\n        highestZZ = -Number.MAX_VALUE\n\n        bNextLong = false\n      }\n    }\n\n    i--\n  }\n\n  zigzag.splice(0, 0, latestZZ)\n\n  var zzLen = zigzag.length > 1 ? (zigzag.length - 1) : 1\n\n  for (i = 0; i < zzLen; i++) {\n    dataOutputZZ[zigzag[i].index] = zigzag[i].value\n  }\n\n  if (arrLen - 1 > zigzag[zigzag.length - 1].index) {\n    zigzag.push({\n      value: (dataInputHigh[arrLen - 1] + dataInputLow[arrLen - 1]) / 2,\n      index: arrLen - 1\n    })\n  }\n\n  for (i = 1; i < zigzag.length; i++) {\n    var step = (zigzag[i].value - zigzag[i - 1].value) / (zigzag[i].index - zigzag[i - 1].index)\n    var nextIdx = zigzag[i].index\n    var startValue = zigzag[i - 1].value\n    var startIdx = zigzag[i - 1].index\n\n    for (var j = zigzag[i - 1].index; j < nextIdx; j++) {\n      dataOutputZZLine[j] = startValue + step * (j - startIdx)\n    }\n  }\n\n  dataOutputZZLine[arrLen - 1] = zigzag[zigzag.length - 1].value\n},[{\n  name: \"acceleration\",\n  value: 0.01,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.001, 0.1]\n},{\n  name: \"afMax\",\n  value: 0.05,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.01, 1]\n}],\n[{\n  name: DATA_NAME.HIGH,\n  index: 0\n},{\n  name: DATA_NAME.LOW,\n  index: 1\n}],\n[{\n  name: \"zigzagLine\",\n  visible: true,\n  renderType: RENDER_TYPE.LINE,\n  color: \"orange\"\n},{\n  name: \"zigzag\",\n  visible: false\n},{\n  name: \"sar\",\n  visible: false\n},{\n  name: \"isLong\",\n  visible: false\n},{\n  name: \"af\",\n  visible: false\n},{\n  name: \"ep\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/Oldie/README.md",
    "content": "This folder contains deprecated programs.\n"
  },
  {
    "path": "Indicators/Oldie/README.txt",
    "content": "This folder contains deprecated programs.\n"
  },
  {
    "path": "Indicators/Oldie/fintechee_oanda_loader.js",
    "content": "registerIndicator(\"fintechee_oanda_loader\", \"A plugin to load Oanda's streaming quotes and transactions(v1.11)\", function (context) {\n  // Deprecated. A new version has been released. Please refer to EA/Plugin-for-Oanda.\n  // Disclaimer: we are not affiliated with the data providers or the API providers.\n},\n[{\n  name: \"oandaDemo\",\n  value: true,\n  required: true,\n  type: PARAMETER_TYPE.BOOLEAN,\n  range: null\n}, {\n  name: \"oandaAccountId\",\n  value: \"XXX-XXX-XXXXXXXX-XXX\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}, {\n  name: \"oandaTradeKey\",\n  value: \"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"oanda\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init\n  setDefaultIndicator(\"fintechee_oanda_loader\", true)\n  window.oandaDemo = getIndiParameter(context, \"oandaDemo\")\n  window.oandaAccountId = getIndiParameter(context, \"oandaAccountId\")\n  window.oandaTradeKey = getIndiParameter(context, \"oandaTradeKey\")\n\n  if (typeof window.oandaChangeCallback == \"undefined\") {\n    window.oandaChangeCallback = function (ctx) {\n      var symbolName = getExtraSymbolName(ctx)\n\n      if (typeof window.oandaApiLoader.currenciesList[symbolName] != \"undefined\") {\n        var chartId = getChartHandleByContext(ctx)\n        var symbol = window.oandaApiLoader.currenciesList[symbolName].symbolName.split(\"_\")\n        var baseCurrency = symbol[0]\n        var termCurrency = symbol[1]\n\n        setTakeoverMode(chartId)\n        changeChartMenuItemName(ctx)\n        var timeFrame = getTimeFrame(ctx)\n\n        window.oandaApiLoader.ticksList.add(baseCurrency)\n        window.oandaApiLoader.ticksList.add(termCurrency)\n        if (typeof window.oandaApiLoader.charts[chartId + \"\"] == \"undefined\") {\n          window.oandaApiLoader.charts[chartId + \"\"] = {\n            chartId: chartId,\n            timeFrame: null,\n            baseCurrency: null,\n            termCurrency: null,\n            baseCurrencyPrice: null,\n            termCurrencyPrice: null\n          }\n        }\n        var chart = window.oandaApiLoader.charts[chartId + \"\"]\n        chart.timeFrame = timeFrame\n        chart.baseCurrency = baseCurrency\n        chart.termCurrency = termCurrency\n\n        // Solution A:\n        // Worked as well\n        // You can compare the two solutions.\n        // $.ajax({\n        //   type: \"GET\",\n        //   url: (window.oandaDemo ? \"https://api-fxpractice.oanda.com/v3/instruments/\" : \"https://api-fxtrade.oanda.com/v3/instruments/\") + chart.baseCurrency + \"_\" + chart.termCurrency + \"/candles?granularity=\" + timeFrame.toUpperCase(),\n        //   contentType: \"application/json; charset=utf-8\",\n        //   dataType: \"json\",\n        //   headers: {\n        //     \"Authorization\": \"bearer \" + window.oandaTradeKey,\n        //     \"Accept-Datetime-Format\": \"UNIX\"\n        //   },\n        //   success: function (res) {\n        //     var data = []\n        //\n        //     if (Array.isArray(res.candles)) {\n        //       for (var i in res.candles) {\n        //         var ohlc = res.candles[i].mid\n        //\n        //         data.push({\n        //           time: Math.floor(res.candles[i].time / 1000),\n        //           volume: res.candles[i].volume,\n        //           open: parseFloat(ohlc.o),\n        //           high: parseFloat(ohlc.h),\n        //           low: parseFloat(ohlc.l),\n        //           close: parseFloat(ohlc.c)\n        //         })\n        //       }\n        //\n        //       takeoverLoad(chartId, data)\n        //     }\n        //   }\n        // })\n\n        // Solution B:\n        window.oandaDataAPI.instruments.candles(window.oandaAccountId, chart.baseCurrency + \"_\" + chart.termCurrency, {\n          granularity: timeFrame.toUpperCase()\n        })\n        .then(function (res) {\n          var data = []\n\n          if (Array.isArray(res.candles)) {\n            for (var i in res.candles) {\n              var ohlc = res.candles[i].mid\n\n              data.push({\n                time: Math.floor(new Date(res.candles[i].time).getTime() / 1000),\n                volume: res.candles[i].volume,\n                open: parseFloat(ohlc.o),\n                high: parseFloat(ohlc.h),\n                low: parseFloat(ohlc.l),\n                close: parseFloat(ohlc.c)\n              })\n            }\n\n            takeoverLoad(chartId, data)\n          }\n        })\n\n      } else {\n        var chartId = getChartHandleByContext(ctx)\n        unsetTakeoverMode(chartId)\n        takeoverLoad(chartId, [])\n        delete window.oandaApiLoader.charts[chartId + \"\"]\n      }\n    }\n  }\n\n  if (typeof window.oandaRemoveCallback == \"undefined\") {\n    window.oandaRemoveCallback = function (ctx) {\n      var chartId = getChartHandleByContext(ctx)\n      unsetTakeoverMode(chartId)\n      takeoverLoad(chartId, [])\n      delete window.oandaApiLoader.charts[chartId + \"\"]\n    }\n  }\n\n  var chartId = getChartHandleByContext(context)\n\n  if (typeof window.oandaApiLoader == \"undefined\") {\n    window.oandaApiLoader = {\n      currenciesList: [],\n      charts: [],\n      ticksList: new Set(),\n      socket: null,\n      sendOrder: function (symbolName, volume) {\n\n      },\n      onTick: function (msg) {\n        var ticks = msg.data\n\n        for (var i in window.oandaApiLoader.charts) {\n          var chart = window.oandaApiLoader.charts[i]\n          var bUpdatable1 = false\n          var bUpdatable2 = false\n\n          for (var j in ticks) {\n            if (j == chart.baseCurrency) {\n              chart.baseCurrencyPrice = parseFloat(ticks[j])\n              bUpdatable1 = true\n            }\n            if (j == chart.termCurrency) {\n              chart.termCurrencyPrice = parseFloat(ticks[j])\n              bUpdatable2 = true\n            }\n          }\n\n          if (bUpdatable1 && bUpdatable2) {\n            if (chart.baseCurrencyPrice != null && chart.termCurrencyPrice != null && chart.baseCurrencyPrice > 0 && chart.termCurrencyPrice > 0) {\n              var tick = {\n                time: Math.floor(new Date().getTime() / 1000),\n                volume: (typeof ticks.volume != \"undefined\" ? ticks.volume : 0),\n                price: Math.round(chart.baseCurrencyPrice / chart.termCurrencyPrice * 100000) / 100000\n              }\n\n              if (chart.timeFrame == \"M1\") {\n                takeoverUpdate(chart.chartId, 60, tick)\n              } else if (chart.timeFrame == \"M5\") {\n                takeoverUpdate(chart.chartId, 300, tick)\n              } else if (chart.timeFrame == \"M15\") {\n                takeoverUpdate(chart.chartId, 900, tick)\n              } else if (chart.timeFrame == \"M30\") {\n                takeoverUpdate(chart.chartId, 1800, tick)\n              } else if (chart.timeFrame == \"H1\") {\n                takeoverUpdate(chart.chartId, 3600, tick)\n              } else if (chart.timeFrame == \"H4\") {\n                takeoverUpdate(chart.chartId, 14400, tick)\n              } else if (chart.timeFrame == \"D\") {\n                takeoverUpdate(chart.chartId, 86400, tick)\n              } else {\n                takeoverUpdate(chart.chartId, 86400, tick)\n              }\n            }\n          }\n        }\n      },\n      onTransaction: function (data) {\n\n      },\n      setupSocket: function () {\n        var symbolsList = []\n        for (var i in window.oandaApiLoader.currenciesList) {\n          symbolsList.push(window.oandaApiLoader.currenciesList[i].symbolName)\n        }\n\n        if (symbolsList.length > 0) {\n          var script = document.createElement(\"script\")\n          document.body.appendChild(script)\n          script.onload = function () {\n            window.latestTickTime = 0\n            window.oandaDataAPI.addToken(window.oandaDemo, window.oandaAccountId, window.oandaTradeKey)\n            window.oandaDataCallback = function (res) {\n              window.latestOandaTickTime = new Date().getTime()\n              window.oandaLoaded = true\n\n              if (typeof res.instrument != \"undefined\") {\n                var data = {\n                  data: []\n                }\n\n                var ask = null\n                var bid = null\n                var price = null\n                if (Array.isArray(res.asks)) {\n                  ask = parseFloat(res.asks[0].price)\n                  price = ask\n                }\n                if (Array.isArray(res.bids)) {\n                  bid = parseFloat(res.bids[0].price)\n                  if (price != null) {\n                    price = (price + bid) / 2\n                  } else {\n                    price = bid\n                  }\n                }\n\n                var instrument = res.instrument.split(\"_\")\n                data.data[instrument[0]] = price\n                data.data[instrument[1]] = 1\n\n                window.oandaApiLoader.oandaQuotes[instrument[0] + \"/\" + instrument[1]] = {\n                  ask: ask,\n                  bid: bid\n                }\n\n                window.oandaApiLoader.onTick(data)\n              }\n            }\n            window.oandaDataAPI.pricing.stream(window.oandaAccountId, {instruments: symbolsList.join(\",\"), snapshot: false}, window.oandaDataCallback)\n            window.oandaOrderAPI.addToken(window.oandaDemo, window.oandaAccountId, window.oandaTradeKey)\n            window.oandaOrderCallback = function (res) {\n              if (typeof res.type != \"undefined\") {\n                var data = {\n\n                }\n                if (res.type == \"ORDER_FILL\") {\n\n                } else if (res.type == \"HEARTBEAT\") {\n                }\n\n                // {\"accountBalance\":\"6505973.49885\",\"accountID\":\"<ACCOUNT>\",\"batchID\":\"777\",\"financing\":\"0.00000\",\"id\":\"778\",\"instrument\":\"EUR_USD\",\"orderID\":\"777\",\"pl\":\"0.00000\",\"price\":\"1.11625\",\"reason\":\"MARKET_ORDER\",\"time\":\"2016-09-20T18:18:22.126490230Z\",\"tradeOpened\":{\"tradeID\":\"778\",\"units\":\"100\"},\"type\":\"ORDER_FILL\",\"units\":\"100\",\"userID\":1179508}\n                window.oandaApiLoader.onTransaction(data)\n              }\n            }\n            window.oandaOrderAPI.transactions.stream(window.oandaAccountId, window.oandaOrderCallback)\n          }\n          script.onerror = function () {\n            alert(\"Failed to load required libs. Please refresh this page again.\")\n          }\n          script.async = true\n          script.src = \"https://www.fintechee.com/js/oanda/oanda_wrapper.js\"\n        }\n      },\n      resetupSocket: function () {\n        var symbolsList = []\n        for (var i in window.oandaApiLoader.currenciesList) {\n          symbolsList.push(window.oandaApiLoader.currenciesList[i].symbolName)\n        }\n\n        if (symbolsList.length > 0) {\n          window.oandaDataAPI.pricing.stream(window.oandaAccountId, {instruments: symbolsList.join(\",\"), snapshot: false}, window.oandaDataCallback)\n          window.oandaOrderAPI.transactions.stream(window.oandaAccountId, window.oandaOrderCallback)\n        }\n      }\n    }\n\n    var chartIds = getLayout(1).concat(getLayout(2)).concat(getLayout(3)).concat(getLayout(4))\n    for (var i in chartIds) {\n      if (typeof window.oandaApiLoader.charts[chartIds[i] + \"\"] == \"undefined\") {\n        window.oandaApiLoader.charts[chartIds[i] + \"\"] = {\n          chartId: chartIds[i],\n          timeFrame: null,\n          baseCurrency: null,\n          termCurrency: null,\n          baseCurrencyPrice: null,\n          termCurrencyPrice: null\n        }\n        createTakeover(chartIds[i], window.oandaChangeCallback, window.oandaRemoveCallback)\n      }\n    }\n\n    var currenciesList = [{\n      symbolName: \"AUD_CAD\",\n      displayName: \"AUD/CAD (Oanda)\"\n    }, {\n      symbolName: \"AUD_CHF\",\n      displayName: \"AUD/CHF (Oanda)\"\n    }, {\n      symbolName: \"AUD_JPY\",\n      displayName: \"AUD/JPY (Oanda)\"\n    }, {\n      symbolName: \"AUD_USD\",\n      displayName: \"AUD/USD (Oanda)\"\n    }, {\n      symbolName: \"EUR_GBP\",\n      displayName: \"EUR/GBP (Oanda)\"\n    }, {\n      symbolName: \"EUR_JPY\",\n      displayName: \"EUR/JPY (Oanda)\"\n    }, {\n      symbolName: \"EUR_USD\",\n      displayName: \"EUR/USD (Oanda)\"\n    }, {\n      symbolName: \"GBP_AUD\",\n      displayName: \"GBP/AUD (Oanda)\"\n    }, {\n      symbolName: \"GBP_CHF\",\n      displayName: \"GBP/CHF (Oanda)\"\n    }, {\n      symbolName: \"GBP_JPY\",\n      displayName: \"GBP/JPY (Oanda)\"\n    }, {\n      symbolName: \"GBP_USD\",\n      displayName: \"GBP/USD (Oanda)\"\n    }, {\n      symbolName: \"USD_CAD\",\n      displayName: \"USD/CAD (Oanda)\"\n    }, {\n      symbolName: \"USD_CHF\",\n      displayName: \"USD/CHF (Oanda)\"\n    }, {\n      symbolName: \"USD_JPY\",\n      displayName: \"USD/JPY (Oanda)\"\n    }]\n\n    window.oandaApiLoader.oandaQuotes = []\n\n    for (var i in currenciesList) {\n      window.oandaApiLoader.currenciesList[currenciesList[i].displayName] = currenciesList[i]\n      window.oandaApiLoader.oandaQuotes[currenciesList[i].symbolName.replace(\"_\", \"/\")] = null\n    }\n\n    addExtraSymbols(currenciesList)\n\n    window.oandaApiLoader.setupSocket()\n  } else if (typeof window.oandaApiLoader.charts[chartId + \"\"] == \"undefined\") {\n    window.oandaApiLoader.charts[chartId + \"\"] = {\n      chartId: chartId,\n      baseCurrency: null,\n      termCurrency: null,\n      baseCurrencyPrice: null,\n      termCurrencyPrice: null\n    }\n    createTakeover(chartId, window.oandaChangeCallback, window.oandaRemoveCallback)\n  }\n},\nfunction (context) { // Deinit\n\n},\nfunction (context) { // Render\n\n})\n"
  },
  {
    "path": "Indicators/Oldie/line_segment_sample.js",
    "content": "// This is just an example to implement chart elements by using custom indicator.\nregisterIndicator(\"line_segment_sample\", \"A line segment implemented by using custom indicator(v1.0)\", function (context) {\n},[{\n  name: \"color\",\n  value: \"#AAA\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}, {\n  name: \"strokeWidth\",\n  value: 2,\n  required: true,\n  type: PARAMETER_TYPE.INTEGER,\n  range: [1, 10]\n}],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"line\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init()\n  var color = getIndiParameter(context, \"color\")\n  var strokeWidth = getIndiParameter(context, \"strokeWidth\")\n\n  window.dragObj = d3.drag()\n  .on(\"start\", function (d) {\n    d3.select(this).raise().classed(\"active\", true)\n  })\n  .on(\"drag\", function (d) {\n    if (d3.select(this).attr(\"class\").includes(\"lineSegmentStarts\")) {\n      window.lineSegment.dragStart(this, d3.event.x, d3.event.y, d)\n    } else if (d3.select(this).attr(\"class\").includes(\"lineSegmentEnds\")) {\n      window.lineSegment.dragEnd(this, d3.event.x, d3.event.y, d)\n    }\n  })\n  .on(\"end\", function (d) {\n    d3.select(this).classed(\"active\", false)\n  })\n\n  window.lineSegment = {\n    data: [],\n    canvas: getSvgCanvas(getIndiHandleByContext(context)),\n    dragStart: function (svgObj, x, y, d) {\n      var startIdx = Math.round(d.xScale.invert(x))\n      if (startIdx < 0) {\n        startIdx = 0\n      } else if (startIdx >= d.barNum) {\n        startIdx = d.barNum - 1\n      }\n\n      var val = y\n      if (val < 0) {\n        val = 0\n      } else if (val > d.height) {\n        val = d.height\n      }\n      d.startVal = d.yScale.invert(val)\n\n      d.startIdx = startIdx + d.cursor\n\n      d3.select(svgObj).attr(\"cx\", d.xScale(startIdx)).attr(\"cy\", val)\n      d3.select(\"#lineSegments_\" + d.id)\n        .attr(\"x1\", d.xScale(startIdx)).attr(\"y1\", val)\n    },\n    dragEnd: function (svgObj, x, y, d) {\n      var endIdx = Math.round(d.xScale.invert(x))\n      if (endIdx < 0) {\n        endIdx = 0\n      } else if (endIdx >= d.barNum) {\n        endIdx = d.barNum - 1\n      }\n\n      var val = y\n      if (val < 0) {\n        val = 0\n      } else if (val > d.height) {\n        val = d.height\n      }\n      d.endVal = d.yScale.invert(val)\n\n      d.endIdx = endIdx + d.cursor\n\n      d3.select(svgObj).attr(\"cx\", d.xScale(endIdx)).attr(\"cy\", val)\n      d3.select(\"#lineSegments_\" + d.id)\n        .attr(\"x2\", d.xScale(endIdx)).attr(\"y2\", val)\n    },\n    render: function () {\n      var lineSegmentStarts = this.canvas.selectAll(\".lineSegmentStarts\").data(this.data)\n\n      lineSegmentStarts\n        .attr(\"cx\", function (d) {return d.xScale(d.startIdx - d.cursor)})\n        .attr(\"cy\", function (d) {return d.yScale(d.startVal)})\n        .attr(\"r\", function (d) {return d.radius})\n\n      lineSegmentStarts.enter().append(\"circle\")\n        .attr(\"id\", function (d) {return \"lineSegmentStarts_\" + d.id})\n        .attr(\"class\", \"lineSegmentStarts\")\n        .attr(\"cx\", function (d) {return d.xScale(d.startIdx - d.cursor)})\n        .attr(\"cy\", function (d) {return d.yScale(d.startVal)})\n        .attr(\"r\", function (d) {return d.radius})\n        .attr(\"fill\", function (d) {return d.color})\n        .attr(\"opacity\", 1.0)\n        .attr(\"stroke\", function (d) {return d.color})\n        .call(window.dragObj)\n\n      lineSegmentStarts.exit().remove()\n\n      var lineSegmentEnds = this.canvas.selectAll(\".lineSegmentEnds\").data(this.data)\n\n      lineSegmentEnds\n        .attr(\"cx\", function (d) {return d.xScale(d.endIdx - d.cursor)})\n        .attr(\"cy\", function (d) {return d.yScale(d.endVal)})\n        .attr(\"r\", function (d) {return d.radius})\n\n      lineSegmentEnds.enter().append(\"circle\")\n        .attr(\"id\", function (d) {return \"lineSegmentEnds_\" + d.id})\n        .attr(\"class\", \"lineSegmentEnds\")\n        .attr(\"cx\", function (d) {return d.xScale(d.endIdx - d.cursor)})\n        .attr(\"cy\", function (d) {return d.yScale(d.endVal)})\n        .attr(\"r\", function (d) {return d.radius})\n        .attr(\"fill\", function (d) {return d.color})\n        .attr(\"opacity\", 1.0)\n        .attr(\"stroke\", function (d) {return d.color})\n        .call(window.dragObj)\n\n      lineSegmentEnds.exit().remove()\n\n      var lineSegments = this.canvas.selectAll(\".lineSegments\").data(this.data)\n\n      lineSegments\n        .attr(\"x1\", function (d) {return d.xScale(d.startIdx - d.cursor)})\n        .attr(\"y1\", function (d) {return d.yScale(d.startVal)})\n        .attr(\"x2\", function (d) {return d.xScale(d.endIdx - d.cursor)})\n        .attr(\"y2\", function (d) {return d.yScale(d.endVal)})\n\n      lineSegments.enter().append(\"line\")\n        .attr(\"id\", function (d) {return \"lineSegments_\" + d.id})\n        .attr(\"class\", \"lineSegments\")\n        .attr(\"x1\", function (d) {return d.xScale(d.startIdx - d.cursor)})\n        .attr(\"y1\", function (d) {return d.yScale(d.startVal)})\n        .attr(\"x2\", function (d) {return d.xScale(d.endIdx - d.cursor)})\n        .attr(\"y2\", function (d) {return d.yScale(d.endVal)})\n        .attr(\"stroke\", function (d) {return d.color})\n        .attr(\"strokeWidth\", function (d) {return d.strokeWidth})\n\n      lineSegments.exit().remove()\n    }\n  }\n\n  window.lineSegment.data.push({\n    id: 1,\n    color: color,\n    strokeWidth: strokeWidth,\n    radius: 5\n  })\n},\nfunction (context) { // Deinit()\n  window.lineSegment.data = []\n  window.lineSegment.render()\n},\nfunction (context) { // Render()\n  var barNum = getBarNum(context)\n  var cursor = getCursor(context)\n  var width = getCanvasWidth(context)\n  var height = getCanvasHeight(context)\n  var xScale = getXScale(context)\n  var yScale = getYScale(context)\n\n  if (getCalculatedLength(context) == 0) {\n    for (var i in window.lineSegment.data) {\n      var data = window.lineSegment.data[i]\n\n      data.startIdx = xScale.invert(width / 3) + cursor\n      data.endIdx = xScale.invert(width * 2 / 3) + cursor\n      data.startVal = yScale.invert(height * 2 / 3)\n      data.endVal = yScale.invert(height / 3)\n    }\n  }\n\n  for (var i in window.lineSegment.data) {\n    var data = window.lineSegment.data[i]\n\n    data.barNum = barNum\n    data.cursor = cursor\n    data.width = width\n    data.height = height\n    data.xScale = xScale\n    data.yScale = yScale\n  }\n\n  window.lineSegment.render()\n})\n"
  },
  {
    "path": "Indicators/Plugin-for-Data-API/crypto_loader.js",
    "content": "registerIndicator(\"fintechee_crypto_loader\", \"A plugin to load the specific cryptocurrency's streaming quotes(v1.02)\", function (context) {\n  // Disclaimer: we are not affiliated with the data providers or the API providers.\n},\n[],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"crypto\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) {\n  setDefaultIndicator(\"fintechee_crypto_loader\", true)\n\n  if (typeof window.cryptoChangeCallback == \"undefined\") {\n    window.cryptoChangeCallback = function (ctx) {\n      var symbolName = getExtraSymbolName(ctx)\n\n      if (typeof window.fintecheeCryptoLoader.cryptocurrenciesList[symbolName] != \"undefined\") {\n        var chartId = getChartHandleByContext(ctx)\n        var symbol = window.fintecheeCryptoLoader.cryptocurrenciesList[symbolName].symbolName.split(\"/\")\n        var baseCurrency = symbol[0]\n        var termCurrency = symbol[1]\n\n        setTakeoverMode(chartId)\n        changeChartMenuItemName(ctx)\n        var timeFrame = getTimeFrame(ctx)\n\n        window.fintecheeCryptoLoader.ticksList.add(baseCurrency)\n        window.fintecheeCryptoLoader.ticksList.add(termCurrency)\n        if (typeof window.fintecheeCryptoLoader.charts[chartId + \"\"] == \"undefined\") {\n          window.fintecheeCryptoLoader.charts[chartId + \"\"] = {\n            chartId: chartId,\n            timeFrame: null,\n            baseCurrency: null,\n            termCurrency: null,\n            baseCurrencyPrice: null,\n            termCurrencyPrice: null\n          }\n        }\n        var chart = window.fintecheeCryptoLoader.charts[chartId + \"\"]\n        chart.timeFrame = timeFrame\n        chart.baseCurrency = baseCurrency\n        chart.termCurrency = termCurrency\n\n        $.ajax({\n          type: \"GET\",\n          url: \"https://api.coincap.io/v2/candles\",\n          contentType: \"application/json; charset=utf-8\",\n          dataType: \"json\",\n          data: {\n            exchange: \"poloniex\",\n            interval: timeFrame.toLowerCase(),\n            baseId: baseCurrency,\n            quoteId: termCurrency\n          },\n          success: function (res) {\n            if (typeof res.data != \"undefined\") {\n              var data = []\n\n              if (Array.isArray(res.data)) {\n                for (var i in res.data) {\n                  var ohlc = res.data[i]\n\n                  data.push({\n                    time: Math.floor(ohlc.period / 1000),\n                    volume: parseFloat(ohlc.volume),\n                    open: parseFloat(ohlc.open),\n                    high: parseFloat(ohlc.high),\n                    low: parseFloat(ohlc.low),\n                    close: parseFloat(ohlc.close)\n                  })\n                }\n\n                takeoverLoad(chartId, data)\n              }\n            }\n          }\n        })\n\n        window.fintecheeCryptoLoader.setupSocket()\n      } else {\n        var chartId = getChartHandleByContext(ctx)\n        unsetTakeoverMode(chartId)\n        takeoverLoad(chartId, [])\n        delete window.fintecheeCryptoLoader.charts[chartId + \"\"]\n      }\n    }\n  }\n\n  if (typeof window.cryptoRemoveCallback == \"undefined\") {\n    window.cryptoRemoveCallback = function (ctx) {\n      var chartId = getChartHandleByContext(ctx)\n      unsetTakeoverMode(chartId)\n      takeoverLoad(chartId, [])\n      delete window.fintecheeCryptoLoader.charts[chartId + \"\"]\n    }\n  }\n\n  var chartId = getChartHandleByContext(context)\n\n  if (typeof window.fintecheeCryptoLoader == \"undefined\") {\n    window.fintecheeCryptoLoader = {\n      cryptocurrenciesList: [],\n      charts: [],\n      ticksList: new Set(),\n      socket: null,\n      onTick: function (msg) {\n        var ticks = JSON.parse(msg.data)\n\n        for (var i in window.fintecheeCryptoLoader.charts) {\n          var chart = window.fintecheeCryptoLoader.charts[i]\n          var bUpdatable = false\n\n          for (var j in ticks) {\n            if (j == chart.baseCurrency) {\n              chart.baseCurrencyPrice = parseFloat(ticks[j])\n              bUpdatable = true\n            }\n            if (j == chart.termCurrency) {\n              chart.termCurrencyPrice = parseFloat(ticks[j])\n              bUpdatable = true\n            }\n          }\n\n          if (bUpdatable) {\n            if (chart.baseCurrencyPrice != null && chart.termCurrencyPrice != null && chart.baseCurrencyPrice > 0 && chart.termCurrencyPrice > 0) {\n              var tick = {\n                time: Math.floor(new Date().getTime() / 1000),\n                volume: 0,\n                price: chart.baseCurrencyPrice / chart.termCurrencyPrice\n              }\n\n              if (chart.timeFrame == \"M1\") {\n                takeoverUpdate(chart.chartId, 60, tick)\n              } else if (chart.timeFrame == \"M5\") {\n                takeoverUpdate(chart.chartId, 300, tick)\n              } else if (chart.timeFrame == \"M15\") {\n                takeoverUpdate(chart.chartId, 900, tick)\n              } else if (chart.timeFrame == \"M30\") {\n                takeoverUpdate(chart.chartId, 1800, tick)\n              } else if (chart.timeFrame == \"H1\") {\n                takeoverUpdate(chart.chartId, 3600, tick)\n              } else if (chart.timeFrame == \"H4\") {\n                takeoverUpdate(chart.chartId, 14400, tick)\n              } else if (chart.timeFrame == \"D\") {\n                takeoverUpdate(chart.chartId, 86400, tick)\n              } else {\n                takeoverUpdate(chart.chartId, 86400, tick)\n              }\n            }\n          }\n        }\n      },\n      setupSocket: function () {\n        if (window.fintecheeCryptoLoader.socket != null) {\n          if(window.fintecheeCryptoLoader.socket.readyState == WebSocket.OPEN) {\n            window.fintecheeCryptoLoader.socket.close()\n          }\n          window.fintecheeCryptoLoader.socket = null\n        }\n\n        var ticksList = Array.from(window.fintecheeCryptoLoader.ticksList)\n\n        if (ticksList.length > 0) {\n          window.fintecheeCryptoLoader.socket = new WebSocket(\"wss://ws.coincap.io/prices?assets=\" + ticksList.join(\",\"))\n          window.fintecheeCryptoLoader.socket.onclose = function (e) {}\n          window.fintecheeCryptoLoader.socket.onmessage = this.onTick\n        }\n\n        window.addEventListener(\"unload\", function () {\n          if (window.fintecheeCryptoLoader.socket != null) {\n            if(window.fintecheeCryptoLoader.socket.readyState == WebSocket.OPEN) {\n              window.fintecheeCryptoLoader.socket.close()\n            }\n            window.fintecheeCryptoLoader.socket = null\n          }\n        })\n      }\n    }\n\n    var chartIds = getLayout(1).concat(getLayout(2)).concat(getLayout(3)).concat(getLayout(4))\n    for (var i in chartIds) {\n      if (typeof window.fintecheeCryptoLoader.charts[chartIds[i] + \"\"] == \"undefined\") {\n        window.fintecheeCryptoLoader.charts[chartIds[i] + \"\"] = {\n          chartId: chartIds[i],\n          timeFrame: null,\n          baseCurrency: null,\n          termCurrency: null,\n          baseCurrencyPrice: null,\n          termCurrencyPrice: null\n        }\n        createTakeover(chartIds[i], window.cryptoChangeCallback, window.cryptoRemoveCallback)\n      }\n    }\n\n    var cryptocurrenciesList = [{\n      symbolName: \"ethereum/bitcoin\",\n      displayName: \"ETH/BTC\"\n    }]\n\n    for (var i in cryptocurrenciesList) {\n      window.fintecheeCryptoLoader.cryptocurrenciesList[cryptocurrenciesList[i].displayName] = cryptocurrenciesList[i]\n    }\n\n    addExtraSymbols(cryptocurrenciesList)\n  } else if (typeof window.fintecheeCryptoLoader.charts[chartId + \"\"] == \"undefined\") {\n    window.fintecheeCryptoLoader.charts[chartId + \"\"] = {\n      chartId: chartId,\n      baseCurrency: null,\n      termCurrency: null,\n      baseCurrencyPrice: null,\n      termCurrencyPrice: null\n    }\n    createTakeover(chartId, window.cryptoChangeCallback, window.cryptoRemoveCallback)\n  }\n},\nfunction (context) {\n\n})\n"
  },
  {
    "path": "Indicators/Plugin-for-Data-API/usage.txt",
    "content": "This folder includes programs used for integrating with data providers, specifically crypto data providers.\n\nWe plan to refactor the programs within this folder. Additionally, the program for connecting with the Oanda API, which was previously located in this folder, has been moved to a new directory named Plugin-for-Oanda. This directory has also undergone refactoring. If you need to reference the structure of a data provider's connectivity, we suggest referring to Plugin-for-Oanda.\n\n"
  },
  {
    "path": "Indicators/Plugin-for-Youtube/tutorial_videos.js",
    "content": "registerIndicator(\"tutorial_videos\", \"Embedded tutorial videos(v1.0)\", function (context) {\n\t},[{\n\t\tname: \"url\",\n\t\tvalue: \"https://www.youtube.com/embed/EUjAIfttCoA\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING,\n\t\trange: null\n\t}],\n\t[{\n\t\tname: DATA_NAME.TIME,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"sma\",\n\t\tvisible: false\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW,\n\tfunction (context) { // Init()\n\t\tif (getLayoutId() != 2) {\n\t\t\tchangeLayout(2)\n\t\t}\n\n\t\twindow.chartIds = getLayout(2)\n\t\tfor (var i in window.chartIds) {\n\t\t\tmoveLayout(window.chartIds[i], 1)\n\t\t}\n\n\t\tembedHtml('<iframe src=\"' + getIndiParameter(context, \"url\") + '\" style=\"width:100%;height:100%;border:none\"></iframe>', 2)\n\t},\n\tfunction (context) { // Deinit()\n\t\tembedHtml(\"\", 2)\n\n\t\tfor (var i in window.chartIds) {\n\t\t\tmoveLayout(window.chartIds[i], 2)\n\t\t}\n\t})\n"
  },
  {
    "path": "Indicators/Plugin-for-Youtube/usage.txt",
    "content": "This plugin is designed to enable the display of YouTube videos, including live streams, within the chart layout. This allows YouTubers to conduct live trading activities and engage with their fans through social media.\n\nWith the aid of this plugin, YouTubers can screen share their trading sessions while streaming live on YouTube. This facilitates real-time communication with viewership, while fans comment and ask questions, making the trading experience more engaging.\n"
  },
  {
    "path": "Indicators/atr_comparison/README.md",
    "content": "![Fintechee ATR comparison indicator](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/atr_comparison/atr_comparison_screenshot.png?raw=true)\n"
  },
  {
    "path": "Indicators/atr_comparison/atr_comparison.js",
    "content": "registerIndicator(\n    \"atr_comparison\", \"An improved Average True Range(v1.0)\", function (context) {\n    // Please add atr_exporter to the target charts before you add this indicator to one of the target charts.\n    // For example, if you want to compare EUR/USD with AUD/USD, then you need to add atr_exporter to the target charts EUR/USD and AUD/USD respectively.\n    // After that, you need to add atr_comparison to either EUR/USD or AUD/USD.\n\t\tvar name1 = getIndiParameter(context, \"name1\")\n    var name2 = getIndiParameter(context, \"name2\")\n\n    if (typeof window.inventoryForATR == \"undefined\" || typeof window.inventoryForATR[name1] == \"undefined\" || typeof window.inventoryForATR[name2] == \"undefined\") {\n      delete context.bFirstRun\n      return\n    } else {\n      if (typeof context.bFirstRun == \"undefined\") {\n        context.bFirstRun = true\n      }\n    }\n\n    var dataInput1 = window.inventoryForATR[name1]\n    var dataInput2 = window.inventoryForATR[name2]\n    var dataOutput1 = getDataOutput(context, \"atr1\")\n    var dataOutput2 = getDataOutput(context, \"atr2\")\n    var dataInputLen1 = dataInput1.length\n    var dataInputLen2 = dataInput2.length\n    var dataOutputLen1 = dataOutput1.length\n    var dataOutputLen2 = dataOutput2.length\n\n    if (context.bFirstRun) {\n      var dataLen = 0\n\n      if (dataInputLen1 <= dataInputLen2) {\n        dataLen = dataInputLen1\n      } else {\n        dataLen = dataInputLen2\n      }\n\n      for (var i = dataInputLen1 - 1; i >= dataInputLen1 - dataLen; i--) {\n        dataOutput1[i] = dataInput1[i]\n      }\n      for (var i = dataInputLen1 - dataLen - 1; i >= 0; i--) {\n        dataOutput1[i] = 0\n      }\n      for (var i = dataInputLen2 - 1; i >= dataInputLen2 - dataLen; i--) {\n        dataOutput2[i] = dataInput2[i]\n      }\n      for (var i = dataInputLen2 - dataLen - 1; i >= 0; i--) {\n        dataOutput2[i] = 0\n      }\n    } else {\n      dataOutput1[dataOutputLen1 - 1] = dataInput1[dataInputLen1 - 1]\n      dataOutput2[dataOutputLen2 - 1] = dataInput2[dataInputLen2 - 1]\n    }\n\t},[{\n\t\tname: \"name1\",\n\t\tvalue: \"chart1\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING,\n\t\trange: null\n\t}, {\n\t\tname: \"name2\",\n\t\tvalue: \"chart2\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING,\n\t\trange: null\n\t}],\n\t[{\n\t\tname: DATA_NAME.TIME,\n\t\tindex: 0\n\t}],\n\t[{\n    name: \"atr1\",\n    visible: true,\n    renderType: RENDER_TYPE.LINE,\n    color: \"steelblue\"\n  },{\n    name: \"atr2\",\n    visible: true,\n    renderType: RENDER_TYPE.LINE,\n    color: \"orange\"\n  }],\n\tWHERE_TO_RENDER.SEPARATE_WINDOW,\n  function (context) { // Init()\n  },\n  function (context) { // Deinit()\n  },\n  function (context) { // Render()\n})\n"
  },
  {
    "path": "Indicators/atr_comparison/atr_comparison_guide.txt",
    "content": "We expand ATR to an improved version that helps us compare the volatilities of different symbols at the same time in one chart.\n\nHow it works?\n\nWe implemented two indicators, one is used to export the data you want to aggregate, such as EURUSD H1 and AUDUSD H1, so you need to add the atr_exporter to EURUSD H1 and AUDUSD H1 both charts.\nThere is a parameter named \"name\".\nYou need to set this parameter to make the other indicator atr_comparison identify the charts you are referring to.\nYou can set the name for EURUSD H1 chart to \"chart1\", you can set the name for AUDUSD H1 to \"chart2\".\nAnd then, you add atr_comparison to either of the two charts. Let's say EURUSD H1.\natr_comparison has two parameters, one should be set \"chart1\" to make it point to EURUSD H1, the other one should be set \"chart2\" to make it point to AUDUSD H1.\nFinally, you put both charts data in one indicator window, and now you can monitor the differences of the fluctuations to find the chance.\n\nThis indicator only supports two symbols. You can expand it to be able to monitor more symbols by just a little editing the original version.\n"
  },
  {
    "path": "Indicators/atr_comparison/atr_exporter.js",
    "content": "registerIndicator(\n    \"atr_exporter\", \"A tool to export the data of Average True Range to the window object(v1.01)\", function (context) {\n\t\tvar dataInputClose = getDataInput(context, 0)\n\t\tvar dataInputHigh = getDataInput(context, 1)\n\t\tvar dataInputLow = getDataInput(context, 2)\n\t\tvar tmpLine = getDataOutput(context, \"tmp\")\n\t\tvar dataOutput = getDataOutput(context, \"atr\")\n\n\t\tvar period = getIndiParameter(context, \"period\")\n    var name = getIndiParameter(context, \"name\")\n\n\t\tvar calculatedLength = getCalculatedLength(context)\n\t\tvar i = calculatedLength\n\t\tvar high = null\n\t\tvar low = null\n\t\tvar prevClose = null\n\n\t\tif (i > 0) {\n\t\t\ti--\n\t\t} else {\n\t\t\ttmpLine[i] = 0\n\t\t\ti = 1\n\t\t}\n\n\t\twhile (i < dataInputClose.length) {\n\t\t\thigh = dataInputHigh[i]\n\t\t\tlow = dataInputLow[i]\n\t\t\tprevClose = dataInputClose[i - 1]\n\n\t\t\ttmpLine[i] = Math.max(high, prevClose) - Math.min(low, prevClose)\n\n\t\t\ti++\n\t\t}\n\n\t\tsma(tmpLine, dataOutput, calculatedLength, period)\n\n    if (calculatedLength == 0) {\n      window.inventoryForATR[name] = dataOutput\n    }\n\t},[{\n\t\tname: \"period\",\n\t\tvalue: 14,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.INTEGER,\n\t\trange: [1, 100]\n\t}, {\n\t\tname: \"name\",\n\t\tvalue: \"chart1\",\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.STRING,\n\t\trange: null\n\t}],\n\t[{\n\t\tname: DATA_NAME.CLOSE,\n\t\tindex: 0\n\t},{\n\t\tname: DATA_NAME.HIGH,\n\t\tindex: 1\n\t},{\n\t\tname: DATA_NAME.LOW,\n\t\tindex: 2\n\t}],\n\t[{\n    name: \"tmp\",\n    visible: false\n    },{\n    name: \"atr\",\n    visible: false\n  }],\n\tWHERE_TO_RENDER.CHART_WINDOW,\n  function (context) { // Init()\n    if (typeof window.inventoryForATR == \"undefined\") {\n      window.inventoryForATR = []\n    }\n  },\n  function (context) { // Deinit()\n    var name = getIndiParameter(context, \"name\")\n\n    delete window.inventoryForATR[name]\n  },\n  function (context) { // Render()\n})\n"
  },
  {
    "path": "Indicators/barrage/barrage.js",
    "content": "registerIndicator(\"barrage\", \"A plugin to display barrages on the chart(v1.03)\", function(context) {},\n  [{\n    name: \"color\",\n    value: \"#FAE2BE\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }, {\n    name: \"strokeWidth\",\n    value: 2,\n    required: true,\n    type: PARAMETER_TYPE.INTEGER,\n    range: [1, 10]\n  }],\n  [{\n    name: DATA_NAME.TIME,\n    index: 0\n  }],\n  [{\n    name: \"barrage\",\n    visible: false\n  }],\n  WHERE_TO_RENDER.CHART_WINDOW,\n  function(context) { // Init()\n    var chartHandle = getChartHandleByContext(context)\n\n    if (typeof window.fintecheeBarrage == \"undefined\") {\n      var barrageStyles = `\n        .barrage-class {\n          position: absolute;\n          background-color: #f0f0f0;\n          border: 1px solid #ccc;\n          padding: 5px;\n          border-radius: 5px;\n          font-size: 12px;\n        }\n      `\n      var styleElement = $(\"<style>\").text(barrageStyles);\n      $(\"head\").append(styleElement)\n      var tooltip = d3.select(\"body\")\n        .append(\"div\")\n        .attr(\"class\", \"barrage-class\")\n        .style(\"opacity\", 0)\n\n      var tooltipTable = `\n      <table id=\"tooltipTable\">\n        <thead>\n          <tr>\n            <th>Topic</th>\n            <th>Imp</th>\n            <th>Time</th>\n            <th>Content</th>\n            <th>Actual</th>\n            <th>Forecast</th>\n            <th>Previous</th>\n          </tr>\n        </thead>\n        <tbody>\n        </tbody>\n      </table>\n      `\n\n      tooltip.html(tooltipTable)\n\n      window.fintecheeBarrage = {\n        bSetInterval: [],\n        tooltip: tooltip,\n        canvas: [],\n        timeArr: [],\n        barNum: [],\n        cursor: [],\n        width: [],\n        height: [],\n        xScale: [],\n        yScale: [],\n        timeFrameVal: [],\n        context: [],\n        data: [],\n        callback: function(ctx) {\n          var chartHandle = getChartHandleByContext(ctx)\n          var color = getIndiParameter(ctx, \"color\")\n          var strokeWidth = getIndiParameter(ctx, \"strokeWidth\")\n          var timeFrameVal = window.fintecheeBarrage.timeFrameVal[chartHandle]\n          window.fintecheeBarrage.data[chartHandle] = []\n          var data = window.fintecheeBarrage.data[chartHandle]\n\n          for (var i in window.pluginForSns.data) {\n            var snsData = window.pluginForSns.data[i]\n            for (var j in snsData) {\n              var snsItem = snsData[j]\n              if (typeof snsItem.data != \"string\") {\n                continue\n              }\n              var time = Math.floor(new Date(snsItem.data + \"Z\").getTime() / 1000)\n              var content = [snsItem]\n              var timeIdx = Math.floor(time / timeFrameVal)\n\n              if (typeof data[timeIdx + \"\"] != \"undefined\") {\n                content = data[timeIdx + \"\"].content.concat(content)\n              }\n\n              data[timeIdx + \"\"] = {\n                time: time,\n                id: 0,\n                color: color,\n                strokeWidth: strokeWidth,\n                radius: 5,\n                idx: null,\n                content: content\n              }\n            }\n          }\n\n          var timeArr = window.fintecheeBarrage.timeArr[chartHandle]\n\n          for (var i in data) {\n            var barrageItem = data[i]\n\n            barrageItem.idx = 0\n            var j = 0\n            while (j < (timeArr.length - 1)) {\n              if (timeArr[j] <= barrageItem.time &&\n                timeArr[j + 1] > barrageItem.time) {\n\n                barrageItem.idx = j\n                break\n              }\n\n              j++\n            }\n            if (j == (timeArr.length - 1) && timeArr[j] <= barrageItem.time) {\n              var day = new Date(barrageItem.time * 1000).getUTCDay()\n              if (timeArr[j] < barrageItem.time && timeArr[j] + 86400 * 2 >= barrageItem.time && (day == 6 || day == 0)) {\n                barrageItem.idx = j\n              } else {\n                barrageItem.idx = j + Math.round((barrageItem.time - timeArr[j]) / timeFrameVal)\n              }\n            }\n          }\n        },\n        formatDate: function(dt) {\n          const month = String(dt.getMonth() + 1).padStart(2, '0');\n          const day = String(dt.getDate()).padStart(2, '0');\n          const hours = String(dt.getHours()).padStart(2, '0');\n          const minutes = String(dt.getMinutes()).padStart(2, '0');\n\n          const utcString = `${month}-${day} ${hours}:${minutes}`;\n          return utcString;\n        },\n        formatContent: function(content) {\n          var tableBody = $(\"#tooltipTable tbody\")\n          tableBody.empty()\n\n          if (content.length == 0) return\n\n          var that = this;\n\n          $.each(content, function(index, item) {\n            var row = $(\"<tr>\")\n            row.append($(\"<td>\").text(item.economy))\n            row.append($(\"<td>\").text(item.impact))\n            row.append($(\"<td>\").text(that.formatDate(new Date(item.data + \"Z\"))))\n            row.append($(\"<td>\").text(item.name.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")))\n            row.append($(\"<td>\").text(item.actual))\n            row.append($(\"<td>\").text(item.forecast))\n            row.append($(\"<td>\").text(item.previous))\n            tableBody.append(row)\n          })\n        },\n        render: function(chartHandle) {\n          if (typeof this.data[chartHandle] == \"undefined\") return\n          var data = this.data[chartHandle]\n          if (data.length == 0) return\n\n          var canvas = this.canvas[chartHandle]\n          var timeArr = this.timeArr[chartHandle]\n          var barNum = this.barNum[chartHandle]\n          var cursor = this.cursor[chartHandle]\n          var width = this.width[chartHandle]\n          var height = this.height[chartHandle]\n          var xScale = this.xScale[chartHandle]\n          var yScale = this.yScale[chartHandle]\n\n          var renderingData = []\n          for (var i in data) {\n            renderingData.push(data[i])\n          }\n\n          var that = this\n          var barrage = canvas.selectAll(\".barrage\").data(renderingData)\n          var symbolGenerator = d3.symbol()\n          var symbol = symbolGenerator.type(d3.symbolTriangle)\n\n          barrage\n            .attr(\"id\", function(d) {\n              return \"barrage_\" + d.id\n            })\n            .attr(\"transform\", function(d) {\n              return \"translate(\" + xScale(d.idx - cursor) + \", \" + (height - d.radius) + \")\"\n            })\n            .on(\"mouseover\", function(d) {\n              var circleX = xScale((d.idx - cursor) <= barNum / 2 ? (d.idx - cursor + 5) : Math.floor(barNum / 2 + 5))\n              var circleY = height - (d.content.length - 1) * 30\n\n              that.formatContent(d.content)\n              that.tooltip\n                .style(\"left\", (circleX + 10) + \"px\")\n                .style(\"top\", (circleY - 10) + \"px\")\n                .transition()\n                .duration(200)\n                .style(\"opacity\", 0.9)\n            })\n            .on(\"mouseout\", function(d) {\n              that.tooltip.transition()\n                .duration(500)\n                .style(\"opacity\", 0)\n            })\n\n          barrage.enter().append(\"path\")\n            .attr(\"d\", symbol)\n            .attr(\"id\", function(d) {\n              return \"barrage_\" + d.id\n            })\n            .attr(\"class\", \"barrage\")\n            .attr(\"transform\", function(d) {\n              return \"translate(\" + xScale(d.idx - cursor) + \", \" + (height - d.radius) + \")\"\n            })\n            .attr(\"opacity\", 1.0)\n            .attr(\"stroke\", function(d) {\n              return d.color\n            })\n            .attr(\"fill\", function(d) {\n              return d.color\n            })\n            .on(\"mouseover\", function(d) {\n              var circleX = xScale((d.idx - cursor) <= barNum / 2 ? (d.idx - cursor + 5) : Math.floor(barNum / 2 + 5))\n              var circleY = height - (d.content.length - 1) * 30\n\n              that.formatContent(d.content)\n              that.tooltip\n                .style(\"left\", (circleX + 10) + \"px\")\n                .style(\"top\", (circleY - 10) + \"px\")\n                .transition()\n                .duration(200)\n                .style(\"opacity\", 0.9)\n            })\n            .on(\"mouseout\", function(d) {\n              that.tooltip.transition()\n                .duration(500)\n                .style(\"opacity\", 0)\n            })\n\n          barrage.exit().remove()\n        }\n      }\n    }\n\n    window.fintecheeBarrage.canvas[chartHandle] = getSvgCanvas(chartHandle)\n\n    if (typeof window.pluginForSns == \"undefined\") {\n      window.fintecheeBarrage.context[chartHandle] = context\n    } else {\n      window.pluginForSns.subscribe(\"barrage-\" + chartHandle, window.fintecheeBarrage.callback, context)\n    }\n  },\n  function(context) { // Deinit()\n    var chartHandle = getChartHandleByContext(context)\n    window.fintecheeBarrage.canvas[chartHandle].selectAll(\".barrage\").data([]).exit().remove()\n\n    delete window.fintecheeBarrage.timeArr[chartHandle]\n    delete window.fintecheeBarrage.canvas[chartHandle]\n    delete window.fintecheeBarrage.barNum[chartHandle]\n    delete window.fintecheeBarrage.cursor[chartHandle]\n    delete window.fintecheeBarrage.width[chartHandle]\n    delete window.fintecheeBarrage.height[chartHandle]\n    delete window.fintecheeBarrage.xScale[chartHandle]\n    delete window.fintecheeBarrage.yScale[chartHandle]\n    delete window.fintecheeBarrage.timeFrameVal[chartHandle]\n    delete window.fintecheeBarrage.context[chartHandle]\n    delete window.fintecheeBarrage.data[chartHandle]\n    delete window.fintecheeBarrage.bSetInterval[chartHandle]\n\n    if (typeof window.pluginForSns != \"undefined\") {\n      window.pluginForSns.unsubscribe(\"barrage\")\n    }\n  },\n  function(context) { // Render()\n    var chartHandle = getChartHandleByContext(context)\n    var timeFrame = getTimeFrame(context)\n    var timeFrameVal = 0\n\n    if (timeFrame == \"M1\") {\n      timeFrameVal = 60\n    } else if (timeFrame == \"M5\") {\n      timeFrameVal = 300\n    } else if (timeFrame == \"M15\") {\n      timeFrameVal = 900\n    } else if (timeFrame == \"M30\") {\n      timeFrameVal = 1800\n    } else if (timeFrame == \"H1\") {\n      timeFrameVal = 3600\n    } else if (timeFrame == \"H4\") {\n      timeFrameVal = 14400\n    } else if (timeFrame == \"D\") {\n      timeFrameVal = 86400\n    } else {\n      timeFrameVal = 86400\n    }\n\n    window.fintecheeBarrage.timeArr[chartHandle] = getDataInput(context, 0)\n    window.fintecheeBarrage.barNum[chartHandle] = getBarNum(context)\n    window.fintecheeBarrage.cursor[chartHandle] = getCursor(context)\n    window.fintecheeBarrage.width[chartHandle] = getCanvasWidth(context)\n    window.fintecheeBarrage.height[chartHandle] = getCanvasHeight(context)\n    window.fintecheeBarrage.xScale[chartHandle] = getXScale(context)\n    window.fintecheeBarrage.yScale[chartHandle] = getYScale(context)\n    window.fintecheeBarrage.timeFrameVal[chartHandle] = timeFrameVal\n\n    if (typeof window.fintecheeBarrage.bSetInterval[chartHandle] != \"undefined\") {\n      return\n    }\n\n    setInterval(function() { // It is not necessary for normal indicators to call setInterval. The reason why we set interval here is because at weekends, the onRender callback function isn't triggered after loading charts.\n      window.fintecheeBarrage.bSetInterval[chartHandle] = true\n\n      if (typeof window.pluginForSns == \"undefined\") {\n        return\n      }\n\n      window.fintecheeBarrage.render(chartHandle)\n    }, 5000)\n  })\n"
  },
  {
    "path": "Indicators/chart_elements/README.md",
    "content": "chart_elements.js is a plugin to manage the chart elements implemented by API for indicators.\n\ntoggle_trading_signals.js is a very useful plugin to toggle show/hide the trading signals.\n"
  },
  {
    "path": "Indicators/chart_elements/chart_elements.js",
    "content": "registerIndicator(\"chart_elements\", \"A manager for the chart elements implemented by using custom indicator(v1.04)\", function (context) {\n},[{\n  name: \"color\",\n  value: \"#AAA\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}, {\n  name: \"strokeWidth\",\n  value: 2,\n  required: true,\n  type: PARAMETER_TYPE.INTEGER,\n  range: [1, 10]\n}],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"line\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init()\n  var chartHandle = getChartHandleByContext(context)\n\n  if (typeof window.dragObj == \"undefined\" || window.dragObj == null) {\n    window.dragObj = d3.drag()\n    .on(\"start\", function (d) {\n      d3.select(this).raise().classed(\"active\", true)\n    })\n    .on(\"drag\", function (d) {\n      if (d.type == \"lineSegment\") {\n        if (d3.select(this).attr(\"class\").includes(\"lineSegmentStarts\")) {\n          window.chartElements.lineSegment.dragStart(d3.event.x, d3.event.y, d)\n        } else if (d3.select(this).attr(\"class\").includes(\"lineSegmentEnds\")) {\n          window.chartElements.lineSegment.dragEnd(d3.event.x, d3.event.y, d)\n        }\n      }\n    })\n    .on(\"end\", function (d) {\n      d3.select(this).classed(\"active\", false)\n      window.chartElements.save()\n    })\n  }\n\n  if (typeof window.chartElements == \"undefined\" || window.chartElements == null) {\n    var elements = []\n\n    if (typeof localStorage.reservedZone != \"undefined\") {\n      var reservedZone = JSON.parse(localStorage.reservedZone)\n      if (typeof reservedZone.elements != \"undefined\") {\n        elements = reservedZone.elements\n      }\n    }\n\n    window.chartElements = {\n      newId: (elements.length > 0 ? elements[elements.length - 1].id + 1 : 0),\n      timeArr: [],\n      data: elements,\n      canvas: [],\n      barNum: [],\n      cursor: [],\n      width: [],\n      height: [],\n      xScale: [],\n      yScale: [],\n      timeFrameVal: [],\n      save: function () {\n        if (typeof localStorage.reservedZone == \"undefined\") {\n          localStorage.reservedZone = JSON.stringify({\n            elements: this.data\n          })\n        } else {\n          var reservedZone = JSON.parse(localStorage.reservedZone)\n          reservedZone.elements = this.data\n          localStorage.reservedZone = JSON.stringify(reservedZone)\n        }\n      },\n      remove: function (id) {\n        var element = null\n        var type = null\n\n        for (var i = this.data.length - 1; i >= 0; i--) {\n          element = this.data[i]\n\n          if (element.id == id) {\n            type = element.type\n            this.data.splice(i, 1)\n            break\n          }\n        }\n\n        this.save()\n        if (type == \"lineSegment\") {\n          this.lineSegment.render(element.chartHandle)\n        }\n      },\n      lineSegment: {\n        add: function (type, chartHandle, color, strokeWidth) {\n          var timeArr = window.chartElements.timeArr[chartHandle]\n          var cursor = window.chartElements.cursor[chartHandle]\n          var width = window.chartElements.width[chartHandle]\n          var height = window.chartElements.height[chartHandle]\n          var xScale = window.chartElements.xScale[chartHandle]\n          var yScale = window.chartElements.yScale[chartHandle]\n\n          var lineSegment = {\n            type: type,\n            chartHandle: chartHandle,\n            id: window.chartElements.newId,\n            color: color,\n            strokeWidth: strokeWidth,\n            radius: 5,\n            startTime: null,\n            endTime: null,\n            startIdx: null,\n            endIdx: null,\n            startVal: null,\n            endVal: null\n          }\n\n          lineSegment.startIdx = Math.floor(xScale.invert(width / 3) + cursor)\n          if (lineSegment.startIdx < 0) {\n            lineSegment.startIdx = 0\n          }\n          if (lineSegment.startIdx >= window.chartElements.timeArr[chartHandle].length) {\n            lineSegment.startIdx = window.chartElements.timeArr[chartHandle].length - 1\n          }\n          lineSegment.endIdx = Math.floor(xScale.invert(width * 2 / 3) + cursor)\n          if (lineSegment.endIdx < 0) {\n            lineSegment.endIdx = 0\n          }\n          if (lineSegment.endIdx >= window.chartElements.timeArr[chartHandle].length) {\n            lineSegment.endIdx = window.chartElements.timeArr[chartHandle].length - 1\n          }\n          lineSegment.startVal = yScale.invert(height * 2 / 3)\n          lineSegment.endVal = yScale.invert(height / 3)\n          lineSegment.startTime = timeArr[lineSegment.startIdx]\n          lineSegment.endTime = timeArr[lineSegment.endIdx]\n\n          window.chartElements.data.push(lineSegment)\n\n          window.chartElements.newId++\n\n          window.chartElements.save()\n          this.render(chartHandle)\n        },\n        dragStart: function (x, y, d) {\n          var chartHandle = d.chartHandle\n          var timeArr = window.chartElements.timeArr[chartHandle]\n          var barNum = window.chartElements.barNum[chartHandle]\n          var cursor = window.chartElements.cursor[chartHandle]\n          var width = window.chartElements.width[chartHandle]\n          var height = window.chartElements.height[chartHandle]\n          var xScale = window.chartElements.xScale[chartHandle]\n          var yScale = window.chartElements.yScale[chartHandle]\n          var timeFrameVal = window.chartElements.timeFrameVal[chartHandle]\n\n          var startIdx = Math.round(xScale.invert(x))\n          if (startIdx < 0) {\n            startIdx = 0\n          } else if (startIdx >= barNum) {\n            startIdx = barNum - 1\n          }\n\n          var val = y\n          if (val < 0) {\n            val = 0\n          } else if (val > height) {\n            val = height\n          }\n          d.startVal = yScale.invert(val)\n\n          d.startIdx = startIdx + cursor\n\n          d3.select(\"#lineSegmentStarts_\" + d.id)\n            .attr(\"cx\", xScale(startIdx)).attr(\"cy\", val)\n          d3.select(\"#lineSegments_\" + d.id)\n            .attr(\"x1\", xScale(startIdx)).attr(\"y1\", val)\n          d3.select(\"#lineSegmentCloses_\" + d.id)\n            .attr(\"cx\", function (d) {return xScale((d.startIdx + d.endIdx) / 2.0 - cursor)})\n            .attr(\"cy\", function (d) {return yScale((d.startVal + d.endVal) / 2.0)})\n\n          if (typeof timeArr[d.startIdx] != \"undefined\") {\n            d.startTime = timeArr[d.startIdx]\n      \t\t} else {\n      \t\t\td.startTime = timeArr[timeArr.length - 1] + timeFrameVal * (d.startIdx - timeArr.length + 1)\n      \t\t}\n        },\n        dragEnd: function (x, y, d) {\n          var chartHandle = d.chartHandle\n          var timeArr = window.chartElements.timeArr[chartHandle]\n          var barNum = window.chartElements.barNum[chartHandle]\n          var cursor = window.chartElements.cursor[chartHandle]\n          var width = window.chartElements.width[chartHandle]\n          var height = window.chartElements.height[chartHandle]\n          var xScale = window.chartElements.xScale[chartHandle]\n          var yScale = window.chartElements.yScale[chartHandle]\n          var timeFrameVal = window.chartElements.timeFrameVal[chartHandle]\n\n          var endIdx = Math.round(xScale.invert(x))\n          if (endIdx < 0) {\n            endIdx = 0\n          } else if (endIdx >= barNum) {\n            endIdx = barNum - 1\n          }\n\n          var val = y\n          if (val < 0) {\n            val = 0\n          } else if (val > height) {\n            val = height\n          }\n          d.endVal = yScale.invert(val)\n\n          d.endIdx = endIdx + cursor\n\n          d3.select(\"#lineSegmentEnds_\" + d.id)\n            .attr(\"cx\", xScale(endIdx)).attr(\"cy\", val)\n          d3.select(\"#lineSegments_\" + d.id)\n            .attr(\"x2\", xScale(endIdx)).attr(\"y2\", val)\n          d3.select(\"#lineSegmentCloses_\" + d.id)\n            .attr(\"cx\", function (d) {return xScale((d.startIdx + d.endIdx) / 2.0 - cursor)})\n            .attr(\"cy\", function (d) {return yScale((d.startVal + d.endVal) / 2.0)})\n\n          if (typeof timeArr[d.endIdx] != \"undefined\") {\n            d.endTime = timeArr[d.endIdx]\n      \t\t} else {\n      \t\t\td.endTime = timeArr[timeArr.length - 1] + timeFrameVal * (d.endIdx - timeArr.length + 1)\n      \t\t}\n        },\n        render: function (chartHandle) {\n          var canvas = window.chartElements.canvas[chartHandle]\n          var timeArr = window.chartElements.timeArr[chartHandle]\n          var barNum = window.chartElements.barNum[chartHandle]\n          var cursor = window.chartElements.cursor[chartHandle]\n          var width = window.chartElements.width[chartHandle]\n          var height = window.chartElements.height[chartHandle]\n          var xScale = window.chartElements.xScale[chartHandle]\n          var yScale = window.chartElements.yScale[chartHandle]\n\n          var renderingData = []\n\n          for (var i in window.chartElements.data) {\n            var element = window.chartElements.data[i]\n\n            if (element.chartHandle == chartHandle && element.type == \"lineSegment\") {\n              renderingData.push(element)\n            }\n          }\n\n          var lineSegmentStarts = canvas.selectAll(\".lineSegmentStarts\").data(renderingData)\n\n          lineSegmentStarts\n            .attr(\"id\", function (d) {return \"lineSegmentStarts_\" + d.id})\n            .attr(\"cx\", function (d) {return xScale(d.startIdx - cursor)})\n            .attr(\"cy\", function (d) {return yScale(d.startVal)})\n            .attr(\"r\", function (d) {return d.radius})\n\n          lineSegmentStarts.enter().append(\"circle\")\n            .attr(\"id\", function (d) {return \"lineSegmentStarts_\" + d.id})\n            .attr(\"class\", \"lineSegmentStarts\")\n            .attr(\"cx\", function (d) {return xScale(d.startIdx - cursor)})\n            .attr(\"cy\", function (d) {return yScale(d.startVal)})\n            .attr(\"r\", function (d) {return d.radius})\n            .attr(\"fill\", function (d) {return d.color})\n            .attr(\"opacity\", 1.0)\n            .attr(\"stroke\", function (d) {return d.color})\n            .call(window.dragObj)\n\n          lineSegmentStarts.exit().remove()\n\n          var lineSegmentEnds = canvas.selectAll(\".lineSegmentEnds\").data(renderingData)\n\n          lineSegmentEnds\n            .attr(\"id\", function (d) {return \"lineSegmentEnds_\" + d.id})\n            .attr(\"cx\", function (d) {return xScale(d.endIdx - cursor)})\n            .attr(\"cy\", function (d) {return yScale(d.endVal)})\n            .attr(\"r\", function (d) {return d.radius})\n\n          lineSegmentEnds.enter().append(\"circle\")\n            .attr(\"id\", function (d) {return \"lineSegmentEnds_\" + d.id})\n            .attr(\"class\", \"lineSegmentEnds\")\n            .attr(\"cx\", function (d) {return xScale(d.endIdx - cursor)})\n            .attr(\"cy\", function (d) {return yScale(d.endVal)})\n            .attr(\"r\", function (d) {return d.radius})\n            .attr(\"fill\", function (d) {return d.color})\n            .attr(\"opacity\", 1.0)\n            .attr(\"stroke\", function (d) {return d.color})\n            .call(window.dragObj)\n\n          lineSegmentEnds.exit().remove()\n\n          var lineSegments = canvas.selectAll(\".lineSegments\").data(renderingData)\n\n          lineSegments\n            .attr(\"id\", function (d) {return \"lineSegments_\" + d.id})\n            .attr(\"x1\", function (d) {return xScale(d.startIdx - cursor)})\n            .attr(\"y1\", function (d) {return yScale(d.startVal)})\n            .attr(\"x2\", function (d) {return xScale(d.endIdx - cursor)})\n            .attr(\"y2\", function (d) {return yScale(d.endVal)})\n\n          lineSegments.enter().append(\"line\")\n            .attr(\"id\", function (d) {return \"lineSegments_\" + d.id})\n            .attr(\"class\", \"lineSegments\")\n            .attr(\"x1\", function (d) {return xScale(d.startIdx - cursor)})\n            .attr(\"y1\", function (d) {return yScale(d.startVal)})\n            .attr(\"x2\", function (d) {return xScale(d.endIdx - cursor)})\n            .attr(\"y2\", function (d) {return yScale(d.endVal)})\n            .attr(\"stroke\", function (d) {return d.color})\n            .attr(\"strokeWidth\", function (d) {return d.strokeWidth})\n\n          lineSegments.exit().remove()\n\n          var lineSegmentCloses = canvas.selectAll(\".lineSegmentCloses\").data(renderingData)\n\n          lineSegmentCloses\n            .attr(\"id\", function (d) {return \"lineSegmentCloses_\" + d.id})\n            .attr(\"cx\", function (d) {return xScale((d.startIdx + d.endIdx) / 2.0 - cursor)})\n            .attr(\"cy\", function (d) {return yScale((d.startVal + d.endVal) / 2.0)})\n            .attr(\"r\", function (d) {return d.radius})\n            .on(\"click\", function (d) {\n              window.chartElements.remove(d.id)\n            })\n\n          lineSegmentCloses.enter().append(\"circle\")\n            .attr(\"id\", function (d) {return \"lineSegmentCloses_\" + d.id})\n            .attr(\"class\", \"lineSegmentCloses\")\n            .attr(\"cx\", function (d) {return xScale((d.startIdx + d.endIdx) / 2.0 - cursor)})\n            .attr(\"cy\", function (d) {return yScale((d.startVal + d.endVal) / 2.0)})\n            .attr(\"r\", function (d) {return d.radius})\n            .attr(\"fill\", \"orange\")\n            .attr(\"opacity\", 1.0)\n            .attr(\"stroke\", function (d) {return d.color})\n            .on(\"click\", function (d) {\n              window.chartElements.remove(d.id)\n            })\n\n          lineSegmentCloses.exit().remove()\n        }\n      }\n    }\n  } else {\n    var elements = []\n\n    if (typeof localStorage.reservedZone != \"undefined\") {\n      var reservedZone = JSON.parse(localStorage.reservedZone)\n      if (typeof reservedZone.elements != \"undefined\") {\n        elements = reservedZone.elements\n      }\n    }\n\n    window.chartElements.data = elements\n  }\n\n  window.chartElements.canvas[chartHandle] = getSvgCanvas(chartHandle)\n},\nfunction (context) { // Deinit()\n  var chartHandle = getChartHandleByContext(context)\n  var elements = window.chartElements.data\n\n  for (var i = elements.length - 1; i >= 0; i--) {\n    if (elements[i].chartHandle == chartHandle) {\n      elements.splice(i, 1)\n    }\n  }\n\n  window.chartElements.lineSegment.render(chartHandle)\n\n  window.chartElements.canvas[chartHandle].selectAll(\".btnLineSegmentG\").data([]).exit().remove()\n\n  delete window.chartElements.timeArr[chartHandle]\n  delete window.chartElements.canvas[chartHandle]\n  delete window.chartElements.barNum[chartHandle]\n  delete window.chartElements.cursor[chartHandle]\n  delete window.chartElements.width[chartHandle]\n  delete window.chartElements.height[chartHandle]\n  delete window.chartElements.xScale[chartHandle]\n  delete window.chartElements.yScale[chartHandle]\n  delete window.chartElements.timeFrameVal[chartHandle]\n},\nfunction (context) { // Render()\n  var chartHandle = getChartHandleByContext(context)\n  var color = getIndiParameter(context, \"color\")\n  var strokeWidth = getIndiParameter(context, \"strokeWidth\")\n  var barNum = getBarNum(context)\n  var cursor = getCursor(context)\n  var width = getCanvasWidth(context)\n  var height = getCanvasHeight(context)\n  var xScale = getXScale(context)\n  var yScale = getYScale(context)\n  var timeFrame = getTimeFrame(context)\n  var timeFrameVal = 0\n\n  if (timeFrame == \"M1\") {\n    timeFrameVal = 60\n  } else if (timeFrame == \"M5\") {\n    timeFrameVal = 300\n  } else if (timeFrame == \"M15\") {\n    timeFrameVal = 900\n  } else if (timeFrame == \"M30\") {\n    timeFrameVal = 1800\n  } else if (timeFrame == \"H1\") {\n    timeFrameVal = 3600\n  } else if (timeFrame == \"H4\") {\n    timeFrameVal = 14400\n  } else if (timeFrame == \"D\") {\n    timeFrameVal = 86400\n  } else {\n    timeFrameVal = 86400\n  }\n\n  var buttons = [{\n    chartHandle: chartHandle,\n    color: color,\n    strokeWidth: strokeWidth,\n    label: \"L\"\n  }]\n  var btnLineSegmentG = null\n  var btnLineSegment = null\n  var btnLineSegmentTxt = null\n\n  if (getCalculatedLength(context) == 0) {\n    var timeArr = getDataInput(context, 0)\n    window.chartElements.timeArr[chartHandle] = timeArr\n\n    btnLineSegmentG = window.chartElements.canvas[chartHandle].append(\"g\")\n      .attr(\"class\", \"btnLineSegmentG\")\n\n    btnLineSegment = btnLineSegmentG.selectAll(\".btnLineSegment\").data(buttons)\n    btnLineSegmentTxt = btnLineSegmentG.selectAll(\".btnLineSegmentTxt\").data(buttons)\n\n    btnLineSegment\n      .enter().append(\"circle\")\n      .attr(\"class\", \"btnLineSegment\")\n      .attr(\"cx\", 15)\n      .attr(\"cy\", height - 15)\n      .attr(\"r\", 10)\n      .attr(\"stroke\", \"steelblue\")\n      .attr(\"fill\", \"steelblue\")\n      .style(\"cursor\", \"pointer\")\n      .on(\"click\", function (d) {\n        window.chartElements.lineSegment.add(\"lineSegment\", d.chartHandle, d.color, d.strokeWidth)\n      })\n\n    btnLineSegmentTxt\n      .enter().append(\"text\")\n      .attr(\"class\", \"btnLineSegmentTxt\")\n      .attr(\"width\", \"10px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", 15)\n      .attr(\"y\", height - 15)\n      .attr(\"dx\", -5)\n      .attr(\"dy\", 5)\n      .attr(\"fill\", \"white\")\n      .attr(\"textAnchor\", \"start\")\n      .style(\"fontSize\", \"8px\")\n      .style(\"cursor\", \"pointer\")\n      .text(function (d) {\n        return d.label\n      })\n      .on(\"click\", function (d) {\n        window.chartElements.lineSegment.add(\"lineSegment\", d.chartHandle, d.color, d.strokeWidth)\n      })\n\n    for (var i in window.chartElements.data) {\n      if (window.chartElements.data[i].type == \"lineSegment\") {\n        var lineSegment = window.chartElements.data[i]\n\n        if (lineSegment.chartHandle == chartHandle) {\n          lineSegment.startIdx = 0\n          var j = 0\n          while (j < (timeArr.length - 1)) {\n            if (timeArr[j] <= lineSegment.startTime &&\n              timeArr[j+1] > lineSegment.startTime) {\n\n              lineSegment.startIdx = j\n              break\n            }\n\n            j++\n          }\n          if (j == (timeArr.length - 1) && timeArr[j] <= lineSegment.startTime) {\n  \t\t\t\t\tlineSegment.startIdx = j + Math.round((lineSegment.startTime - timeArr[j]) / timeFrameVal)\n  \t\t\t\t}\n\n          lineSegment.endIdx = 0\n          j = 0\n          while (j < (timeArr.length - 1)) {\n            if (timeArr[j] <= lineSegment.endTime &&\n              timeArr[j+1] > lineSegment.endTime) {\n\n              lineSegment.endIdx = j\n              break\n            }\n\n            j++\n          }\n          if (j == (timeArr.length - 1) && timeArr[j] <= lineSegment.endTime) {\n  \t\t\t\t\tlineSegment.endIdx = j + Math.round((lineSegment.endTime - timeArr[j]) / timeFrameVal)\n  \t\t\t\t}\n        }\n      }\n    }\n  } else {\n    btnLineSegment = window.chartElements.canvas[chartHandle].selectAll(\".btnLineSegment\").data(buttons)\n    btnLineSegmentTxt = window.chartElements.canvas[chartHandle].selectAll(\".btnLineSegmentTxt\").data(buttons)\n\n    btnLineSegment\n      .attr(\"cy\", height - 15)\n\n    btnLineSegmentTxt\n      .attr(\"y\", height - 15)\n  }\n\n  window.chartElements.barNum[chartHandle] = barNum\n  window.chartElements.cursor[chartHandle] = cursor\n  window.chartElements.width[chartHandle] = width\n  window.chartElements.height[chartHandle] = height\n  window.chartElements.xScale[chartHandle] = xScale\n  window.chartElements.yScale[chartHandle] = yScale\n  window.chartElements.timeFrameVal[chartHandle] = timeFrameVal\n\n  window.chartElements.lineSegment.render(chartHandle)\n})\n"
  },
  {
    "path": "Indicators/chart_elements/chart_elements_intro.txt",
    "content": "One of the key features of Fintechee is its extensibility. The platform comes equipped with built-in chart elements such as the line element and Fibonacci. You can even create your own chart elements on the fly. chart_elements is not only a manager for customized elements but also a reference for you to refer to. It's worth noting that chart_elements is still under maintenance, so we may update it in the future. To avoid being overwritten, please rename the program and then edit it.\n"
  },
  {
    "path": "Indicators/chart_elements/toggle_signals_intro.txt",
    "content": "toggle_trading_signals is used to toggle the display of circles to indicate when trades are opened and closed.\n"
  },
  {
    "path": "Indicators/chart_elements/toggle_trading_signals.js",
    "content": "\tregisterIndicator(\"toggle_trading_signals\", \"Toggle the display of the trading signals(v1.03)\", function (context) {\n\t},[{\n\t\tname: \"opacityPendingOrder\",\n\t\tvalue: 0,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\trange: [0, 1.0]\n\t},{\n\t\tname: \"opacityOpenTrade\",\n\t\tvalue: 0,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\trange: [0, 1.0]\n\t},{\n\t\tname: \"opacityHistoryTrade\",\n\t\tvalue: 0,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.NUMBER,\n\t\trange: [0, 1.0]\n\t},{\n\t\tname: \"isGlobal\",\n\t\tvalue: false,\n\t\trequired: true,\n\t\ttype: PARAMETER_TYPE.BOOLEAN,\n\t\trange: null\n\t}],\n\t[{\n\t\tname: DATA_NAME.TIME,\n\t\tindex: 0\n\t}],\n\t[{\n\t\tname: \"toggle_trading_signals\",\n\t\tvisible: false\n\t}],\n\tWHERE_TO_RENDER.CHART_WINDOW,\n\tfunction (context) { // Init()\n\t\tvar opacityPendingOrder = getIndiParameter(context, \"opacityPendingOrder\")\n\t\tvar opacityPendingOrder2 = opacityPendingOrder > 0 ? 1 : 0;\n\t\tvar opacityOpenTrade = getIndiParameter(context, \"opacityOpenTrade\")\n\t\tvar opacityOpenTrade2 = opacityOpenTrade > 0 ? 1 : 0;\n\t\tvar opacityHistoryTrade = getIndiParameter(context, \"opacityHistoryTrade\")\n\t\tvar opacityHistoryTrade2 = opacityHistoryTrade > 0 ? 1 : 0;\n\t\tvar isGlobal = getIndiParameter(context, \"isGlobal\")\n\n\t\tvar chartHandle = getChartHandleByContext(context)\n\t\tvar canvas = isGlobal ? d3 : d3.select(\"#cc_k_c_d_\" + chartHandle)\n\n\t\tcanvas.selectAll(\".cc_k_c_p_o_l\").style(\"opacity\", opacityPendingOrder2)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_t_l\").style(\"opacity\", opacityPendingOrder2)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_s_l\").style(\"opacity\", opacityPendingOrder2)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_b\").style(\"opacity\", opacityPendingOrder)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_t\").style(\"opacity\", opacityPendingOrder2)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_t_l\").style(\"opacity\", opacityOpenTrade2)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_s_l\").style(\"opacity\", opacityOpenTrade2)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_b\").style(\"opacity\", opacityOpenTrade)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_t\").style(\"opacity\", opacityOpenTrade2)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_o_b\").style(\"opacity\", opacityHistoryTrade)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_c_b\").style(\"opacity\", opacityHistoryTrade)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_o_t\").style(\"opacity\", opacityHistoryTrade2)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_c_t\").style(\"opacity\", opacityHistoryTrade2)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_l\").style(\"opacity\", opacityHistoryTrade2)\n\t},\n\tfunction (context) { // Deinit()\n\t\tvar opacity = 0.5\n\t\tvar chartHandle = getChartHandleByContext(context)\n\t\tvar isGlobal = getIndiParameter(context, \"isGlobal\")\n\t\tvar canvas = isGlobal ? d3 : d3.select(\"#cc_k_c_d_\" + chartHandle)\n\n\t\tcanvas.selectAll(\".cc_k_c_p_o_l\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_t_l\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_s_l\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_b\").style(\"opacity\", opacity)\n\t\tcanvas.selectAll(\".cc_k_c_p_o_t\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_t_l\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_s_l\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_b\").style(\"opacity\", opacity)\n\t\tcanvas.selectAll(\".cc_k_c_o_t_t\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_o_b\").style(\"opacity\", opacity)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_c_b\").style(\"opacity\", opacity)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_o_t\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_c_t\").style(\"opacity\", 1)\n\t\tcanvas.selectAll(\".cc_k_c_h_t_l\").style(\"opacity\", 1)\n\t})\n"
  },
  {
    "path": "Indicators/cursor/cursor.js",
    "content": "registerIndicator(\"cursor\", \"Cursor on hover(v1.0)\", function (context) {\n  // Please note, this indicator will make scrolling chart disabled. So, if you want to scroll the chart, please remove this indicator from the chart.\n},[{\n  name: \"color\",\n  value: \"#AAA\",\n  required: true,\n  type: PARAMETER_TYPE.STRING,\n  range: null\n}, {\n  name: \"strokeWidth\",\n  value: 2,\n  required: true,\n  type: PARAMETER_TYPE.INTEGER,\n  range: [1, 10]\n}],\n[{\n\tname: DATA_NAME.TIME,\n\tindex: 0\n}, {\n\tname: DATA_NAME.CLOSE,\n\tindex: 1\n}],\n[{\n  name: \"line\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init()\n  var color = getIndiParameter(context, \"color\")\n  var strokeWidth = getIndiParameter(context, \"strokeWidth\")\n\n  context.cursor = {\n    timeArr: null,\n    priceArr: null,\n    canvas: null,\n    barNum: null,\n    cursor: null,\n    width: null,\n    height: null,\n    xScale: null,\n    yScale: null,\n    color: color,\n    xAxis: {\n\t\t\tstrokeWidth: strokeWidth,\n\t\t\tval: null\n    },\n\t\tyAxis: {\n\t\t\tstrokeWidth: strokeWidth,\n\t\t\tidx: null,\n\t\t\ttime: null\n    },\n    cursorFrame: null,\n    cursorXAxis: null,\n    cursorYAxis: null,\n    xAxisText: null,\n    yAxisText: null,\n    xAxisText2: null,\n    yAxisText2: null,\n\t\tmousemove: function (x, y) {\n\t\t\tif (context.cursor.timeArr == null) return\n\n\t\t\tvar canvas = context.cursor.canvas\n\t\t\tvar timeArr = context.cursor.timeArr\n\t\t\tvar barNum = context.cursor.barNum\n\t\t\tvar cursor = context.cursor.cursor\n\t\t\tvar width = context.cursor.width\n\t\t\tvar height = context.cursor.height\n\t\t\tvar xScale = context.cursor.xScale\n\t\t\tvar yScale = context.cursor.yScale\n\n\t\t\tvar idx = Math.round(xScale.invert(x))\n\t\t\tif (idx < 0) {\n\t\t\t\tidx = 0\n\t\t\t} else if (idx >= barNum) {\n\t\t\t\tidx = barNum - 1\n\t\t\t}\n\n\t\t\tvar val = y\n\t\t\tif (val < 0) {\n\t\t\t\tval = 0\n\t\t\t} else if (val > height) {\n\t\t\t\tval = height\n\t\t\t}\n\n\t\t\tcontext.cursor.xAxis.val = yScale.invert(val)\n\t\t\tcontext.cursor.yAxis.idx = idx\n\t\t\tcontext.cursor.yAxis.time = (idx + cursor) >= timeArr.length ? timeArr[timeArr.length - 1] : ((idx + cursor) < 0 ? timeArr[0] : timeArr[idx + cursor])\n\n\t\t\tthis.render()\n\t\t},\n\t\trender: function () {\n\t\t\tvar canvas = context.cursor.canvas\n\t\t\tvar timeArr = context.cursor.timeArr\n      var priceArr = context.cursor.priceArr\n\t\t\tvar barNum = context.cursor.barNum\n\t\t\tvar cursor = context.cursor.cursor\n\t\t\tvar width = context.cursor.width\n\t\t\tvar height = context.cursor.height\n\t\t\tvar xScale = context.cursor.xScale\n\t\t\tvar yScale = context.cursor.yScale\n\n\t\t\tcontext.cursor.cursorFrame\n\t\t\t\t.attr(\"width\", width)\n\t\t\t\t.attr(\"height\", height)\n\n      var y = yScale(context.cursor.xAxis.val)\n\t\t\tcontext.cursor.cursorXAxis\n\t\t\t\t.attr(\"x1\", xScale(0))\n\t\t\t\t.attr(\"y1\", y)\n\t\t\t\t.attr(\"x2\", xScale(barNum - 1))\n\t\t\t\t.attr(\"y2\", y)\n\n      var x = xScale(context.cursor.yAxis.idx)\n\t\t\tcontext.cursor.cursorYAxis\n\t\t\t\t.attr(\"x1\", x)\n\t\t\t\t.attr(\"y1\", 0)\n\t\t\t\t.attr(\"x2\", x)\n\t\t\t\t.attr(\"y2\", height)\n\n      context.cursor.xAxisText\n        .attr(\"y\", y)\n        .text(context.cursor.xAxis.val)\n\n\t\t\tcontext.cursor.yAxisText\n        .attr(\"x\", x)\n        .text(new Date(context.cursor.yAxis.time * 1000).toLocaleString())\n\n      context.cursor.xAxisText2\n        .attr(\"y\", y)\n        .text(context.cursor.xAxis.val - priceArr[priceArr.length - 1])\n\n\t\t\tcontext.cursor.yAxisText2\n        .attr(\"x\", x)\n        .text(timeArr.length - 1 - (cursor + context.cursor.yAxis.idx))\n\t\t}\n  }\n\n\tvar chartHandle = getChartHandleByContext(context)\n  context.cursor.canvas = getSvgCanvas(chartHandle)\n},\nfunction (context) { // Deinit()\n  var chartHandle = getChartHandleByContext(context)\n\n\tcontext.cursor.canvas.selectAll(\".cursorFrame\").data([]).exit().remove()\n  context.cursor.canvas.selectAll(\".cursorXAxis\").data([]).exit().remove()\n\tcontext.cursor.canvas.selectAll(\".cursorYAxis\").data([]).exit().remove()\n  context.cursor.canvas.selectAll(\".cursorXAxisText\").data([]).exit().remove()\n\tcontext.cursor.canvas.selectAll(\".cursorYAxisText\").data([]).exit().remove()\n  context.cursor.canvas.selectAll(\".cursorXAxisText2\").data([]).exit().remove()\n\tcontext.cursor.canvas.selectAll(\".cursorYAxisText2\").data([]).exit().remove()\n},\nfunction (context) { // Render()\n  var barNum = getBarNum(context)\n  var cursor = getCursor(context)\n  var width = getCanvasWidth(context)\n  var height = getCanvasHeight(context)\n  var xScale = getXScale(context)\n  var yScale = getYScale(context)\n\n\tif (getCalculatedLength(context) == 0) {\n    var timeArr = getDataInput(context, 0)\n\t\tcontext.cursor.timeArr = timeArr\n    context.cursor.priceArr = getDataInput(context, 1)\n\t\tcontext.cursor.xAxis.val = yScale.invert(height / 2)\n\t\tcontext.cursor.yAxis.idx = Math.floor(xScale.invert(width / 2))\n\t\tcontext.cursor.yAxis.time = (context.cursor.yAxis.idx + cursor) >= timeArr.length ? timeArr[timeArr.length - 1] : ((context.cursor.yAxis.idx + cursor) < 0 ? timeArr[0] : timeArr[context.cursor.yAxis.idx + cursor])\n\n\t\tvar canvas = context.cursor.canvas\n\n\t\tcontext.cursor.cursorFrame = canvas.selectAll(\".cursorFrame\").data([{}]).enter().append(\"rect\")\n\t\t\t.attr(\"class\", \"cursorFrame\")\n\t\t\t.attr(\"width\", width)\n\t\t\t.attr(\"height\", height)\n\t\t\t.attr(\"opacity\", 0)\n\t\t\t.on(\"mousemove\", function () {\n        var mouseX = d3.mouse(context.cursor.cursorFrame.node())[0] - context.cursor.cursorFrame.attr(\"x\")\n        var mouseY = d3.mouse(context.cursor.cursorFrame.node())[1] - context.cursor.cursorFrame.attr(\"y\")\n\t\t\t\tcontext.cursor.mousemove(mouseX, mouseY)\n\t\t\t})\n\n\t\tcontext.cursor.cursorXAxis = canvas.selectAll(\".cursorXAxis\").data([context.cursor.xAxis]).enter().append(\"line\")\n\t\t\t.attr(\"class\", \"cursorXAxis\")\n\t\t\t.attr(\"x1\", function (d) {return xScale(0)})\n\t\t\t.attr(\"y1\", function (d) {return yScale(d.val)})\n\t\t\t.attr(\"x2\", function (d) {return xScale(barNum - 1)})\n\t\t\t.attr(\"y2\", function (d) {return yScale(d.val)})\n      .attr(\"stroke\", context.cursor.color)\n\t\t\t.attr(\"strokeWidth\", function (d) {return d.strokeWidth})\n\n\t\tcontext.cursor.cursorYAxis = canvas.selectAll(\".cursorYAxis\").data([context.cursor.yAxis]).enter().append(\"line\")\n\t\t\t.attr(\"class\", \"cursorYAxis\")\n\t\t\t.attr(\"x1\", function (d) {return xScale(d.idx)})\n\t\t\t.attr(\"y1\", 0)\n\t\t\t.attr(\"x2\", function (d) {return xScale(d.idx)})\n\t\t\t.attr(\"y2\", height)\n\t\t\t.attr(\"stroke\", context.cursor.color)\n\t\t\t.attr(\"strokeWidth\", function (d) {return d.strokeWidth})\n\n    context.cursor.xAxisText = canvas.selectAll(\".cursorXAxisText\").data([context.cursor.xAxis]).enter().append(\"text\")\n      .attr(\"class\", \"cursorXAxisText\")\n      .attr(\"width\", \"50px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 30)\n      .attr(\"y\", function (d) {return yScale(d.val)})\n      .attr(\"dx\", -15)\n      .attr(\"dy\", -5)\n      .attr(\"fill\", context.cursor.color)\n      .attr(\"textAnchor\", \"start\")\n      .style(\"font-size\", \"12px\")\n      .text(function (d) {return d.val})\n\n    context.cursor.yAxisText = canvas.selectAll(\".cursorYAxisText\").data([context.cursor.yAxis]).enter().append(\"text\")\n      .attr(\"class\", \"cursorYAxisText\")\n      .attr(\"width\", \"50px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", function (d) {return xScale(d.idx)})\n      .attr(\"y\", 10)\n      .attr(\"dx\", 5)\n      .attr(\"dy\", 3)\n      .attr(\"fill\", context.cursor.color)\n      .attr(\"textAnchor\", \"start\")\n      .style(\"font-size\", \"12px\")\n      .text(function (d) {return new Date(d.time * 1000).toLocaleString()})\n\n    context.cursor.xAxisText2 = canvas.selectAll(\".cursorXAxisText2\").data([context.cursor.xAxis]).enter().append(\"text\")\n      .attr(\"class\", \"cursorXAxisText2\")\n      .attr(\"width\", \"50px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 30)\n      .attr(\"y\", function (d) {return yScale(d.val)})\n      .attr(\"dx\", -15)\n      .attr(\"dy\", 10)\n      .attr(\"fill\", context.cursor.color)\n      .attr(\"textAnchor\", \"start\")\n      .style(\"font-size\", \"12px\")\n      .text(function (d) {return d.val - context.cursor.priceArr[context.cursor.priceArr.length - 1]})\n\n    context.cursor.yAxisText2 = canvas.selectAll(\".cursorYAxisText2\").data([context.cursor.yAxis]).enter().append(\"text\")\n      .attr(\"class\", \"cursorYAxisText2\")\n      .attr(\"width\", \"50px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", function (d) {return xScale(d.idx)})\n      .attr(\"y\", 10)\n      .attr(\"dx\", 5)\n      .attr(\"dy\", 15)\n      .attr(\"fill\", context.cursor.color)\n      .attr(\"textAnchor\", \"start\")\n      .style(\"font-size\", \"12px\")\n      .text(function (d) {return timeArr.length - 1 - (cursor + d.idx)})\n  }\n\n\tcontext.cursor.barNum = barNum\n  context.cursor.cursor = cursor\n  context.cursor.width = width\n  context.cursor.height = height\n  context.cursor.xScale = xScale\n  context.cursor.yScale = yScale\n\n  context.cursor.render()\n})\n"
  },
  {
    "path": "Indicators/cursor/usage.txt",
    "content": "\"cursor\" is an implementation to show a cursor on the chart. The function to scroll the chart conflicts with this program. Therefore, if you want to scroll the chart, please remove this indicator from the chart.\n"
  },
  {
    "path": "Indicators/extra_fractals/README.md",
    "content": "![Fintechee extra fractals indicator](https://github.com/fintechees/Expert-Advisor-Studio/raw/master/Indicators/extra_fractals/extra_fractals_screenshot.png?raw=true)\n"
  },
  {
    "path": "Indicators/extra_fractals/extra_fractals.js",
    "content": "registerIndicator(\"extra_fractals\", \"An extended Fractals(v1.01)\", function (context) {\n  var dataInputHigh = getDataInput(context, 0)\n  var dataInputLow = getDataInput(context, 1)\n  var dataInputOpen = getDataInput(context, 2)\n  var dataInputClose = getDataInput(context, 3)\n  var dataOutputUp = getDataOutput(context, \"fractalsUp\")\n  var dataOutputDown = getDataOutput(context, \"fractalsDown\")\n  var dataOutputZZ = getDataOutput(context, \"zigzag\")\n  var dataOutputZZ2 = getDataOutput(context, \"zigzag2\")\n  var dataOutputZZUp = getDataOutput(context, \"zigzagUp\")\n  var dataOutputZZDown = getDataOutput(context, \"zigzagDown\")\n  var dataOutputZZUpIdx = getDataOutput(context, \"zigzagUpIdx\")\n  var dataOutputZZDownIdx = getDataOutput(context, \"zigzagDownIdx\")\n  var dataOutputZZLine = getDataOutput(context, \"zigzagLine\")\n\n  var calculatedLength = getCalculatedLength(context)\n\n  var ptr = 0\n\n  if (calculatedLength > 0) {\n    dataOutputZZ[calculatedLength - 1] = 0\n    dataOutputZZ2[calculatedLength - 1] = 0\n    dataOutputZZLine[calculatedLength - 1] = 0\n\n    ptr = calculatedLength - 4\n  } else {\n    for (var i = 0; i < dataInputHigh.length; i++) {\n      dataOutputUp[i] = 0\n      dataOutputDown[i] = 0\n      dataOutputZZ[i] = 0\n      dataOutputZZ2[i] = 0\n      dataOutputZZUp[i] = 0\n      dataOutputZZDown[i] = 0\n      dataOutputZZUpIdx[i] = 0\n      dataOutputZZDownIdx[i] = 0\n      dataOutputZZLine[i] = 0\n    }\n\n    ptr = 2\n  }\n\n  var highest = null\n  var lowest = null\n\n  while (ptr < dataInputHigh.length - 3) {\n    bHFound = false\n    highest = dataInputHigh[ptr]\n\n    if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) {\n      bHFound = true\n      dataOutputUp[ptr] = highest\n    }\n\n    bLFound = false\n    lowest = dataInputLow[ptr]\n\n    if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) {\n      bLFound = true\n      dataOutputDown[ptr] = lowest\n    }\n\n    ptr++\n  }\n\n  if (calculatedLength == 0) {\n    ptr = 2\n  } else {\n    ptr = calculatedLength - 4\n  }\n\n  while (ptr < dataInputHigh.length - 1) {\n    if (dataOutputUp[ptr] > 0) {\n      if (dataOutputZZUp[ptr - 1] > 0) {\n        dataOutputZZUp[ptr] = dataOutputZZUp[ptr - 1]\n      } else {\n        dataOutputZZUp[ptr] = dataOutputUp[ptr]\n      }\n      dataOutputZZUpIdx[ptr] = ptr\n    } else {\n      if (dataOutputUp[ptr - 1] > 0) {\n        dataOutputZZUp[ptr] = dataOutputUp[ptr - 1]\n      } else {\n        dataOutputZZUp[ptr] = dataOutputZZUp[ptr - 1]\n      }\n      dataOutputZZUpIdx[ptr] = dataOutputZZUpIdx[ptr - 1]\n    }\n\n    if (dataOutputDown[ptr] > 0) {\n      if (dataOutputZZDown[ptr - 1] > 0) {\n        dataOutputZZDown[ptr] = dataOutputZZDown[ptr - 1]\n      } else {\n        dataOutputZZDown[ptr] = dataOutputDown[ptr]\n      }\n      dataOutputZZDownIdx[ptr] = ptr\n    } else {\n      if (dataOutputDown[ptr - 1] > 0) {\n        dataOutputZZDown[ptr] = dataOutputDown[ptr - 1]\n      } else {\n        dataOutputZZDown[ptr] = dataOutputZZDown[ptr - 1]\n      }\n      dataOutputZZDownIdx[ptr] = dataOutputZZDownIdx[ptr - 1]\n    }\n\n    ptr++\n  }\n\n  if (ptr == dataInputHigh.length - 1) {\n    dataOutputZZUp[ptr] = dataOutputZZUp[ptr - 1]\n    dataOutputZZDown[ptr] = dataOutputZZDown[ptr - 1]\n    dataOutputZZUpIdx[ptr] = dataOutputZZUpIdx[ptr - 1]\n    dataOutputZZDownIdx[ptr] = dataOutputZZDownIdx[ptr - 1]\n  }\n\n  var zigzag = []\n\n  if (calculatedLength == 0) {\n    ptr = 5\n  } else {\n    ptr = calculatedLength - 2\n    var zzCnt = 0\n\n    while (zzCnt < 2) {\n      if (dataOutputZZ[ptr] > 0) {\n        zigzag.splice(0, 0, {\n          value: dataOutputZZ2[ptr],\n          index: ptr\n        })\n\n        zzCnt++\n      }\n\n      ptr--\n    }\n\n    ptr = calculatedLength - 1\n  }\n\n  while (ptr < dataInputHigh.length) {\n    if (dataOutputZZ[ptr] > 0) {\n      ptr++\n      continue\n    }\n\n    var orientation = -1\n\n    if (((dataInputHigh[ptr] >= dataOutputZZUp[ptr - 2] && dataInputLow[ptr] <= dataOutputZZUp[ptr - 2] && dataInputOpen[ptr] <= dataOutputZZUp[ptr - 2]) ||\n        (dataInputOpen[ptr] >= dataOutputZZUp[ptr - 2] && dataInputClose[ptr - 1] < dataOutputZZUp[ptr - 2])) && dataOutputZZ[ptr - 1] == 0 && dataOutputZZ[ptr - 2] == 0 &&\n        ((dataInputHigh[ptr] >= dataOutputZZDown[ptr - 2] && dataInputLow[ptr] <= dataOutputZZDown[ptr - 2] && dataInputOpen[ptr] >= dataOutputZZDown[ptr - 2]) ||\n        (dataInputClose[ptr - 1] > dataOutputZZDown[ptr - 2] && dataInputOpen[ptr] <= dataOutputZZDown[ptr - 2])) && dataOutputZZ[ptr - 1] == 0 && dataOutputZZ[ptr - 2] == 0) {\n\n      if (dataInputOpen[ptr] > dataInputClose[ptr]) {\n        orientation = 1\n      } else {\n        orientation = 0\n      }\n    }\n\n    if (orientation != 0 &&\n        ((dataInputHigh[ptr] >= dataOutputZZUp[ptr - 2] && dataInputLow[ptr] <= dataOutputZZUp[ptr - 2] && dataInputOpen[ptr] <= dataOutputZZUp[ptr - 2]) ||\n        (dataInputOpen[ptr] >= dataOutputZZUp[ptr - 2] && dataInputClose[ptr - 1] < dataOutputZZUp[ptr - 2])) && dataOutputZZ[ptr - 1] == 0 && dataOutputZZ[ptr - 2] == 0) {\n      var foundIdx = -1\n      var lowestZZ = Number.MAX_VALUE\n      var idx = dataOutputZZUpIdx[ptr - 2]\n\n      for (var i = idx; i < ptr; i++) {\n        if (dataInputLow[i] < lowestZZ) {\n          foundIdx = i\n          lowestZZ = dataInputLow[i]\n        }\n      }\n\n      if (foundIdx != -1) {\n        zigzag.push({\n          value: dataOutputZZUp[ptr - 2],\n          index: ptr\n        })\n        dataOutputZZ[ptr] = lowestZZ\n        dataOutputZZ2[ptr] = dataOutputZZUp[ptr - 2]\n      }\n    }\n\n    if (orientation != 1 &&\n        ((dataInputHigh[ptr] >= dataOutputZZDown[ptr - 2] && dataInputLow[ptr] <= dataOutputZZDown[ptr - 2] && dataInputOpen[ptr] >= dataOutputZZDown[ptr - 2]) ||\n        (dataInputClose[ptr - 1] > dataOutputZZDown[ptr - 2] && dataInputOpen[ptr] <= dataOutputZZDown[ptr - 2])) && dataOutputZZ[ptr - 1] == 0 && dataOutputZZ[ptr - 2] == 0) {\n      var foundIdx = -1\n      var highestZZ = -Number.MAX_VALUE\n      var idx = dataOutputZZDownIdx[ptr - 2]\n\n      for (var i = idx; i < ptr; i++) {\n        if (dataInputHigh[i] > highestZZ) {\n          foundIdx = i\n          highestZZ = dataInputHigh[i]\n        }\n      }\n\n      if (foundIdx != -1) {\n        zigzag.push({\n          value: dataOutputZZDown[ptr - 2],\n          index: ptr\n        })\n        dataOutputZZ[ptr] = highestZZ\n        dataOutputZZ2[ptr] = dataOutputZZDown[ptr - 2]\n      }\n    }\n\n    ptr++\n  }\n\n  for (var i = 1; i < zigzag.length; i++) {\n    var step = (zigzag[i].value - zigzag[i - 1].value) / (zigzag[i].index - zigzag[i - 1].index)\n    var nextIdx = zigzag[i].index\n    var startValue = zigzag[i - 1].value\n    var startIdx = zigzag[i - 1].index\n\n    for (var j = zigzag[i - 1].index; j < nextIdx; j++) {\n      dataOutputZZLine[j] = startValue + step * (j - startIdx)\n    }\n  }\n\n},[],\n[{\n  name: DATA_NAME.HIGH,\n  index: 0\n},{\n  name: DATA_NAME.LOW,\n  index: 1\n},{\n  name: DATA_NAME.OPEN,\n  index: 2\n},{\n  name: DATA_NAME.CLOSE,\n  index: 3\n}],\n[{\n  name: \"zigzagLine\",\n  visible: true,\n  renderType: RENDER_TYPE.LINE,\n  color: \"orange\"\n},{\n  name: \"zigzag\",\n  visible: false\n},{\n  name: \"zigzag2\",\n  visible: true,\n  renderType: RENDER_TYPE.ROUND,\n  color: \"orange\"\n},{\n  name: \"zigzagUp\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"green\"\n},{\n  name: \"zigzagDown\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"red\"\n},{\n  name: \"zigzagUpIdx\",\n  visible: false\n},{\n  name: \"zigzagDownIdx\",\n  visible: false\n},{\n  name: \"fractalsUp\",\n  visible: true,\n  renderType: RENDER_TYPE.ROUND,\n  color: \"green\"\n},{\n  name: \"fractalsDown\",\n  visible: true,\n  renderType: RENDER_TYPE.ROUND,\n  color: \"red\"\n}],\nWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/extra_fractals/usage.txt",
    "content": "\"Fractals\" is a very useful indicator to find breakout opportunities in an active market. However, the weakness of Fractal is that it is less intuitive. Therefore, we need auxiliary lines to help us check intuitively. \"Extra_fractals\" is an additional version that adds auxiliary lines automatically to the chart. Additionally, it adds a special ZigZag that connects with all the breakout points.\n"
  },
  {
    "path": "Indicators/extra_mfi/extra_mfi.js",
    "content": "registerIndicator(\"extra_mfi\", \"Market Facilitation Index Extra Version(v1.0)\", function (context) {\n  var dataInputHigh = getDataInput(context, 0)\n  var dataInputLow = getDataInput(context, 1)\n  var dataInputVol = getDataInput(context, 2)\n  var dataOutputMfi = getDataOutput(context, \"mfi\")\n  var dataOutput = getDataOutput(context, \"extramfi\")\n  var dataOutputLv = getDataOutput(context, \"level\")\n\n  var calculatedLength = getCalculatedLength(context)\n  var i = calculatedLength\n\n  if (i != 0) {\n    i--\n  }\n\n  while (i < dataInputVol.length) {\n    if (dataInputVol[i] == 0) {\n      dataOutputMfi[i] = 0\n    } else {\n      dataOutputMfi[i] = (dataInputHigh[i] - dataInputLow[i]) / dataInputVol[i]\n    }\n\n    dataOutputLv[i] = 0\n\n    if (i > 0) {\n      if (dataInputVol[i] > dataInputVol[i - 1] && dataOutputMfi[i] > dataOutputMfi[i - 1]) {\n        dataOutput[i] = 3\n      } else if (dataInputVol[i] > dataInputVol[i - 1] && dataOutputMfi[i] < dataOutputMfi[i - 1]) {\n        dataOutput[i] = 2\n        dataOutputLv[i] = 2\n      } else if (dataInputVol[i] < dataInputVol[i - 1] && dataOutputMfi[i] > dataOutputMfi[i - 1]) {\n        dataOutput[i] = 1\n      } else {\n        dataOutput[i] = 0\n      }\n    } else {\n      dataOutput[0] = 0\n    }\n\n    i++\n  }\n},[],\n[{\n  name: DATA_NAME.HIGH,\n  index: 0\n},{\n  name: DATA_NAME.LOW,\n  index: 1\n},{\n  name: DATA_NAME.VOLUME,\n  index: 2\n}],\n[{\n  name: \"mfi\",\n  visible: false\n},{\n  name: \"extramfi\",\n  visible: true,\n  renderType: RENDER_TYPE.LINE,\n  color: \"steelblue\"\n},{\n  name: \"level\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"orange\"\n}],\nWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/extra_mfi/extra_mfi_guide.txt",
    "content": "How to read this indicator?\n\nWhen the orange dasharray is equal to 2, that means the market is going to be reversal.\n"
  },
  {
    "path": "Indicators/extra_sar/extra_sar.js",
    "content": "registerIndicator(\"extra_sar\", \"Parabolic SAR(v1.0)\", function (context) {\n  var dataInputHigh = getDataInput(context, 0)\n  var dataInputLow = getDataInput(context, 1)\n\n  var dataOutput = getDataOutput(context, \"sar\")\n  var dataOutputIsLong = getDataOutput(context, \"isLong\")\n  var dataOutputAf = getDataOutput(context, \"af\")\n  var dataOutputEp = getDataOutput(context, \"ep\")\n\n  var acceleration = getIndiParameter(context, \"acceleration\")\n  var afMax = getIndiParameter(context, \"afMax\")\n  var shift = getIndiParameter(context, \"shift\")\n\n  var calculatedLength = getCalculatedLength(context)\n  var i = calculatedLength\n\n  var prevH = null\n  var prevL = null\n  var currH = null\n  var currL = null\n  var sar = null\n  var isLong = null\n  var af = acceleration\n  var ep = null\n\n  if (i > 0) {\n    i -= 2\n    prevH = dataInputHigh[i - 1]\n    prevL = dataInputLow[i - 1]\n    isLong = dataOutputIsLong[i]\n    sar = dataOutput[i]\n    af = dataOutputAf[i]\n    ep = dataOutputEp[i]\n  } else {\n    dataOutput[i] = 0\n    dataOutputIsLong[i] = true\n    dataOutputAf[i] = af\n    dataOutputEp[i] = 0\n\n    i = 1\n\n    prevH = dataInputHigh[i - 1]\n    prevL = dataInputLow[i - 1]\n    isLong = true\n    sar = prevL\n    ep = prevH\n  }\n\n  while (i < dataInputHigh.length) {\n    currH = dataInputHigh[i]\n    currL = dataInputLow[i]\n\n    if (isLong) {\n      if (currL <= sar) {\n        isLong = false\n        sar = Math.max(ep, currH, prevH)\n\n        dataOutput[i] = sar\n\n        af = acceleration\n        ep = currL\n        sar = sar + af * (ep - sar)\n        sar = Math.max(sar, currH, prevH)\n      } else {\n        dataOutput[i] = sar\n\n        if (currH > ep) {\n          ep = currH\n          if (af - dataOutputAf[i - 1] <= 0) {\n            af += acceleration\n          }\n          if (af > afMax) {\n            af = afMax\n          }\n        }\n        sar = sar + af * (ep - sar)\n        sar = Math.min(sar, currL, prevL)\n      }\n    } else {\n      if (currH >= sar) {\n        isLong = true\n        sar = Math.min(ep, currL, prevL)\n\n        dataOutput[i] = sar\n\n        af = acceleration\n        ep = currH\n        sar = sar + af * (ep - sar)\n        sar = Math.min(sar, currL, prevL)\n      } else {\n        dataOutput[i] = sar\n\n        if (currL < ep) {\n          ep = currL\n          if (af - dataOutputAf[i - 1] <= 0) {\n            af += acceleration\n          }\n          if (af > afMax) {\n            af = afMax\n          }\n        }\n        sar = sar + af * (ep - sar)\n        sar = Math.max(sar, currH, prevH)\n      }\n    }\n\n    dataOutputIsLong[i] = isLong\n    dataOutputAf[i] = af\n    dataOutputEp[i] = ep\n\n    i++\n\n    prevH = currH\n    prevL = currL\n  }\n\n  if (calculatedLength == 0) {\n    setIndiShift(context, \"sar\", shift)\n  }\n},[{\n  name: \"acceleration\",\n  value: 0.01,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.001, 0.1]\n},{\n  name: \"afMax\",\n  value: 0.05,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.01, 1]\n},{\n  name: \"shift\",\n  value: 1,\n  required: true,\n  type: PARAMETER_TYPE.INTEGER,\n  range: [0, 20]\n}],\n[{\n  name: DATA_NAME.HIGH,\n  index: 0\n},{\n  name: DATA_NAME.LOW,\n  index: 1\n}],\n[{\n  name: \"sar\",\n  visible: true,\n  renderType: RENDER_TYPE.ROUND,\n  color: \"steelblue\"\n},{\n  name: \"isLong\",\n  visible: false\n},{\n  name: \"af\",\n  visible: false\n},{\n  name: \"ep\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW)\n"
  },
  {
    "path": "Indicators/fibonacci_retracements/README.md",
    "content": "![Fintechee Fibonacci retracement indicator](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/fibonacci_retracements/fibonacci_retracements.png?raw=true)\n"
  },
  {
    "path": "Indicators/fibonacci_retracements/fibonacci_retracements.js",
    "content": "registerIndicator(\"fibonacci_retracements\", \"Fibonacci retracements viewer based on ZigZag(v1.0)\", function (context) {\n  var dataInputHigh = getDataInput(context, 0)\n  var dataInputLow = getDataInput(context, 1)\n\n  var dataOutputFibo = getDataOutput(context, \"fibo\")\n  var dataOutputZZLine = getDataOutput(context, \"zigzagLine\")\n  var dataOutputZZ = getDataOutput(context, \"zigzag\")\n  var dataOutput = getDataOutput(context, \"sar\")\n  var dataOutputIsLong = getDataOutput(context, \"isLong\")\n  var dataOutputAf = getDataOutput(context, \"af\")\n  var dataOutputEp = getDataOutput(context, \"ep\")\n  var fiboLevel0 = getDataOutput(context, \"fiboLevel0\")\n  var fiboLevel1 = getDataOutput(context, \"fiboLevel1\")\n  var fiboLevel2 = getDataOutput(context, \"fiboLevel2\")\n  var fiboLevel3 = getDataOutput(context, \"fiboLevel3\")\n\n  var acceleration = getIndiParameter(context, \"acceleration\")\n  var afMax = getIndiParameter(context, \"afMax\")\n\n  var arrLen = dataInputHigh.length\n  var calculatedLength = getCalculatedLength(context)\n  var i = calculatedLength\n\n  var prevH = null\n  var prevL = null\n  var currH = null\n  var currL = null\n  var sar = null\n  var isLong = null\n  var af = acceleration\n  var ep = null\n\n  if (i > 0) {\n    i -= 2\n    prevH = dataInputHigh[i - 1]\n    prevL = dataInputLow[i - 1]\n    isLong = dataOutputIsLong[i]\n    sar = dataOutput[i]\n    af = dataOutputAf[i]\n    ep = dataOutputEp[i]\n  } else {\n    dataOutput[i] = 0\n    dataOutputIsLong[i] = true\n    dataOutputAf[i] = af\n    dataOutputEp[i] = 0\n\n    i = 1\n\n    prevH = dataInputHigh[i - 1]\n    prevL = dataInputLow[i - 1]\n    isLong = true\n    sar = prevL\n    ep = prevH\n  }\n\n  while (i < arrLen) {\n    currH = dataInputHigh[i]\n    currL = dataInputLow[i]\n\n    if (isLong) {\n      if (currL <= sar) {\n        isLong = false\n        sar = Math.max(ep, currH, prevH)\n\n        dataOutput[i] = sar\n\n        af = acceleration\n        ep = currL\n        sar = sar + af * (ep - sar)\n        sar = Math.max(sar, currH, prevH)\n      } else {\n        dataOutput[i] = sar\n\n        if (currH > ep) {\n          ep = currH\n          if (af - dataOutputAf[i - 1] <= 0) {\n            af += acceleration\n          }\n          if (af > afMax) {\n            af = afMax\n          }\n        }\n        sar = sar + af * (ep - sar)\n        sar = Math.min(sar, currL, prevL)\n      }\n    } else {\n      if (currH >= sar) {\n        isLong = true\n        sar = Math.min(ep, currL, prevL)\n\n        dataOutput[i] = sar\n\n        af = acceleration\n        ep = currH\n        sar = sar + af * (ep - sar)\n        sar = Math.min(sar, currL, prevL)\n      } else {\n        dataOutput[i] = sar\n\n        if (currL < ep) {\n          ep = currL\n          if (af - dataOutputAf[i - 1] <= 0) {\n            af += acceleration\n          }\n          if (af > afMax) {\n            af = afMax\n          }\n        }\n        sar = sar + af * (ep - sar)\n        sar = Math.max(sar, currH, prevH)\n      }\n    }\n\n    dataOutputIsLong[i] = isLong\n    dataOutputAf[i] = af\n    dataOutputEp[i] = ep\n\n    i++\n\n    prevH = currH\n    prevL = currL\n  }\n\n  var zigzag = []\n  var latestZZ = null\n  var latestZZIdx = -1\n  var latestZZ2 = null\n\n  if (calculatedLength > 0) {\n    dataOutputZZ[calculatedLength - 1] = 0\n    dataOutputZZLine[calculatedLength - 1] = 0\n    dataOutputFibo[calculatedLength - 1] = 0\n    fiboLevel0[calculatedLength - 1] = 0.382\n    fiboLevel1[calculatedLength - 1] = 0.5\n    fiboLevel2[calculatedLength - 1] = 0.618\n    fiboLevel3[calculatedLength - 1] = 1.618\n\n    for (i = arrLen - 1; i >= 0; i--) {\n      if (dataOutputZZ[i] != 0) {\n        if (latestZZ == null) {\n          latestZZ = {\n            value: dataOutputZZ[i],\n            index: i\n          }\n\n          latestZZIdx = i\n        } else {\n          latestZZ2 = {\n            value: dataOutputZZ[i],\n            index: i\n          }\n\n          break\n        }\n      }\n    }\n  } else {\n    dataOutputZZ[0] = (dataInputHigh[0] + dataInputLow[0]) / 2\n    dataOutputZZLine[0] = dataOutputZZ[0]\n    dataOutputFibo[0] = 0\n\n    for (i = 1; i < arrLen; i++) {\n      dataOutputZZ[i] = 0\n      fiboLevel0[i] = 0.382\n      fiboLevel1[i] = 0.5\n      fiboLevel2[i] = 0.618\n      fiboLevel3[i] = 1.618\n    }\n\n    latestZZ = {\n      value: dataOutputZZ[0],\n      index: 0\n    }\n\n    latestZZIdx = 0\n  }\n\n  i = arrLen - 1\n\n  var foundIdx = -1\n  var lowestZZ = Number.MAX_VALUE\n  var highestZZ = -Number.MAX_VALUE\n\n  var bNextLong = dataOutputIsLong[i]\n\n  while (i >= 0 && i >= latestZZIdx) {\n    if (dataOutputIsLong[i]) {\n      if (bNextLong && i != 0) {\n        if (dataInputHigh[i] > highestZZ) {\n          foundIdx = i\n          highestZZ = dataInputHigh[i]\n        }\n      } else {\n        if (foundIdx != -1) {\n          zigzag.splice(0, 0, {\n            value: lowestZZ,\n            index: foundIdx\n          })\n        }\n\n        foundIdx = i\n        lowestZZ = Number.MAX_VALUE\n        highestZZ = dataInputHigh[i]\n\n        bNextLong = true\n      }\n    } else {\n      if (!bNextLong && i != 0) {\n        if (dataInputLow[i] < lowestZZ) {\n          foundIdx = i\n          lowestZZ = dataInputLow[i]\n        }\n      } else {\n        if (foundIdx != -1) {\n          zigzag.splice(0, 0, {\n            value: highestZZ,\n            index: foundIdx\n          })\n        }\n\n        foundIdx = i\n        lowestZZ = dataInputLow[i]\n        highestZZ = -Number.MAX_VALUE\n\n        bNextLong = false\n      }\n    }\n\n    i--\n  }\n\n  zigzag.splice(0, 0, latestZZ)\n  if (calculatedLength > 0) {\n    zigzag.splice(0, 0, latestZZ2)\n  }\n\n  var zzLen = zigzag.length > 1 ? (zigzag.length - 1) : 1\n\n  for (i = 0; i < zzLen; i++) {\n    dataOutputZZ[zigzag[i].index] = zigzag[i].value\n  }\n\n  if (arrLen - 1 > zigzag[zigzag.length - 1].index) {\n    zigzag.push({\n      value: (dataInputHigh[arrLen - 1] + dataInputLow[arrLen - 1]) / 2,\n      index: arrLen - 1\n    })\n  }\n\n  var height = 0\n  var zigzagLen = zigzag.length\n\n  for (i = 2; i < zigzagLen; i++) {\n    var step = (zigzag[i].value - zigzag[i - 1].value) / (zigzag[i].index - zigzag[i - 1].index)\n    var nextIdx = zigzag[i].index\n    var startValue = zigzag[i - 1].value\n    var startIdx = zigzag[i - 1].index\n    height = Math.abs(zigzag[i - 2].value - zigzag[i - 1].value)\n\n    for (var j = zigzag[i - 1].index; j < nextIdx; j++) {\n      dataOutputZZLine[j] = startValue + step * (j - startIdx)\n      if (height == 0) {\n        dataOutputFibo[j] = 0\n      } else {\n        dataOutputFibo[j] = Math.abs(dataOutputZZLine[j] - zigzag[i - 1].value) / height\n      }\n    }\n  }\n\n  if (zigzagLen >= 3) {\n    height = Math.abs(zigzag[zigzagLen - 3].value - zigzag[zigzagLen - 2].value)\n\n    dataOutputZZLine[arrLen - 1] = zigzag[zigzagLen - 1].value\n    dataOutputFibo[arrLen - 1] = Math.abs(zigzag[zigzagLen - 2].value - zigzag[zigzagLen - 1].value) / height\n  } else {\n    dataOutputFibo[arrLen - 1] = 0\n  }\n},[{\n  name: \"acceleration\",\n  value: 0.01,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.001, 0.1]\n},{\n  name: \"afMax\",\n  value: 0.05,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.01, 1]\n}],\n[{\n  name: DATA_NAME.HIGH,\n  index: 0\n},{\n  name: DATA_NAME.LOW,\n  index: 1\n}],\n[{\n  name: \"fibo\",\n  visible: true,\n  renderType: RENDER_TYPE.LINE,\n  color: \"orange\"\n},{\n  name: \"zigzagLine\",\n  visible: false\n},{\n  name: \"zigzag\",\n  visible: false\n},{\n  name: \"sar\",\n  visible: false\n},{\n  name: \"isLong\",\n  visible: false\n},{\n  name: \"af\",\n  visible: false\n},{\n  name: \"ep\",\n  visible: false\n},{\n  name: \"fiboLevel0\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"#AAAAAA\"\n},{\n  name: \"fiboLevel1\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"#AAAAAA\"\n},{\n  name: \"fiboLevel2\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"#AAAAAA\"\n},{\n  name: \"fiboLevel3\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"#AAAAAA\"\n}],\nWHERE_TO_RENDER.SEPARATE_WINDOW)\n"
  },
  {
    "path": "Indicators/fibonacci_retracements/usage.txt",
    "content": "Fibonacci retracements are always used to identify market reversal opportunities. Traditionally, we would check for Fibonacci retracements on the same chart using auxiliary lines. However, this indicator uses a simpler approach by displaying breakout points and auxiliary lines in a separate window.\n"
  },
  {
    "path": "Indicators/order_buttons/README.md",
    "content": "This plugin is used to add a widget on the chart. Then you can send market orders via chart directly.\n"
  },
  {
    "path": "Indicators/order_buttons/order_buttons.js",
    "content": "registerIndicator(\"order_buttons\", \"A chart widget with the buttons to send market orders(v1.0)\", function (context) {\n},[{\n  name: \"lotsStep\",\n  value: 0.01,\n  required: true,\n  type: PARAMETER_TYPE.NUMBER,\n  range: [0.01, 10]\n}],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"line\",\n  visible: false\n}],\nWHERE_TO_RENDER.CHART_WINDOW,\nfunction (context) { // Init()\n  var chartHandle = getChartHandleByContext(context)\n  context.lotsStep = getIndiParameter(context, \"lotsStep\")\n\n  if (typeof window.orderButtons == \"undefined\" || window.orderButtons == null) {\n    window.orderButtons = {\n      canvas: [],\n      lots: [],\n      brokerName: getBrokerNameByContext(context),\n      accountId: getAccountIdByContext(context),\n      symbolName: []\n    }\n  }\n\n  window.orderButtons.canvas[chartHandle] = getSvgCanvas(chartHandle)\n  window.orderButtons.lots[chartHandle] = context.lotsStep\n  window.orderButtons.symbolName[chartHandle] = getChartSymbolNameByContext(context)\n},\nfunction (context) { // Deinit()\n  var chartHandle = getChartHandleByContext(context)\n\n  window.orderButtons.canvas[chartHandle].selectAll(\".btnBuyG\").data([]).exit().remove()\n  window.orderButtons.canvas[chartHandle].selectAll(\".btnIncreaseLotsG\").data([]).exit().remove()\n  window.orderButtons.canvas[chartHandle].selectAll(\".lotsG\").data([]).exit().remove()\n  window.orderButtons.canvas[chartHandle].selectAll(\".btnDecreaseLotsG\").data([]).exit().remove()\n  window.orderButtons.canvas[chartHandle].selectAll(\".btnSellG\").data([]).exit().remove()\n  delete window.orderButtons.canvas[chartHandle]\n  delete window.orderButtons.lots[chartHandle]\n  delete window.orderButtons.symbolName[chartHandle]\n},\nfunction (context) { // Render()\n  var chartHandle = getChartHandleByContext(context)\n  var width = getCanvasWidth(context)\n  var height = getCanvasHeight(context)\n\n  var buyButton = [{\n    chartHandle: chartHandle,\n    label: \"Buy\"\n  }]\n  var btnBuyG = null\n  var btnBuy = null\n  var btnBuyTxt = null\n  var increaseLotsButton = [{\n    chartHandle: chartHandle,\n    label: \"+\"\n  }]\n  var btnIncreaseLotsG = null\n  var btnIncreaseLots = null\n  var btnIncreaseLotsTxt = null\n  var lotsRect = [{\n    chartHandle: chartHandle\n  }]\n  var lotsG = null\n  var lots = null\n  var lotsTxt = null\n  var decreaseLotsButton = [{\n    chartHandle: chartHandle,\n    label: \"-\"\n  }]\n  var btnDecreaseLotsG = null\n  var btnDecreaseLots = null\n  var btnDecreaseLotsTxt = null\n  var sellButton = [{\n    chartHandle: chartHandle,\n    label: \"Sell\"\n  }]\n  var btnSellG = null\n  var btnSell = null\n  var btnSellTxt = null\n\n  if (getCalculatedLength(context) == 0) {\n    btnBuyG = window.orderButtons.canvas[chartHandle].append(\"g\")\n      .attr(\"class\", \"btnBuyG\")\n    btnIncreaseLotsG = window.orderButtons.canvas[chartHandle].append(\"g\")\n      .attr(\"class\", \"btnIncreaseLotsG\")\n    lotsG = window.orderButtons.canvas[chartHandle].append(\"g\")\n      .attr(\"class\", \"lotsG\")\n    btnDecreaseLotsG = window.orderButtons.canvas[chartHandle].append(\"g\")\n      .attr(\"class\", \"btnDecreaseLotsG\")\n    btnSellG = window.orderButtons.canvas[chartHandle].append(\"g\")\n      .attr(\"class\", \"btnSellG\")\n\n    btnBuy = btnBuyG.selectAll(\".btnBuy\").data(buyButton)\n    btnBuyTxt = btnBuyG.selectAll(\".btnBuyTxt\").data(buyButton)\n    btnIncreaseLots = btnIncreaseLotsG.selectAll(\".btnIncreaseLots\").data(increaseLotsButton)\n    btnIncreaseLotsTxt = btnIncreaseLotsG.selectAll(\".btnIncreaseLotsTxt\").data(increaseLotsButton)\n    lots = lotsG.selectAll(\".lots\").data(lotsRect)\n    lotsTxt = lotsG.selectAll(\".lotsTxt\").data(lotsRect)\n    btnDecreaseLots = btnDecreaseLotsG.selectAll(\".btnDecreaseLots\").data(decreaseLotsButton)\n    btnDecreaseLotsTxt = btnDecreaseLotsG.selectAll(\".btnDecreaseLotsTxt\").data(decreaseLotsButton)\n    btnSell = btnSellG.selectAll(\".btnSell\").data(sellButton)\n    btnSellTxt = btnSellG.selectAll(\".btnSellTxt\").data(sellButton)\n\n    var sendMarketOrder = function (d, orderType) {\n      var brokerName = window.orderButtons.brokerName\n      var accountId = window.orderButtons.accountId\n      var symbolName = window.orderButtons.symbolName[d.chartHandle]\n      var volume = window.orderButtons.lots[d.chartHandle]\n      sendOrder(brokerName, accountId, symbolName, orderType, 0, 0, volume, 0, 0, \"\", 0, 0)\n    }\n\n    btnBuy\n      .enter().append(\"rect\")\n      .attr(\"class\", \"btnBuy\")\n      .attr(\"x\", width - 57)\n      .attr(\"y\", 7)\n      .attr(\"width\", 50)\n      .attr(\"height\", 30)\n      .attr(\"stroke\", \"white\")\n      .attr(\"fill\", \"green\")\n      .style(\"cursor\", \"pointer\")\n      .on(\"click\", function (d) {\n        sendMarketOrder(d, ORDER_TYPE.OP_BUY)\n      })\n\n    btnBuyTxt\n      .enter().append(\"text\")\n      .attr(\"class\", \"btnBuyTxt\")\n      .attr(\"width\", \"10px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 37)\n      .attr(\"y\", 22)\n      .attr(\"dx\", -5)\n      .attr(\"dy\", 5)\n      .attr(\"fill\", \"white\")\n      .attr(\"textAnchor\", \"start\")\n      .style(\"fontSize\", \"8px\")\n      .style(\"cursor\", \"pointer\")\n      .text(function (d) {\n        return d.label\n      })\n      .on(\"click\", function (d) {\n        sendMarketOrder(d, ORDER_TYPE.OP_BUY)\n      })\n\n    var increaseLots = function (d) {\n      var currLots = parseFloat(window.orderButtons.lots[d.chartHandle])\n      currLots += context.lotsStep\n      currLots = Math.round(currLots * 100) /  100\n      window.orderButtons.lots[d.chartHandle] = currLots\n      var currLotsTxt = window.orderButtons.canvas[d.chartHandle].selectAll(\".lotsTxt\")\n      currLotsTxt.text(currLots)\n    }\n\n    btnIncreaseLots\n      .enter().append(\"rect\")\n      .attr(\"class\", \"btnIncreaseLots\")\n      .attr(\"x\", width - 67)\n      .attr(\"y\", 7)\n      .attr(\"width\", 10)\n      .attr(\"height\", 30)\n      .attr(\"stroke\", \"white\")\n      .attr(\"fill\", \"green\")\n      .style(\"cursor\", \"pointer\")\n      .on(\"click\", function (d) {\n        increaseLots(d)\n      })\n\n    btnIncreaseLotsTxt\n      .enter().append(\"text\")\n      .attr(\"class\", \"btnIncreaseLotsTxt\")\n      .attr(\"width\", \"10px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 62)\n      .attr(\"y\", 22)\n      .attr(\"dx\", -5)\n      .attr(\"dy\", 5)\n      .attr(\"fill\", \"white\")\n      .attr(\"textAnchor\", \"start\")\n      .style(\"fontSize\", \"8px\")\n      .style(\"cursor\", \"pointer\")\n      .text(function (d) {\n        return d.label\n      })\n      .on(\"click\", function (d) {\n        increaseLots(d)\n      })\n\n    lots\n      .enter().append(\"rect\")\n      .attr(\"class\", \"lots\")\n      .attr(\"x\", width - 117)\n      .attr(\"y\", 7)\n      .attr(\"width\", 50)\n      .attr(\"height\", 30)\n      .attr(\"stroke\", \"white\")\n      .attr(\"fill\", \"white\")\n\n    lotsTxt\n      .enter().append(\"text\")\n      .attr(\"class\", \"lotsTxt\")\n      .attr(\"width\", \"10px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 102)\n      .attr(\"y\", 22)\n      .attr(\"dx\", -5)\n      .attr(\"dy\", 5)\n      .attr(\"fill\", \"black\")\n      .attr(\"textAnchor\", \"start\")\n      .style(\"fontSize\", \"8px\")\n      .text(function (d) {\n        return window.orderButtons.lots[d.chartHandle]\n      })\n\n    var decreaseLots = function (d) {\n      var currLots = parseFloat(window.orderButtons.lots[d.chartHandle])\n      if (currLots - context.lotsStep == 0) return\n      currLots -= context.lotsStep\n      currLots = Math.round(currLots * 100) /  100\n      window.orderButtons.lots[d.chartHandle] = currLots\n      var currLotsTxt = window.orderButtons.canvas[d.chartHandle].selectAll(\".lotsTxt\")\n      currLotsTxt.text(currLots)\n    }\n\n    btnDecreaseLots\n      .enter().append(\"rect\")\n      .attr(\"class\", \"btnDecreaseLots\")\n      .attr(\"x\", width - 127)\n      .attr(\"y\", 7)\n      .attr(\"width\", 10)\n      .attr(\"height\", 30)\n      .attr(\"stroke\", \"white\")\n      .attr(\"fill\", \"red\")\n      .style(\"cursor\", \"pointer\")\n      .on(\"click\", function (d) {\n        decreaseLots(d)\n      })\n\n    btnDecreaseLotsTxt\n      .enter().append(\"text\")\n      .attr(\"class\", \"btnDecreaseLotsTxt\")\n      .attr(\"width\", \"10px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 120)\n      .attr(\"y\", 22)\n      .attr(\"dx\", -5)\n      .attr(\"dy\", 5)\n      .attr(\"fill\", \"white\")\n      .attr(\"textAnchor\", \"start\")\n      .style(\"fontSize\", \"8px\")\n      .style(\"cursor\", \"pointer\")\n      .text(function (d) {\n        return d.label\n      })\n      .on(\"click\", function (d) {\n        decreaseLots(d)\n      })\n\n    btnSell\n      .enter().append(\"rect\")\n      .attr(\"class\", \"btnSell\")\n      .attr(\"x\", width - 177)\n      .attr(\"y\", 7)\n      .attr(\"width\", 50)\n      .attr(\"height\", 30)\n      .attr(\"stroke\", \"white\")\n      .attr(\"fill\", \"red\")\n      .style(\"cursor\", \"pointer\")\n      .on(\"click\", function (d) {\n        sendMarketOrder(d, ORDER_TYPE.OP_SELL)\n      })\n\n    btnSellTxt\n      .enter().append(\"text\")\n      .attr(\"class\", \"btnSellTxt\")\n      .attr(\"width\", \"10px\")\n      .attr(\"height\", \"10px\")\n      .attr(\"x\", width - 157)\n      .attr(\"y\", 22)\n      .attr(\"dx\", -5)\n      .attr(\"dy\", 5)\n      .attr(\"fill\", \"white\")\n      .attr(\"textAnchor\", \"start\")\n      .style(\"fontSize\", \"8px\")\n      .style(\"cursor\", \"pointer\")\n      .text(function (d) {\n        return d.label\n      })\n      .on(\"click\", function (d) {\n        sendMarketOrder(d, ORDER_TYPE.OP_SELL)\n      })\n\n  } else {\n    btnBuy = window.orderButtons.canvas[chartHandle].selectAll(\".btnBuy\").data(buyButton)\n    btnBuyTxt = window.orderButtons.canvas[chartHandle].selectAll(\".btnBuyTxt\").data(buyButton)\n\n    btnBuy\n      .attr(\"x\", width - 57)\n\n    btnBuyTxt\n      .attr(\"x\", width - 37)\n\n    btnIncreaseLots = window.orderButtons.canvas[chartHandle].selectAll(\".btnIncreaseLots\").data(increaseLotsButton)\n    btnIncreaseLotsTxt = window.orderButtons.canvas[chartHandle].selectAll(\".btnIncreaseLotsTxt\").data(increaseLotsButton)\n\n    btnIncreaseLots\n      .attr(\"x\", width - 67)\n\n    btnIncreaseLotsTxt\n      .attr(\"x\", width - 62)\n\n    lots = window.orderButtons.canvas[chartHandle].selectAll(\".lots\").data(lotsRect)\n    lotsTxt = window.orderButtons.canvas[chartHandle].selectAll(\".lotsTxt\").data(lotsRect)\n\n    lots\n      .attr(\"x\", width - 117)\n\n    lotsTxt\n      .attr(\"x\", width - 102)\n\n    btnDecreaseLots = window.orderButtons.canvas[chartHandle].selectAll(\".btnDecreaseLots\").data(decreaseLotsButton)\n    btnDecreaseLotsTxt = window.orderButtons.canvas[chartHandle].selectAll(\".btnDecreaseLotsTxt\").data(decreaseLotsButton)\n\n    btnDecreaseLots\n      .attr(\"x\", width - 127)\n\n    btnDecreaseLotsTxt\n      .attr(\"x\", width - 120)\n\n    btnSell = window.orderButtons.canvas[chartHandle].selectAll(\".btnSell\").data(sellButton)\n    btnSellTxt = window.orderButtons.canvas[chartHandle].selectAll(\".btnSellTxt\").data(sellButton)\n\n    btnSell\n      .attr(\"x\", width - 177)\n\n    btnSellTxt\n      .attr(\"x\", width - 157)\n  }\n})\n"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/equity_curve.js",
    "content": "registerIndicator(\"equity_curve\", \"An indicator to show the equity and the balance of an account(v1.02)\", function (context) {\n  var dataInput = getDataInput(context, 0)\n  var dataOutputEq = getDataOutput(context, \"equity\")\n  var dataOutputBl = getDataOutput(context, \"balance\")\n\n  if (typeof window.accounts != \"undefined\" && typeof window.accounts[context.chartHandle] != \"undefined\" && typeof window.accounts[context.chartHandle].equity != \"undefined\") {\n    context.equity = window.accounts[context.chartHandle].equity\n    context.balance = window.accounts[context.chartHandle].balance\n  }\n\n  var calculatedLength = getCalculatedLength(context)\n  var i = calculatedLength\n\n  if (i > 0) {\n    i--\n  }\n\n  while (i < dataInput.length) {\n    dataOutputEq[i] = typeof context.equity == \"undefined\" ? 0 : (typeof context.equity[i] == \"undefined\" ? (i > 0 ? context.equity[i - 1] : 0) : context.equity[i])\n    dataOutputBl[i] = typeof context.balance == \"undefined\" ? 0 : (typeof context.balance[i] == \"undefined\" ? (i > 0 ? context.balance[i - 1] : 0) : context.balance[i])\n\n    i++\n  }\n},[{\n\tname: \"chartHandle\",\n\tvalue: 0,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: null,\n}],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"equity\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"steelblue\"\n}, {\n  name: \"balance\",\n  visible: true,\n  renderType: RENDER_TYPE.LINE,\n  color: \"green\"\n}],\nWHERE_TO_RENDER.SEPARATE_WINDOW,\nfunction (context) { // init\n  context.chartHandle = getIndiParameter(context, \"chartHandle\")\n\n  if (typeof window.accounts != \"undefined\" && typeof window.accounts[context.chartHandle] != \"undefined\" && typeof window.accounts[context.chartHandle].equity != \"undefined\") {\n    context.equity = window.accounts[context.chartHandle].equity\n    context.balance = window.accounts[context.chartHandle].balance\n  } else {\n    popupErrorMessage(\"Please note, this indicator(equity_curve) can't be used independently. An EA called \\\"equity_curve_viewer\\\" that serves as an initiator should be used with this one simultaneously. You need to define an window object in the source codes of your EA that tries to refer to this indicator to manage the information about the equity and the balance. Please specify chartHandle as the index number of the window object before getting the handle of this indicator.\")\n  }\n},\nfunction (context) { // deinit\n  if (typeof window.accounts != \"undefined\" && typeof window.accounts[context.chartHandle] != \"undefined\" && typeof window.accounts[context.chartHandle].equity != \"undefined\") {\n    delete window.accounts[context.chartHandle].equity\n    delete window.accounts[context.chartHandle].balance\n  }\n},\nfunction (context) { // render\n})\n"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/equity_curve_viewer.js",
    "content": "registerEA(\n  \"equity_curve_viewer\",\n  \"An EA used for watching the information about the equity and the balance of an account(v1.0)\",\n  [{ // parameters\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  },{\n    name: \"timeFrame\",\n    value: TIME_FRAME.H1,\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function (context) { // Init()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n    var timeFrame = getEAParameter(context, \"timeFrame\")\n\n    context.tradingManager = {\n      equity: 0,\n      balance: 0,\n      getAccountInfo: function (account) {\n        this.equity = getEquityOfAccount(account)\n        this.balance = getBalanceOfAccount(account) + getPLOfAccount(account)\n\n        var arrEquity = window.accounts[context.chartHandle].equity\n        var arrBalance = window.accounts[context.chartHandle].balance\n        var arrEquityLen = arrEquity.length\n        for (var i = arrEquityLen; i < context.arrEquityLen; i++) {\n          arrEquity.push(0)\n          arrBalance.push(0)\n        }\n\n        arrEquity[context.arrEquityLen - 1] = this.equity\n        arrBalance[context.arrEquityLen - 1] = this.balance\n      }\n    }\n\n    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n    if (typeof window.accounts == \"undefined\") {\n      window.accounts = []\n    }\n    if (typeof window.accounts[context.chartHandle] == \"undefined\") {\n      window.accounts[context.chartHandle] = {\n        equity: [],\n        balance: []\n      }\n    } else {\n      window.accounts[context.chartHandle].equity = []\n      window.accounts[context.chartHandle].balance = []\n    }\n    context.equityHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"equity_curve\", [{\n      name: \"chartHandle\", value: context.chartHandle}])\n  },\n  function (context) { // Deinit()\n  },\n  function (context) { // OnTick()\n    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n    context.arrEquityLen = arrTime.length\n\n    var account = getAccount(context, 0)\n\n    context.tradingManager.getAccountInfo(account)\n  },\n  function (context) { // OnTransaction()\n  }\n)\n"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/how_to_use_equity_curve_unrealized_pl.txt",
    "content": "Almost all the indicators' charts are based on candlesticks or another indicator's output.\nWe can use almost all the indicators independently.\n\nBut equity_curve and unrealized_pl are different from the common indicators.\nTheir data are generated by the account information, such as equity and unrealized profit/loss.\nAnd, our APIs to get the account information can be used only in the EAs.\nSo, we need an EA to serve as an assistant to transfer the account infomation from APIs used by EAs to indicators.\n\nIf you check the current folder, you can find equity_curve_viewer and unrealized_pl_viewer that serve as the assistants.\n\nOur trading platform has a very convenient function. You can specify the indicators used in an EA and get the indicators' output by controlling the handles of the indicators.\nSo, if you launch the EA that retrieves some indicators' output, the indicators will be loaded and attached to the chart automatically.\n\nIf you want to use equity_curve or unrealized_pl, what you need to do is to run equity_curve_viewer or unrealized_pl_viewer(please note both equity_curve_viewer and unrealized_pl_viewer are EAs, not indicators).\nThen equity_curve or unrealized_pl will be loaded and attached to the chart.\nYou can add other indicators to the charts in the same way.(Of course, you can add other indicators by choosing them on the toolbar menu as well. This way is more common.)\n"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/unrealized_pl.js",
    "content": "registerIndicator(\"unrealized_pl\", \"An indicator to show the unrealized PL of an account(v1.05)\", function (context) {\n  var dataInput = getDataInput(context, 0)\n  var dataOutputPl = getDataOutput(context, \"totalPl\")\n  var dataOutputPlL = getDataOutput(context, \"totalPlL\")\n  var dataOutputPlS = getDataOutput(context, \"totalPlS\")\n\n  if (typeof window.accounts != \"undefined\" && typeof window.accounts[context.chartHandle] != \"undefined\" && typeof window.accounts[context.chartHandle].totalPl != \"undefined\") {\n    context.totalPl = window.accounts[context.chartHandle].totalPl\n    context.totalPlL = window.accounts[context.chartHandle].totalPlL\n    context.totalPlS = window.accounts[context.chartHandle].totalPlS\n  }\n\n  var calculatedLength = getCalculatedLength(context)\n  var i = calculatedLength\n\n  if (i > 0) {\n    i--\n  }\n\n  while (i < dataInput.length) {\n    dataOutputPl[i] = typeof context.totalPl == \"undefined\" ? 0 : (typeof context.totalPl[i] == \"undefined\" ? (i > 0 ? context.totalPl[i - 1] : 0) : context.totalPl[i])\n    dataOutputPlL[i] = typeof context.totalPlL == \"undefined\" ? 0 : (typeof context.totalPlL[i] == \"undefined\" ? (i > 0 ? context.totalPlL[i - 1] : 0) : context.totalPlL[i])\n    dataOutputPlS[i] = typeof context.totalPlS == \"undefined\" ? 0 : (typeof context.totalPlS[i] == \"undefined\" ? (i > 0 ? context.totalPlS[i - 1] : 0) : context.totalPlS[i])\n\n    i++\n  }\n},[{\n\tname: \"chartHandle\",\n\tvalue: 0,\n\trequired: true,\n\ttype: \"Integer\",\n\trange: null,\n}],\n[{\n  name: DATA_NAME.TIME,\n  index: 0\n}],\n[{\n  name: \"totalPl\",\n  visible: true,\n  renderType: RENDER_TYPE.LINE,\n  color: \"steelblue\"\n}, {\n  name: \"totalPlL\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"green\"\n}, {\n  name: \"totalPlS\",\n  visible: true,\n  renderType: RENDER_TYPE.DASHARRAY,\n  color: \"red\"\n}],\nWHERE_TO_RENDER.SEPARATE_WINDOW,\nfunction (context) { // init\n  context.chartHandle = getIndiParameter(context, \"chartHandle\")\n\n  if (typeof window.accounts != \"undefined\" && typeof window.accounts[context.chartHandle] != \"undefined\" && typeof window.accounts[context.chartHandle].totalPl != \"undefined\") {\n    context.totalPl = window.accounts[context.chartHandle].totalPl\n    context.totalPlL = window.accounts[context.chartHandle].totalPlL\n    context.totalPlS = window.accounts[context.chartHandle].totalPlS\n  } else {\n    popupErrorMessage(\"Please note, this indicator(unrealized_pl) can't be used independently. An EA called \\\"unrealized_pl_viewer\\\" that serves as an initiator should be used with this one simultaneously. You need to define an window object in the source codes of your EA that tries to refer to this indicator to manage the information about the unrealized PL. Please specify chartHandle as the index number of the window object before getting the handle of this indicator.\")\n  }\n},\nfunction (context) { // deinit\n  if (typeof window.accounts != \"undefined\" && typeof window.accounts[context.chartHandle] != \"undefined\" && typeof window.accounts[context.chartHandle].totalPl != \"undefined\") {\n    delete window.accounts[context.chartHandle].totalPl\n    delete window.accounts[context.chartHandle].totalPlL\n    delete window.accounts[context.chartHandle].totalPlS\n  }\n},\nfunction (context) { // render\n})\n"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/unrealized_pl_viewer.js",
    "content": "registerEA(\n  \"unrealized_pl_viewer\",\n  \"An EA used for watching the information about the unrealized PL of an account(v1.01)\",\n  [{ // parameters\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  },{\n    name: \"timeFrame\",\n    value: TIME_FRAME.H1,\n    required: true,\n    type: PARAMETER_TYPE.STRING,\n    range: null\n  }],\n  function (context) { // Init()\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n    var timeFrame = getEAParameter(context, \"timeFrame\")\n\n    context.tradingManager = {\n      totalPlL: 0,\n      totalPlS: 0,\n      getPosInfo: function (brokerNm, accId, symbolNm) {\n        this.totalPlL = 0\n        this.totalPlS = 0\n\n        var cnt = getOpenTradesListLength(context)\n        for (var i = cnt - 1; i >= 0; i--) {\n          var openTrade = getOpenTrade(context, i)\n          var symbol = getSymbolName(openTrade)\n\n          if (symbol == symbolNm) {\n            var orderType = getOrderType(openTrade)\n\n            if (orderType == ORDER_TYPE.OP_BUY) {\n              this.totalPlL += getUnrealizedPL(openTrade)\n            } else {\n              this.totalPlS += getUnrealizedPL(openTrade)\n            }\n          }\n        }\n\n        var arrTotalPl = window.accounts[context.chartHandle].totalPl\n        var arrTotalPlL = window.accounts[context.chartHandle].totalPlL\n        var arrTotalPlS = window.accounts[context.chartHandle].totalPlS\n        var arrTotalPlLen = arrTotalPl.length\n        for (var i = arrTotalPlLen; i < context.arrUnrealizedPlLen; i++) {\n          arrTotalPl.push(0)\n          arrTotalPlL.push(0)\n          arrTotalPlS.push(0)\n        }\n\n        arrTotalPl[context.arrUnrealizedPlLen - 1] = this.totalPlL + this.totalPlS\n        arrTotalPlL[context.arrUnrealizedPlLen - 1] = this.totalPlL\n        arrTotalPlS[context.arrUnrealizedPlLen - 1] = this.totalPlS\n      }\n    }\n\n    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)\n    if (typeof window.accounts == \"undefined\") {\n      window.accounts = []\n    }\n    if (typeof window.accounts[context.chartHandle] == \"undefined\") {\n      window.accounts[context.chartHandle] = {\n        totalPl: [],\n        totalPlL: [],\n        totalPlS: []\n      }\n    } else {\n      window.accounts[context.chartHandle].totalPl = []\n      window.accounts[context.chartHandle].totalPlL = []\n      window.accounts[context.chartHandle].totalPlS = []\n    }\n    context.unrealizedPlHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, \"unrealized_pl\", [{\n      name: \"chartHandle\", value: context.chartHandle}])\n  },\n  function (context) { // Deinit()\n  },\n  function (context) { // OnTick()\n    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)\n    context.arrUnrealizedPlLen = arrTime.length\n\n    var account = getAccount(context, 0)\n    var brokerName = getBrokerNameOfAccount(account)\n    var accountId = getAccountIdOfAccount(account)\n    var symbolName = getEAParameter(context, \"symbolName\")\n\n    context.tradingManager.getPosInfo(brokerName, accountId, symbolName)\n  },\n  function (context) { // OnTransaction()\n  }\n)\n"
  },
  {
    "path": "LICENSE",
    "content": "Fintechee License = MIT License + Restrictions for Racists\n\nCopyright (c) 2022 Fintechee\n\nPermission is hereby granted, free of charge, to any person except the individuals\nand the institutions that are identified as racists by Fintechee obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "> ## Anti-Racism Announcement!\n> ### WE ABSOLUTELY DISALLOW PROVIDING OUR SERVICE/PRODUCT/WHITE-LABEL TO ANY RACIST OR RACIST-SUPPORTED BUSINESS.\n> ### ESPECIALLY AGAINST A NOTORIOUS RACIST JESSE NICKLES, HE IS ABSOLUTELY ON OUR BLACKLIST FOREVER!\n> ### TO KNOW WHO JESSE NICKLES IS AND WHAT HE IS DOING, PLEASE CHECK THIS REVIEW POSTED BY A VICTIM:\n> https://wpjohnny.com/littlebizzy-jesse-nickles-fraud-slander-alert/\n> ### OR THIS CLAIM(TO TAKE DOWN HIS INDEX ON GOOGLE) SUBMITTED BY ANOTHER VICTIM\n> https://www.lumendatabase.org/notices/28558356\n> ### OR THIS LAWSUIT AGAINST HIM BY HIS ALMA MATER\n> https://cite.case.law/frd/304/594/\n> ### JESSE NICKLES' GITHUB USERNAME: jessuppi\n\n<h1 align=\"center\">Expert Advisor Studio</h1>\n<div align=\"center\">The most sophisticated Github repository for creating expert advisors(trading robots) and making automated trading doable on the Web browser.</div>\n\n<br />\n\n<div align=\"center\">\n  <a href=\"https://www.fintechee.com/features/fix-api/\">\n    <img src=\"https://img.shields.io/badge/FIX--API-Fintechee-red\" alt=\"Fintechee ~ Fintech Trading Platform ~ FIX API ~ Expert Advisor Studio ~ White Label\" />\n  </a>\n  <a href=\"https://www.fintechee.com/web-trader/\">\n    <img src=\"https://img.shields.io/badge/WEB--Trader-Fintechee-yellow\" alt=\"Fintechee ~ Fintech Trading Platform ~ WEB Trader ~ Expert Advisor Studio ~ White Label\" />\n  </a>\n  <a href=\"https://twitter.com/Fintechee1\">\n  <img alt=\"Fintechee ~ Expert Advisor Studio ~ Twitter\" src=\"https://img.shields.io/badge/Social-Twitter-steelblue\" />\n</a>\n\n</div>\n<div align=\"center\">\n  <a href=\"https://www.linkedin.com/in/marksea\">\n    <img src=\"https://img.shields.io/badge/Founder-Fintechee-red\" alt=\"Fintechee Founder ~ Expert Advisor Studio ~ Creator\" />\n  </a>\n  <a href=\"https://www.angelinvestmentnetwork.org/\">\n    <img src=\"https://img.shields.io/badge/Investor-Fintech__Angel-orange\" alt=\"Fintechee ~ Angel Investment Network ~ Fintech Industry\" />\n  </a>\n</div>\n\n<br />\n\n<div align=\"center\">\n  <sub>Created by <a href=\"https://www.fintechee.com/\">Fintechee</a></sub>\n</div>\n\n<div align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/c_cpp_compiler.gif\" alt=\"Expert Advisor Studio Fintechee's C Mql Compiler\" align=\"center\" />\n</div>\n\n<div align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/Indicators/extra_fractals/extra_fractals_screenshot.png\" alt=\"Expert Advisor Studio Fintechee's Extra Fractals Indicator\" align=\"center\" />\n\n  <img src=\"https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/architecture.png\" alt=\"Expert Advisor Studio Fintechee's Architecture\" align=\"center\" />\n</div>\n\n<br />\n\n## News!!\n\n### AI Trader Released!\n\n![Fintechee AI Trader](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/AI/ai-trader.png)\n\nhttps://www.fintechee.com/ai-trader/\n\nNo need to understand indicators or charts—it's as simple as eating a piece of cake.\n\n### Our CRM Supports FIX API Gateway!\n\nOur CRM currently supports the FIX API Gateway! Any broker or liquidity provider can integrate with our CRM via the FIX API. We have the capability to amalgamate all existing trading platforms to create a copy trading platform or assist liquidity providers in building a top-tier platform.\n\n### Why Trailing Stop Should be Set on The Client Side?\n\nA lot of traders(most of them are beginners) often set trailing stop on the backend. It's not a good way because your bottom line is completely visible. Now a plugin for trailing stop has been created! You can manage your trailing stop on the client side.\n\n### OpenAI Supported\n\nWe've created a plugin called \"Plugin for SNS with OpenAI\" that encompasses all the functionalities of \"Plugin for SNS\". You can now utilize \"Plugin for SNS with OpenAI\" to interact with OpenAI (ChatGPT).\n\n### Social Media on Chart\n\nWe are proud to announce the release of a highly engaging feature - SNS integration for real-time content publishing. With this new feature, you can now display all the content from your social network directly on the chart.\nPlease install an EA named \"plugin_for_sns\" and an indicator named \"barrage\" to use this feature.\n\n![Fintechee Social Media Integration](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/barrage/barrage.png)\n\n### Championship\n\nWe are hosting a Forex trading championship. All participants will use demo accounts, and no real funds will be involved(risk-free). The competition format is knockout-style. Each competition unit consists of 32 participants, meaning one first-place winner will be determined from these 32 participants. The first-place winner of each competition unit will receive a $500 cash prize, which is real money. The competition will have as many units as there are sponsors, typically one sponsor per unit. Registration has begun. Please access https://fisdk.com/dashboard to register.\n\n![Forex Trading Championship hosted by Fintechee](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/screenshot/championship.png)\n\n### Copy Trading\n\n![Copy Trading supported by Fintechee](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/screenshot/copytrading.png)\n\nWe are excited to announce the launch of our latest feature: Copy Trading! What's more, cross-broker copy trading is now available too. With no requirement for issuing authorization tokens to third parties, integrating with independent copy trading platforms is risk-free, operating separately from broker sides. Feel free to explore the new feature by visiting https://fisdk.com/dashboard/.\n\nOur innovative hub structure significantly enhances copy trading performance. Rather than receiving trading requests from third-party copy trading platforms, we utilize a handful of scalable hubs to seamlessly execute the copy trading process.\n\n### New Layout!!\n\n![New Layout of Fintechee](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/screenshot/fintechee_new_layout.png)\n\nWe release a new version with a new layout today(July 13th, 2023)!\n\n### Extension\n\n![Extension of Fintechee](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/extension.png)\n\nAdded an extra tab for extensions. This means that you can now install the EA/indicator that was released on our Github repository directly from our Web Trader.\n\n### FiSDK\n\nWe recently released FiSDK, a tool specifically designed for managing the backend. This tool features APIs that are entirely distinct from the APIs used for EA/indicators (Charting System). The APIs provided in this repository are mainly designed for quant traders to stay ahead of market movements and generate trading signals. FiSDK’s APIs, on the other hand, are primarily intended for position monitoring in the backoffice.\n\nFor more information on FiSDK, please check out this repository: https://github.com/fintechees/fisdk\n\nPlease note that the examples provided in the fisdk repository cannot be used in the WEB-trader’s console panel, and the examples provided here cannot be used in the fisdk repository.\n\n### Payment Gateway\n\nBased on the clients' requirements, we can integrate with any payment gateway at no charge.\n\n### Marketplace(multi-vendor) for EA\n\nOur new marketplace for EA developers, Fintechee.io, allows you to sell all types of digital products, not just C/C++/Mql based EAs/indicators. The digital signature technology we use ensures that copyright is protected, and each download link expires a few minutes after the order is created.\n\nWe launched on Aug. 12th, 2022, and we’ve already listed an EA called SimpleScalping in production for just $10. The algorithm is based on Martingale and is very stable on a larger timeframe with sufficient patience.\n\nCurrently, our payment gateway(for the EA marketplace, not for the WEB-trader) is connected to PayPal’s sandbox. If you have a PayPal test (developer) account, you can obtain any EA for free.\n\n### FIX Bridge(an individual version of WEB trader's backend)\n\nwe have developed a new version of our FIX Bridge feature for individual traders. It’s free FOREVER!\n\nDownload link:\nhttps://www.fintechee.com/assets/fix-api/fintecheefixbridge.7z\n\n## Campaign\nEveryone can get a free license to use our FIX API trading platform individual version if he/she matches any one of the conditions below.\n\nA. Our partners' client\n\nB. Github user\n\nC. Youtuber\n\nD. Coupon\n\nWe have updated our campaign page: https://www.fintechee.com/marketing/campaign/\n\nWe will update the necessary files for the FIX API trading platform individual version regularly in our Github repository: https://github.com/fintechee/FIX-API-Pro/\n\n## Community and Trading Signals\nWe built a forum for sharing trading signals and trading skills.\nhttps://www.fintechee.org\n\nhttps://www.fintechee.com/shared.html\n\n## Features\n\n<table>\n<tr><td><strong>WEB-based</strong></td><td>Javascript SDK</td></tr>\n<tr><td><strong>Compatibility</strong></td><td>Compatible with C/C++/MQL</td></tr>\n<tr><td><strong>Any Data</strong></td><td>You can import any data(historical/streaming) as long as you have data source.</td></tr>\n<tr><td><strong>Auto Market Maker</strong></td><td>You can send transactions to blockchains' SWAP smart contracts via Market Maker Bot</td></tr>\n<tr><td><strong>Copy Trading</strong></td><td>Copy Trading is our built-in new feature for now</td></tr>\n<tr><td><strong>Payment Gateway</strong></td><td>Based on the clients' requirements, we can integrate with any payment gateway at no charge</td></tr>\n<tr><td><strong>AI Enabled</strong></td><td>Integration with Artificial Intelligence(AI)</td></tr>\n<tr><td><strong>DEX</strong></td><td>Integration with DEX and Clearing House</td></tr>\n<tr><td><strong>Technical</strong></td><td>Custom Indicators(You can create compound indicators -- make an indicator calculated based on another indicator)</td></tr>\n<tr><td><strong>Trading Options</strong></td><td>You can analyze Bitcoin or Ether's options by using our plugins.</td></tr>\n<tr><td><strong>FIX API</strong></td><td>FIX API individual version(Your browser -> local Java Package -> FIX API straightforward)</td></tr>\n<tr><td><strong>White Label Enabled</strong></td><td>We offer a FIX API institutional version and a dashboard for brokers' managers.</td></tr>\n<tr><td><strong>MFA Enabled</strong></td><td>Multiple Factor Authentication makes trading more secure</td></tr>\n<tr><td><strong>APP Supported</strong></td><td>APP(Android, already listed on our website and published on Google Play)</td></tr>\n<tr><td><strong>EA Code Generator</strong></td><td>We offer toolkits for generating Expert Advisor source codes.</td></tr>\n<tr><td><strong>More Trading Instruments</strong></td><td>Our FIX API-based backend supports Spread Betting.</td></tr>\n<tr><td><strong>Price Aggregator</strong></td><td>We have 20+ liquidity providers and our backend supports automated order router to make you trade via the cheapest trading channel.</td></tr>\n<tr><td><strong>MAM-based Frontend</strong></td><td>Multiple accounts management on the frontend(useful for trading arbitrage)</td></tr>\n<tr><td><strong>MAM-based Backend</strong></td><td>Our FIX API supports MAM to make the platform operable by individuals.</td></tr>\n<tr><td><strong>Multiple Charts Management</strong></td><td>Our WEB trader terminal(trader room) is designed to be responsive(UI layout).</td></tr>\n<tr><td><strong>Investor Mode</strong></td><td>Investor mode(guest mode, read-only) is allowed.</td></tr>\n<tr><td><strong>Binance API</strong></td><td>Integration with Binance API on the backend</td></tr>\n<tr><td><strong>Trading Chaos</strong></td><td>EA based on Trading Chaos(Bill Williams' book)</td></tr>\n<tr><td><strong>Many Features</strong></td><td>...... Many features, you can explore them on your own.</td></tr>\n</table>\n\n## Usage\n\nI have received several questions about how to utilize the JavaScript files in this repository. However, the usage is not the same as Node.js, so it is unnecessary to use “node xxx.js” to run them. In fact, it’s a much simpler process, as our files are browser-based. All you need to do is open the Fintechee Web Trader, copy and paste the relevant source codes into the Console Panel, and then click the Run Button. It’s that easy!\n\nEach file in this repository is independent and can be used separately. The EAs and indicators are stored solely on your browser and are never uploaded to the server side. We use Web LocalStorage to ensure that the secrets of your trading strategies are protected.\n\nA simple manual: https://github.com/fintechees/Expert-Advisor-Studio/blob/master/simple_manual.txt\n\nWEB Trader: https://www.fintechee.com/web-trader/\n\nPlugins' usage: https://www.fintechee.com/plugins/\n\nHow to compile C/C++/MQL: https://www.fintechee.com/expert-advisor-cpp-compiler/\n\n## Live Stream\n\nWe started a live stream on Youtube\n\nPlease access our video stream page to see how we trade arbitrage in real-time(FIX API quotes vs Oanda).\nRecommendation:\nhttps://twitter.com/Fintechee1\n![Expert Advisor Studio Trading Arbitrage(FIX API vs Oanda) via Fintechee](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/Arbitrage/arbitrageyoutube.png)\n\n![Expert Advisor Studio Trading Arbitrage(FIX API vs Oanda) via Fintechee](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/Arbitrage/arbitragechance.png)\nAlternative:\nhttps://www.fintechee.com/videostreaming/\n\nPlease access our demo to run the EAs:\nhttps://www.fintechee.com\n\nYou don't know how to use these EAs?\nPlease check out our Youtube Channel, there are tutorials(https://www.youtube.com/channel/UCjBs_l6rUxhtZlfRhDuVGSg)\nYou can find the source codes for the tutorials here: https://github.com/fintechee/tutorials\n\nPlease check our [Github wiki](https://github.com/fintechees/Expert-Advisor-Studio/wiki) to know more details about APIs.\n\nPlease check this tutorial(https://www.fintechee.com/expert-advisor-cpp-compiler) to learn how to use our Nodejs package(https://github.com/fintechee/Expert-Advisor-CPP-Compiler) to compile C/C++/MQL-based programs.\n\n![Expert Advisor Studio Fintechee Screenshot](https://www.fintechee.com/vpimages/services/newscreenshot1.png)\n\n![Expert Advisor Studio Fintechee's Ecosystem](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/ecosystem.png)\n\n![Expert Advisor Studio Expert Advisor C/C++/MQL Compiler](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/cppcompiler.png)\n\n![Expert Advisor Studio Fintechee custom indicator](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/analyzestructure.png)\n\n### Release Notes\n2020.7.7 three APIs were modified and added parameters.\n1. sendOrder\n2. modifyOrder\n3. closeTrade\n\n2021.2.22 Added one API to improve the performance.\n1. getCurrentTick\n\n2021.3.3 two APIs were modified.\n\n1. registerIndicator\n\nWe added three parameters to this API, all of which are callback functions: OnInit, OnDeinit, and OnRender. We added these to extend the functionality of Fintechee and make it easier to manage and monitor indicators. When you add an indicator to the chart, the OnInit callback function will be called. When you remove an indicator from the chart, the OnDeinit function will be called. After the main callback function is executed, the OnRender function will be triggered. The OnRender function is particularly useful if you want to add your own renderer to the platform. Our platform’s renderer is based on D3.js. If you are not familiar with it, you can use other alternative JS charting systems such as Chart.js.\n\nThese callback functions are new features; other platforms do not have these parameters. Fortunately, this API is compatible with older versions, so you do not need to modify your old indicators.\n\nExample:\nhttps://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/chart_elements/line_segment_sample.js\n\n2. registerEA\n\nWe have added a new parameter to this API, namely a callback function that receives a message when a transaction is triggered. For instance, if you want to send an order to the backend and avoid blocking your process, everything on our platform runs asynchronously. Therefore, you can continue with your analysis and leave this callback function in place to receive a notification from the backend when the order is executed and a new trade is opened.\n\nThis callback function is a new feature; other platforms do not offer this parameter. Fortunately, this API is backward compatible, so you don’t need to modify your old EAs.\n\nExample:\nhttps://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/CopyTrading/copy_trading_for_oanda.js\n\n2021.9.18 Added three APIs useful when the onTransaction event is triggered.\n1. getLatestTransBrokerName\n2. getLatestTransAccountId\n3. getLatestTrans\n\n2022.11.2 Added one API useful when you want to combine several EAs into a workflow.\n1. launchEA\n\n### Constants\n\n```javascript\nvar BROKER_NAME = {\n\tDEMO: \"Fintechee Demo\"\n}\n\nvar TIME_FRAME = {\n\tM1: \"M1\",\n\tM5: \"M5\",\n\tM15: \"M15\",\n\tM30: \"M30\",\n\tH1: \"H1\",\n\tH4: \"H4\",\n\tD: \"D\",\n\tW: \"W\",\n\tM: \"M\"\n}\n\nvar ORDER_TYPE = {\n\tOP_BUY: \"BUY\",\n\tOP_SELL: \"SELL\",\n\tOP_BUYLIMIT: \"BUY LIMIT\",\n\tOP_SELLLIMIT: \"SELL LIMIT\",\n\tOP_BUYSTOP: \"BUY STOP\",\n\tOP_SELLSTOP: \"SELL STOP\"\n}\n\nvar WHERE_TO_RENDER = {\n\tCHART_WINDOW: \"CHART_WINDOW\",\n\tSEPARATE_WINDOW: \"SEPARATE_WINDOW\"\n}\n\nvar DATA_NAME = {\n\tTIME: \"Time\",\n\tOPEN: \"Open\",\n\tHIGH: \"High\",\n\tLOW: \"Low\",\n\tCLOSE: \"Close\",\n\tHL2: \"HL2\",\n\tHLC3: \"HLC3\",\n\tHLCC4: \"HLCC4\"\n}\n\nvar RENDER_TYPE = {\n\tHISTOGRAM: \"Histogram\",\n\tLINE: \"Line\",\n\tROUND: \"Round\",\n\tDASHARRAY: \"Dasharray\"\n}\n\nvar PARAMETER_TYPE = {\n\tINTEGER: \"Integer\",\n\tNUMBER: \"Number\",\n\tBOOLEAN: \"Boolean\",\n\tSTRING: \"String\"\n}\n```\n### Common Function\n\n```javascript\nfunction sma (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (calculatedLength > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar sum = 0\n\n\tfor (var j = i - period + 1; j < i; j++) {\n\t\tsum += dataInput[j]\n\t}\n\n\tfor (var j = i; j < dataInput.length; j++) {\n\t\tsum += dataInput[j]\n\t\tdataOutput[j] = sum / period\n\t\tsum -= dataInput[j - period + 1]\n\t}\n}\n\nfunction ema (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\tvar smthFctr = 2.0 / (period + 1)\n\n\tif (i == 0) {\n\t\tdataOutput[0] = dataInput[0]\n\t\ti++\n\t} else if (i == 1) {\n\t} else {\n\t\ti--\n\t}\n\n\twhile (i < dataInput.length) {\n\t\tdataOutput[i] = dataInput[i] * smthFctr + dataOutput[i - 1] * (1 - smthFctr)\n\t\ti++\n\t}\n}\n\nfunction smma (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\tvar sum = 0\n\n\tif (i > 0) {\n\t\ti--\n\t} else {\n\t\ti = period - 1\n\n\t\tfor (var j = 1; j < period; j++) {\n\t\t\tdataOutput[i - j] = 0\n\t\t\tsum += dataInput[i - j]\n\t\t}\n\n\t\tsum += dataInput[i]\n\t\tdataOutput[i] = sum / period\n\t\ti++\n\t}\n\n\twhile (i < dataInput.length) {\n\t\tsum = dataOutput[i - 1] * period - dataOutput[i - 1] + dataInput[i]\n\t\tdataOutput[i] = sum / period\n\t\ti++\n\t}\n}\n\nfunction lwma (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (i > 0) {\n\t\ti--\n\t} else {\n\t\tfor (var j = 0; j < period - 1; j++) {\n\t\t\tdataOutput[j] = 0\n\t\t}\n\n\t\ti = period - 1\n\t}\n\n\tvar sum = 0\n\tvar diffsum = 0\n\tvar weight = 0\n\n\tfor (var j = 1; j < period; j++) {\n\t\tsum += dataInput[i - j] * (period - j)\n\t\tdiffsum += dataInput[i - j]\n\t\tweight += j\n\t}\n\tweight += period\n\n\twhile (i < dataInput.length) {\n\t\tsum += dataInput[i] * period\n\t\tdataOutput[i] = sum / weight\n\t\tdiffsum += dataInput[i]\n\t\tsum -= diffsum\n\t\tdiffsum -= dataInput[i - period + 1]\n\t\ti++\n\t}\n}\n```\n\nPlease check our site for details. [Fintechee](https://www.fintechee.com/sdk-trading/)\n\n### Fintechee License\n\nFintechee License = MIT License + Restrictions for Racists\n\nhttps://github.com/fintechee transferred this repo to https://github.com/fintechees on Aug 25th 2021.\n\n\n![Expert Advisor Studio Fintechee APP Screenshot1](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile1.png)\n![Expert Advisor Studio Fintechee APP Screenshot2](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile2.png)\n![Expert Advisor Studio Fintechee APP Screenshot3](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile3.png)\n![Expert Advisor Studio Fintechee APP Screenshot4](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile4.png)\n![Expert Advisor Studio Fintechee APP Screenshot0](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile0.png)\n![Expert Advisor Studio Fintechee APP Screenshot5](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile5.png)\n![Expert Advisor Studio Fintechee APP Screenshot6](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile6.png)\n![Expert Advisor Studio Fintechee APP Screenshot7](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile7.png)\n![Expert Advisor Studio Fintechee APP Screenshot8](https://raw.githubusercontent.com/fintechees/Expert-Advisor-Studio/master/screenshot/mobile8.png)\n"
  },
  {
    "path": "screenshot/README.md",
    "content": "\n\n"
  },
  {
    "path": "simple_manual.txt",
    "content": "1. Supported Programming Languages\nFintechee supports JS/C/C++/MQL programming languages.\n\nJS codes can be run straightforward on Fintechee WEB Trader and you DON'T need to compile JS files.\n\nC/C++/MQL codes are required to compile before you run the compiled files on Fintechee WEB Trader.\n\n\n2. How to Run JS Codes?\nFintechee WEB Trader has a console panel to run JS files. Any JS codes can be run in the console.\n\nFintechee-runnable EAs/indicators have to be coded in a special form.\n\nWe use registerEA and registerIndicator the two APIs to import your custom EA/indicator codes.\n\nPlease check the wiki on our Github repo or the samples to know how to code your custom EA/indicators.\n\n\n3. How to Run C/C++/MQL Codes?\nRunning C/C++/MQL files is a little bit complicated. We need one more step.\n\nIn our WEB Trader, you can find a built-in plugin named \"plugin_for_mql\".\n\nYou need to launch this plugin first and then load the C/C++/MQL compiled files(after you load C/C++/MQL compiled files, you can stop the plugin).\n\nBecause a part of C/C++/MQL compiled files are binary-formatted WASMs, so they are not readable and you can't copy-paste the files straightforward to the console.\n\nThe correct method to load C/C++/MQL compiled files is to import a JSON string that refers to your C/C++/MQL compiled files.\n\nIf you purchase EAs/indicators via Fintechee, the vendors should provide you with a JSON string that is written in the guide of the product that you buy.\n\nIf you are a developer, you need to generate the JSON strings for your source codes on your own. You need to copy-paste your original C/C++/MQL codes in Fintechee C/C++ console panel and click \"Generate EA\" or \"Generate Indicator\" button to generate the JSON strings. Meanwhile you can find an edited version of your source codes on the right side of the console panel. Copy-paste the edited codes to the left side of the console panel and replace your original version with the edited one. After that, compile it by clicking \"Compile EA\" or \"Compile Indicator\" button. If the output has no errors, you are done successfully. Then you can import the JSON string to \"plugin_for_mql\" and load your C/C++/MQL compiled files.\nTo compile C/C++/MQL codes, you need to install this compiler first:\nhttps://github.com/fintechees/Expert-Advisor-Cpp-Compiler\n\n\n4. How to Run Tensorflow-based EA(JS Codes)?\nFintechee supports neural networks as well.\n\nTensorflow is a significant framework that is based on Convolutional Neural Network. The training time is shorter. We recommend you use it for your AI-based EAs/indicators.\n\nAll AI-based EAs developed by Fintechee include two parts: one is used to train a model, the other one is used to trade following the signals that the model generates.\n\nBefore you train or run the Tensorflow-based EAs, you need to launch a built-in plugin named \"plugin_to_load_tensorflow\" first(after you receive a success message that notifies you Tensorflow has been loaded, you can stop this plugin).\n\n\n\n5. How to Run Tensorflow-based EA(C/C++/MQL Codes)?\nFintechee provides 5 extended APIs for C/C++/MQL developers:\nBuildCNN\nLoadCNN\nSaveCNN\nTrainCNN\nRunCNN\n\nRunning Tensorflow-based C/C++/MQL files is a little bit complicated. We need TWO more steps.\n\nThe two steps are for loading C/C++/MQL compiled files and loading Tensorflow.\n\nPlease refer to the 3rd and 4th paragraphs to know how to launch the plugins.\n\nAnother important point is, at the beginning of the OnInit function, you need to add a line to call PreventCleanUp(this is an extended API as well, it can make the neural networks' models stord in the context cache not cleared after the backtesting is done). PreventCleanUp is not required for the EAs that are NOT based on neural networks.\n"
  }
]