master 0b72f0061d6d cached
143 files
838.4 KB
238.2k tokens
662 symbols
1 requests
Download .txt
Showing preview only (886K chars total). Download the full file or copy to clipboard to get everything.
Repository: fintechees/Expert-Advisor-Studio
Branch: master
Commit: 0b72f0061d6d
Files: 143
Total size: 838.4 KB

Directory structure:
gitextract_dqvm1vq7/

├── AI/
│   ├── aitrader_12_eurusd.json
│   ├── aitrader_12_gbpusd.json
│   └── readme.md
├── EA/
│   ├── Arbitrage/
│   │   ├── README.md
│   │   ├── fintechee_external_arbitrage.js
│   │   ├── guide_for_fintechee_external_arbitrage.txt
│   │   └── sample_trading_arbitrage.js
│   ├── Built-in/
│   │   ├── README.md
│   │   ├── sample_using_rsi.js
│   │   └── sample_using_sma.js
│   ├── Chaos/
│   │   ├── chaos.js
│   │   └── intro.txt
│   ├── CopyTrading/
│   │   ├── README.md
│   │   ├── copy_trading_for_oanda.js
│   │   ├── copy_trading_for_oanda_guide.txt
│   │   ├── copy_trading_locally.js
│   │   └── copy_trading_locally_guide.txt
│   ├── Martingale/
│   │   ├── improved_martingale.js
│   │   ├── improved_martingale.txt
│   │   └── sample_martingale.js
│   ├── NeuralNetwork/
│   │   ├── nn_example.js
│   │   ├── sample_run_neuron_model.js
│   │   ├── sample_training_neuron_model.js
│   │   └── usage.txt
│   ├── Oldie/
│   │   ├── README.md
│   │   ├── README.txt
│   │   └── fixapi_oanda_arbitrage.js
│   ├── Plugin-for-Deribit/
│   │   ├── plugin_for_deribit.js
│   │   └── usage.txt
│   ├── Plugin-for-EOS/
│   │   ├── decentralized_exchange_eos_approve.js
│   │   ├── decentralized_exchange_eos_cancel.js
│   │   ├── decentralized_exchange_eos_exec.js
│   │   ├── decentralized_exchange_eos_propose.js
│   │   ├── decentralized_exchange_eos_unapprove.js
│   │   ├── payment_gateway_eos.js
│   │   ├── payment_gateway_eos_lib_loader.js
│   │   ├── payment_gateway_eos_scatter.js
│   │   └── usage.txt
│   ├── Plugin-for-FXCM/
│   │   └── README.md
│   ├── Plugin-for-MQL/
│   │   ├── README.md
│   │   ├── mqlea2fintechee.h
│   │   ├── mqlindi2fintechee.h
│   │   ├── plugin_for_mql.js
│   │   ├── runtestcnn.cpp
│   │   ├── testcnn.cpp
│   │   ├── testverisig.cpp
│   │   └── usage.txt
│   ├── Plugin-for-Oanda/
│   │   ├── plugin_for_oanda.js
│   │   └── usage.txt
│   ├── Plugin-for-SNS/
│   │   ├── plugin_for_sns.js
│   │   └── usage.txt
│   ├── Plugin-for-SNS-with-OpenAI/
│   │   ├── plugin_for_sns_with_openai.js
│   │   └── usage.txt
│   ├── Plugin-for-Tensorflow/
│   │   ├── import_export_model.js
│   │   ├── plugin_to_load_tensorflow.js
│   │   ├── sample_running_cnn_model.js
│   │   ├── sample_training_cnn_model.js
│   │   ├── test_loading_tensorflow.js
│   │   ├── test_xor_powered_by_tensorflow.js
│   │   └── usage.txt
│   ├── Plugin-for-TradingView/
│   │   └── plugin_for_tradingview.js
│   ├── Plugin-for-TrailingStop/
│   │   └── plugin_for_trailingstop.js
│   ├── Plugin-for-XCoinCH/
│   │   ├── market_maker_bot.js
│   │   └── usage.txt
│   ├── PriceAction/
│   │   └── price_action.js
│   ├── Sample-for-Workflow/
│   │   ├── callee.js
│   │   └── caller.js
│   ├── Tips/
│   │   ├── about_API_getData.txt
│   │   └── how_to_rename.txt
│   └── Utility/
│       ├── historical_data_cleaner.js
│       ├── historical_data_viewer.js
│       └── usage.txt
├── Indicators/
│   ├── Built-in/
│   │   ├── README.md
│   │   ├── ac.js
│   │   ├── adx.js
│   │   ├── alligator.js
│   │   ├── ao.js
│   │   ├── atr.js
│   │   ├── bands.js
│   │   ├── bears.js
│   │   ├── bidask.js
│   │   ├── bulls.js
│   │   ├── cci.js
│   │   ├── common.js
│   │   ├── demarker.js
│   │   ├── ema.js
│   │   ├── envelopes.js
│   │   ├── fractals.js
│   │   ├── heikin-ashi.js
│   │   ├── ichimoku.js
│   │   ├── lwma.js
│   │   ├── macd.js
│   │   ├── mfi.js
│   │   ├── momentum.js
│   │   ├── rsi.js
│   │   ├── rvi.js
│   │   ├── sar.js
│   │   ├── sma.js
│   │   ├── smma.js
│   │   ├── stochastic.js
│   │   ├── volume.js
│   │   ├── wpr.js
│   │   └── zigzag.js
│   ├── Oldie/
│   │   ├── README.md
│   │   ├── README.txt
│   │   ├── fintechee_oanda_loader.js
│   │   └── line_segment_sample.js
│   ├── Plugin-for-Data-API/
│   │   ├── crypto_loader.js
│   │   └── usage.txt
│   ├── Plugin-for-Youtube/
│   │   ├── tutorial_videos.js
│   │   └── usage.txt
│   ├── atr_comparison/
│   │   ├── README.md
│   │   ├── atr_comparison.js
│   │   ├── atr_comparison_guide.txt
│   │   └── atr_exporter.js
│   ├── barrage/
│   │   └── barrage.js
│   ├── chart_elements/
│   │   ├── README.md
│   │   ├── chart_elements.js
│   │   ├── chart_elements_intro.txt
│   │   ├── toggle_signals_intro.txt
│   │   └── toggle_trading_signals.js
│   ├── cursor/
│   │   ├── cursor.js
│   │   └── usage.txt
│   ├── extra_fractals/
│   │   ├── README.md
│   │   ├── extra_fractals.js
│   │   └── usage.txt
│   ├── extra_mfi/
│   │   ├── extra_mfi.js
│   │   └── extra_mfi_guide.txt
│   ├── extra_sar/
│   │   └── extra_sar.js
│   ├── fibonacci_retracements/
│   │   ├── README.md
│   │   ├── fibonacci_retracements.js
│   │   └── usage.txt
│   ├── order_buttons/
│   │   ├── README.md
│   │   └── order_buttons.js
│   └── unrealized_pl_and_equity_curve/
│       ├── equity_curve.js
│       ├── equity_curve_viewer.js
│       ├── how_to_use_equity_curve_unrealized_pl.txt
│       ├── unrealized_pl.js
│       └── unrealized_pl_viewer.js
├── LICENSE
├── README.md
├── screenshot/
│   └── README.md
└── simple_manual.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: AI/aitrader_12_eurusd.json
================================================
{"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"}]}]}

================================================
FILE: AI/aitrader_12_gbpusd.json
================================================
{"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"}]}]}

================================================
FILE: AI/readme.md
================================================
AI Trader
https://www.fintechee.com/ai-trader/


We will provide some AI models for free.


Our 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.


We store backtesting reports in this repo: https://github.com/fintechees/AI-Trader-Backtesting-Report


If you are interested in purchasing our paid AI model, please contact us: admin@fintechee.com.


Campaign!!

We 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.

The individual trader is required to have a FIX API account.
We will set up a dedicated platform for this trader, linked to a single account.
The monthly fee is $100 USD, which includes cloud service costs.


================================================
FILE: EA/Arbitrage/README.md
================================================
We will add more details to introduce how to use this EA.


================================================
FILE: EA/Arbitrage/fintechee_external_arbitrage.js
================================================
registerEA(
  "fintechee_external_arbitrage",
  "A test EA to trade arbitrage based on the price difference between Fintechee and the external trading platform(v1.0)",
  [{
    name: "externalSys",
    value: "Oanda",
    required: true,
    type: PARAMETER_TYPE.STRING,
    range: null
  }, {
    name: "autoLoad",
    value: true,
    required: true,
    type: PARAMETER_TYPE.BOOLEAN,
    range: null
  }, {
    name: "autoSave",
    value: true,
    required: true,
    type: PARAMETER_TYPE.BOOLEAN,
    range: null
  }, {
    name: "backgroundColor",
    value: "#dfc29a",
    required: true,
    type: PARAMETER_TYPE.STRING,
    range: null
  }],
  function (context) { // Init()
    var externalSys = getEAParameter(context, "externalSys")

    if (externalSys == "Oanda") {
      if (typeof window.pluginForOanda == "undefined") {
        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.")
      }
    } else {
      throw new Error("The specific external trading platform is not supported.")
    }

    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)

    var currTime = new Date().getTime()

    if (typeof window.arbitrage == "undefined") {
      window.arbitrage = {
        autoLoad: getEAParameter(context, "autoLoad"),
        autoSave: getEAParameter(context, "autoSave"),
        bgColor: getEAParameter(context, "backgroundColor"),
        latestDay: new Date().getDay(),
        latestSaveTime: currTime,
        quotes: [],
        statistics: [],
        loadStatistics: function () {
          if (typeof localStorage.reservedZone != "undefined") {
            var reservedZone = JSON.parse(localStorage.reservedZone)

            if (typeof reservedZone.arbitrageStatistics != "undefined" && typeof reservedZone.arbitrageStatistics.statistics != "undefined") {
              if (new Date(reservedZone.arbitrageStatistics.latestSaveTime).getDay() < window.latestDay) {
                for (var i in reservedZone.arbitrageStatistics.statistics) {
                  var statistics = reservedZone.arbitrageStatistics.statistics[i]
                  this.statistics[statistics.symbolName] = {
                    h: [],
                    h2: [],
                    ph: statistics.h,
                    ph2: statistics.h2
                  }
                  for (var j = 0; j <= 23; j++) {
                    this.statistics[statistics.symbolName].h.push(0)
                    this.statistics[statistics.symbolName].h2.push(0)
                  }
                }
              } else {
                for (var i in reservedZone.arbitrageStatistics.statistics) {
                  var statistics = reservedZone.arbitrageStatistics.statistics[i]
                  this.statistics[statistics.symbolName] = {
                    h: statistics.h,
                    h2: statistics.h2,
                    ph: statistics.ph,
                    ph2: statistics.ph2
                  }
                }
              }
            }
          }
        },
        saveStatistics: function () {
          var reservedZone = {}

          if (typeof localStorage.reservedZone != "undefined") {
            reservedZone = JSON.parse(localStorage.reservedZone)
          }

          reservedZone.arbitrageStatistics = {
            latestSaveTime: new Date().getTime(),
            statistics: []
          }

          for (var i in this.statistics) {
            reservedZone.arbitrageStatistics.statistics.push({
              symbolName: i,
              h: this.statistics[i].h,
              h2: this.statistics[i].h2,
              ph: this.statistics[i].ph,
              ph2: this.statistics[i].ph2
            })
          }

          localStorage.reservedZone = JSON.stringify(reservedZone)
        },
        count: function (symbolName, hour) {
          this.statistics[symbolName].h[hour]++
        },
        count2: function (symbolName, hour) {
          this.statistics[symbolName].h2[hour]++
        },
        chartLibUrl: "https://cdn.jsdelivr.net/npm/chart.js@2.8.0",
        bLibLoaded: false,
        loadChartJsLib: function () {
          var tags = document.getElementsByTagName("script")
          for (var i = tags.length - 1; i >= 0; i--) {
            if (tags[i] && tags[i].getAttribute("src") != null && tags[i].getAttribute("src") == this.chartLibUrl) {
              this.bLibLoaded = true
              break
            }
          }

          var that = this

          if (!this.bLibLoaded) {
            var script = document.createElement("script")
            script.id = "chartjs_lib"

            document.body.appendChild(script)
            script.onload = function () {
              that.bLibLoaded = true
              that.initArbitrageChart()
              popupMessage("The ChartJS lib has been loaded successfully!")
            }
            script.onerror = function () {
              that.bLibLoaded = false
              popupErrorMessage("Failed to load the ChartJS lib.")
            }
            script.async = true
            script.src = this.chartLibUrl
          } else {
            this.initArbitrageChart()
          }
        },
        currentChartSymbolName: "EUR/USD",
        initArbitrageChart: function () {
          var ctx = document.getElementById("arbitrage_chart").getContext("2d")
          var statistics = this.statistics[this.currentChartSymbolName]

          var labels = []
          var data = []
          var data2 = []
          var pdata = []
          var pdata2 = []
          for (var i = 0; i <= 23; i++) {
            labels.push(i + "")
            data.push(statistics.h[i])
            data2.push(statistics.h2[i])
            pdata.push(statistics.ph[i])
            pdata2.push(statistics.ph2[i])
          }

          this.arbitrageChart = new Chart(ctx, {
              type: "line",
              data: {
                  labels: labels,
                  datasets: [{
                      label: this.currentChartSymbolName + "(F-X)", // F stands for Fintechee, X stands for eXternal sys
                      backgroundColor: "rgba(255,255,255,0)",
                      borderColor: "#DB2828",
                      data: data
                  }, {
                      label: this.currentChartSymbolName + "(X-F)",
                      backgroundColor: "rgba(255,255,255,0)",
                      borderColor: "#21BA45",
                      data: data2
                  }, {
                      label: this.currentChartSymbolName + "(F-X)",
                      backgroundColor: "rgba(255,255,255,0)",
                      borderColor: "#DB2828",
                      borderDash: [2, 3],
                      data: pdata
                  }, {
                      label: this.currentChartSymbolName + "(X-F)",
                      backgroundColor: "rgba(255,255,255,0)",
                      borderColor: "#21BA45",
                      borderDash: [2, 3],
                      data: pdata2
                  }]
              },
              options: {
                responsive: true,
                maintainAspectRatio: false
              }
          })
        },
        updateArbitrageChart: function (symbolName, bAll, hour) {
          if (bAll) {
            for (var i = 0; i <= 23; i++) {
              this.arbitrageChart.data.datasets[0].data[i] = this.statistics[symbolName].h[i]
              this.arbitrageChart.data.datasets[2].data[i] = this.statistics[symbolName].ph[i]
            }
          } else {
            this.arbitrageChart.data.datasets[0].data[hour] = this.statistics[symbolName].h[hour]
          }

          this.arbitrageChart.update()
        },
        updateArbitrageChart2: function (symbolName, bAll, hour) {
          if (bAll) {
            for (var i = 0; i <= 23; i++) {
              this.arbitrageChart.data.datasets[1].data[i] = this.statistics[symbolName].h2[i]
              this.arbitrageChart.data.datasets[3].data[i] = this.statistics[symbolName].ph2[i]
            }
          } else {
            this.arbitrageChart.data.datasets[1].data[hour] = this.statistics[symbolName].h2[hour]
          }

          this.arbitrageChart.update()
        },
        updatePrevArbitrage: function () {
          for (var i in this.statistics) {
            this.statistics[i].ph = this.statistics[i].h
            this.statistics[i].ph2 = this.statistics[i].h2
            this.statistics[i].h = []
            this.statistics[i].h2 = []

            for (var j = 0; j <= 23; j++) {
              this.statistics[i].h.push(0)
              this.statistics[i].h2.push(0)
            }
          }
        },
        chartIds: [],
        initDashboard: function () {
          if (typeof $("#arbitrage_chart_dashboard").html() == "undefined") {
            var arbitrageChartPanel = '<div id="arbitrage_chart_dashboard" style="background:' + this.bgColor + ';height:100%">' +
              '<div class="row" style="background:' + this.bgColor + ';text-align:center">' +
                '<div class="ui buttons">' +
                  // '<div class="ui button" style="background:' + this.bgColor + '" id="btn_show_arbitrage_prices">List</div>' +
                  '<div class="ui button" style="background:' + this.bgColor + '" id="btn_load_arbitrage_statistics">Load</div>' +
                  '<div class="ui button" style="background:' + this.bgColor + '" id="btn_save_arbitrage_statistics">Save</div>' +
                '</div>' +
              '</div>' +
              '<div class="row">' +
                '<table id="arbitrage_prices" class="cell-border">' +
                '</table>' +
              '</div>' +
              '<div class="row">' +
                '<div class="chart-container" style="background:' + this.bgColor + ';position:relative;height:35vh">' +
                  '<canvas id="arbitrage_chart"></canvas>' +
                '</div>' +
              '</div>' +
            '</div>'

            var arbitragePricesPanel = '<div class="ui fullscreen modal" id="arbitrage_prices_dashboard">' +
              '<div class="content">' +
              '</div>' +
            '</div>'

            $("#reserved_zone").append(arbitragePricesPanel)

            if (getLayoutId() != 3) {
        			changeLayout(3)
        		}

        		this.chartIds = getLayout(2)
        		for (var i in this.chartIds) {
        			moveLayout(this.chartIds[i], 1)
        		}

            embedHtml(arbitrageChartPanel, 2)
          }

          var that = this

          if (!$.fn.dataTable.isDataTable("#arbitrage_prices")) {
      			this.pricesTable = $("#arbitrage_prices").DataTable({
      				data: [],
      				columns: [
                {
                  title: "Instruments"
                }, {
                  title: "Fintechee-Ext",
                  render: function (data, type, row) {
      							if (data > 0) {
      								return '<p style = "background:#21BA45;color:#FFFFFF" >' + data + '</p>'
      							} else {
      								return '<p style = "background:' + that.bgColor + ';color:#DB2828" >' + data + '</p>'
      							}
      						}
      					}, {
                  title: "Ext-Fintechee",
                  render: function (data, type, row) {
                    if (data > 0) {
                      return '<p style = "background:#21BA45;color:#FFFFFF" >' + data + '</p>'
                    } else {
                      return '<p style = "background:' + that.bgColor + ';color:#DB2828" >' + data + '</p>'
                    }
      						}
      					}, {
                  title: "External"
                }, {
                  title: "Op"
                }
      				],
              headerCallback: function (thead, data, start, end, display) {
                $(thead).css("background-color", that.bgColor)
              },
              rowCallback: function (row, data, index) {
                $("td", row).css("background-color", that.bgColor)
              },
              ordering: false,
              searching: false,
              bPaginate: false,
              bLengthChange: false,
              bFilter: false,
              bInfo: false,
              scrollY: "50vh",
              scrollCollapse: true,
              paging: false,
              columnDefs: [
                {width: "20%", targets: 0, className: "dt-body-center"},
                {width: "20%", targets: 1, className: "dt-body-right"},
                {width: "20%", targets: 2, className: "dt-body-right"},
                {width: "20%", targets: 3, className: "dt-body-right"},
                {width: "20%", targets: 4, className: "dt-body-center"},
                {width: "20%", targets: [0], className: "dt-head-center"},
                {width: "20%", targets: [1], className: "dt-head-center"},
                {width: "20%", targets: [2], className: "dt-head-center"},
                {width: "20%", targets: [3], className: "dt-head-center"},
                {width: "20%", targets: [4], className: "dt-head-center"},
                {
                  targets: -1,
                  data: null,
                  defaultContent: '<button id="btn_check_arbitrage" class="ui button" style="padding:0;background:' + this.bgColor + '"><i class="tachometer alternate blue icon"></i></button>' +
                                  '<button id="btn_sell" class="ui button" style="padding:0;background:' + this.bgColor + ';color:#DB2828">S</button>' +
                                  '<button id="btn_buy" class="ui button" style="padding:0;background:' + this.bgColor + ';color:#21BA45">B</button>'
                }
              ]
      			})

            for (var i in this.quotes) {
              $("#arbitrage_prices").DataTable().row.add([
                i,
                "",
                "",
                "",
                ""
              ]).draw(false)
            }

            $("#arbitrage_prices tbody").on("click", "[id*=btn_check_arbitrage]", function () {
              if (typeof that.pricesTable != "undefined") {
                var data = that.pricesTable.row($(this).parents("tr")).data()
                if (typeof data == "undefined") {
                  data = that.pricesTable.row($(this)).data()
                }

                that.currentChartSymbolName = data[0]
                that.arbitrageChart.data.datasets[0].label = that.currentChartSymbolName + "(F-X)" // F stands for Fintechee, O stands for eXternal sys
                that.arbitrageChart.data.datasets[1].label = that.currentChartSymbolName + "(X-F)"
                that.arbitrageChart.data.datasets[2].label = that.currentChartSymbolName + "(F-X)"
                that.arbitrageChart.data.datasets[3].label = that.currentChartSymbolName + "(X-F)"
                that.updateArbitrageChart(data[0], true, -1)
                that.updateArbitrageChart2(data[0], true, -1)
              }
            })

            $("#btn_load_arbitrage_statistics").on("click", function () {
              that.loadStatistics()
            })

            $("#btn_save_arbitrage_statistics").on("click", function () {
              that.saveStatistics()
            })
      		}

          for (var i in this.quotes) {
            this.statistics[i] = {
              h: [],
              h2: [],
              ph: [],
              ph2: []
            }

            for (var j = 0; j <= 23; j++) {
              this.statistics[i].h.push(0)
              this.statistics[i].h2.push(0)
              this.statistics[i].ph.push(0)
              this.statistics[i].ph2.push(0)
            }
          }
        }
      }
    }

    if (externalSys == "Oanda") {
      window.arbitrage.quotes = window.pluginForOanda.quotes
    }

    window.arbitrage.initDashboard()
		window.arbitrage.loadChartJsLib()

    if (window.arbitrage.autoLoad) {
      window.arbitrage.loadStatistics()
    }

    for (var i in window.arbitrage.quotes) {
      getQuotes(context, brokerName, accountId, i.replace("_", "/"))
    }
  },
  function (context) { // Deinit()
    embedHtml("", 2)

		for (var i in window.arbitrage.chartIds) {
			moveLayout(window.arbitrage.chartIds[i], 2)
		}

    if (!window.arbitrage.bLibLoaded) {
			var script = document.getElementById("chartjs_lib")
			script.remove()
		}
  },
  function (context) { // OnTick()
    var externalSys = getEAParameter(context, "externalSys")

    if (externalSys == "Oanda") {
      if (typeof window.pluginForOanda == "undefined") {
        return
      }
    } else {
      return
    }

    var currTime = new Date().getTime()
    var hour = new Date(currTime).getHours()
    var day = new Date(currTime).getDay()

    if (window.arbitrage.autoSave && currTime - window.arbitrage.latestSaveTime > 60000) {
      window.arbitrage.saveStatistics()
      window.arbitrage.latestSaveTime = currTime
    }

    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)

    var currentTick = getCurrentTick(context)
    var symbolName = currentTick.symbolName
    var askFintechee = currentTick.ask
    var bidFintechee = currentTick.bid

    if (window.arbitrage.latestDay != day) {
      window.arbitrage.updatePrevArbitrage()
      window.arbitrage.updateArbitrageChart(symbolName, true, -1)
      window.arbitrage.updateArbitrageChart2(symbolName, true, -1)
      window.arbitrage.latestDay = day
    }

    if (window.arbitrage.quotes[symbolName] == null) return

    var askExt = window.arbitrage.quotes[symbolName].ask
    var bidExt = window.arbitrage.quotes[symbolName].bid

    if (askFintechee != null && bidFintechee != null && askExt != null && bidExt != null) {
      var table = $('#arbitrage_prices').DataTable()
      var tb = $('#arbitrage_prices').dataTable()

      table.columns().eq(0).each(function (index) {
        if (index == 0) {
          var column = table.column(index).data()
          for (var i in column) {
            if (isNaN(i)) continue

            var rowId = parseInt(i)

            if (column[i] == symbolName) {
              tb.fnUpdate(Math.round((bidExt - askFintechee) * 100000) / 100000, rowId, 1, false, false)
              tb.fnUpdate(Math.round((bidFintechee - askExt) * 100000) / 100000, rowId, 2, false, false)
              tb.fnUpdate(Math.round((askExt + bidExt) / 2 * 100000) / 100000, rowId, 3, false, false)
              break
            }
          }
        }
      })

      if (bidExt > askFintechee) {
        window.arbitrage.count(symbolName, hour)
        if (symbolName == window.arbitrage.currentChartSymbolName) {
          window.arbitrage.updateArbitrageChart(symbolName, false, hour)
        }
        // var msg = new Date() + " " + symbolName + " Chance!! Ext Bid: " + bidExt + ", Fintechee Ask: " + askFintechee + ", Difference: " + (bidExt - askFintechee) + "\n"
        // printMessage(msg)
      }
      if (bidFintechee > askExt) {
        window.arbitrage.count2(symbolName, hour)
        if (symbolName == window.arbitrage.currentChartSymbolName) {
          window.arbitrage.updateArbitrageChart2(symbolName, false, hour)
        }
        // var msg = new Date() + " " + symbolName + " Chance!! Fintechee Bid: " + bidFintechee + ", Ext Ask: " + askExt + ", Difference: " + (bidFintechee - askExt) + "\n"
        // printMessage(msg)
      }
    }
  }
)


================================================
FILE: EA/Arbitrage/guide_for_fintechee_external_arbitrage.txt
================================================
To utilize this EA and display the statistics panel regarding the frequencies of arbitrage opportunities, you must first open the “plugin_for_oanda”.

Once 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.

Following 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.

The 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.



================================================
FILE: EA/Arbitrage/sample_trading_arbitrage.js
================================================
registerEA(
		"sample_trading_arbitrage",
		"Two accounts signed up on the different servers are required to trade arbitrage. Additionally please make sure that you have signed in to both accounts and logged out from the accounts in investor mode.(v1.04)",
		[],// parameters
		function (context) { // Init()
			var account1 = getAccount(context, 0)
			var account2 = getAccount(context, 1)

			var acc1 = {
				brokerName: getBrokerNameOfAccount(account1),
				accountId: getAccountIdOfAccount(account1),
				symbolName: "EUR/USD"
			}
			var acc2 = {
				brokerName: getBrokerNameOfAccount(account2),
				accountId: getAccountIdOfAccount(account2),
				symbolName: "EUR/USD"
			}

			getQuotes (context, acc1.brokerName, acc1.accountId, acc1.symbolName)
			getQuotes (context, acc2.brokerName, acc2.accountId, acc2.symbolName)

			context.acc1 = acc1
			context.acc2 = acc2
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
			var currTime = new Date().getTime()
			if (typeof context.currTime == "undefined") {
				context.currTime = currTime
			} else if (context.currTime <= currTime - 1000) {
				context.currTime = currTime
			} else {
				return
			}

			var acc1 = context.acc1
			var acc2 = context.acc2

			var ask1 = null
			var ask2 = null
			var bid1 = null
			var bid2 = null

			try {
				ask1 = getAsk(context, acc1.brokerName, acc1.accountId, acc1.symbolName)
				ask2 = getAsk(context, acc2.brokerName, acc2.accountId, acc2.symbolName)
				bid1 = getBid(context, acc1.brokerName, acc1.accountId, acc1.symbolName)
				bid2 = getBid(context, acc2.brokerName, acc2.accountId, acc2.symbolName)
			} catch (e) {
				// 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.)
				printErrorMessage(e.message)
				return
			}

			var volume = 0.01

			if (ask1 < bid2) {
				var tradeNum = getOpenTradesListLength(context)

				var acc1TradeId = null
				var acc2TradeId = null

				for (var i = tradeNum - 1; i >= 0; i--) {
					var trade = getOpenTrade(context, i)
					var brokerName = getBrokerName(trade)
					var accountId = getAccountId(trade)
					var tradeId = getTradeId(trade)
					var orderType = getOrderType(trade)
					if (brokerName == acc1.brokerName && accountId == acc1.accountId && orderType == ORDER_TYPE.OP_SELL) {
						acc1TradeId = tradeId
					}
					if (brokerName == acc2.brokerName && accountId == acc2.accountId && orderType == ORDER_TYPE.OP_BUY) {
						acc2TradeId = tradeId
					}
				}

				if (acc1TradeId == null) {
					sendOrder(acc1.brokerName, acc1.accountId, acc1.symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
				} else {
					closeTrade(acc1.brokerName, acc1.accountId, acc1TradeId, 0, 0)
				}

				if (acc2TradeId == null) {
					sendOrder(acc2.brokerName, acc2.accountId, acc2.symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
				} else {
					closeTrade(acc2.brokerName, acc2.accountId, acc2TradeId, 0, 0)
				}
			} else if (ask2 < bid1) {
				var tradeNum = getOpenTradesListLength(context)

				var acc1TradeId = null
				var acc2TradeId = null

				for (var i = tradeNum - 1; i >= 0; i--) {
					var trade = getOpenTrade(context, i)
					var brokerName = getBrokerName(trade)
					var accountId = getAccountId(trade)
					var tradeId = getTradeId(trade)
					var orderType = getOrderType(trade)
					if (brokerName == acc2.brokerName && accountId == acc2.accountId && orderType == ORDER_TYPE.OP_SELL) {
						acc2TradeId = tradeId
					}
					if (brokerName == acc1.brokerName && accountId == acc1.accountId && orderType == ORDER_TYPE.OP_BUY) {
						acc1TradeId = tradeId
					}
				}

				if (acc2TradeId == null) {
					sendOrder(acc2.brokerName, acc2.accountId, acc2.symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
				} else {
					closeTrade(acc2.brokerName, acc2.accountId, acc2TradeId, 0, 0)
				}

				if (acc1TradeId == null) {
					sendOrder(acc1.brokerName, acc1.accountId, acc1.symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
				} else {
					closeTrade(acc1.brokerName, acc1.accountId, acc1TradeId, 0, 0)
				}
			}
		}
	)


================================================
FILE: EA/Built-in/README.md
================================================
The EAs in this folder will be updated automatically when you open the WEB trader.

If you customize the EAs in this folder, please rename them to avoid being overwritten.


================================================
FILE: EA/Built-in/sample_using_rsi.js
================================================
registerEA(
		"sample_using_rsi",
		"A test EA based on rsi(v1.01)",
		[{ // parameters
			name: "period",
			value: 20,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		}],
		function (context) { // Init()
			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			getQuotes (context, brokerName, accountId, symbolName)
			context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
			var period = getEAParameter(context, "period")
			context.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
				name: "period",
				value: period
			}])
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
			var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)
			if (typeof context.currTime == "undefined") {
				context.currTime = arrTime[arrTime.length - 1]
			} else if (context.currTime != arrTime[arrTime.length - 1]) {
				context.currTime = arrTime[arrTime.length - 1]
			} else {
				return
			}

			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			var arrRsi = getData(context, context.indiHandle, "rsi")

			var ask = null
			var bid = null
			try {
				ask = getAsk(context, brokerName, accountId, symbolName)
				bid = getBid(context, brokerName, accountId, symbolName)
			} catch (e) {
				// 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.)
				printErrorMessage(e.message)
				return
			}

			var limitPrice = 0.0003
			var stopPrice = 0.0003
			var volume = 0.01

			if (30 < arrRsi[arrRsi.length - 3] && 30 > arrRsi[arrRsi.length - 2]) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUYLIMIT, ask-limitPrice, 0, volume, ask+limitPrice, bid-3*stopPrice, "", 0, 0)
			} else if (70 > arrRsi[arrRsi.length - 3] && 70 < arrRsi[arrRsi.length - 2]) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELLLIMIT, bid+limitPrice, 0, volume, bid-limitPrice, ask+3*stopPrice, "", 0, 0)
			}
		}
	)


================================================
FILE: EA/Built-in/sample_using_sma.js
================================================
registerEA(
		"sample_using_sma",
		"A test EA based on sma(v1.04)",
		[{ // parameters
			name: "period",
			value: 20,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		}],
		function (context) { // Init()
			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			getQuotes (context, brokerName, accountId, symbolName)
			context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
			var period = getEAParameter(context, "period")
			context.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "sma", [{
				name: "period",
				value: period
			}])
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
			var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)
			if (typeof context.currTime == "undefined") {
				context.currTime = arrTime[arrTime.length - 1]
			} else if (context.currTime != arrTime[arrTime.length - 1]) {
				context.currTime = arrTime[arrTime.length - 1]
			} else {
				return
			}

			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)
			var arrSma = getData(context, context.indiHandle, "sma")

			var ask = null
			var bid = null
			try {
				ask = getAsk(context, brokerName, accountId, symbolName)
				bid = getBid(context, brokerName, accountId, symbolName)
			} catch (e) {
				// 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.)
				printErrorMessage(e.message)
				return
			}

			var limitPrice = 0.0003
			var stopPrice = 0.0003
			var volume = 0.01

			if (arrClose[arrClose.length - 3] < arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] > arrSma[arrSma.length - 2]) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUYLIMIT, ask-limitPrice, 0, volume, ask+limitPrice, bid-3*stopPrice, "", 0, 0)
			} else if (arrClose[arrClose.length - 3] > arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] < arrSma[arrSma.length - 2]) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELLLIMIT, bid+limitPrice, 0, volume, bid-limitPrice, ask+3*stopPrice, "", 0, 0)
			}
		}
	)


================================================
FILE: EA/Chaos/chaos.js
================================================
registerEA(
  "chaos",
  "An EA based on Chaos theory(v1.0)",
  [{
    name: "symbolName",
    value: "EUR/USD",
    required: true,
    type: "String",
    range: null,
    step: null
  }, {
    name: "volume",
    value: 0.01,
    required: true,
    type: "Number",
    range: [0.01, 1.0],
    step: null
  }, {
    name: "timeFrame",
    value: "H4",
    required: true,
    type: "String",
    range: null,
    step: null
  }],
  function (context) { // Init()
    // Bill Williams' Chaos Trading Strategy is amazing.
    // This EA is based on the theory written in his book "Trading Chaos".

    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)
    var symbolName = getEAParameter(context, "symbolName")
    var timeFrame = getEAParameter(context, "timeFrame")

    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame)
    context.fractalsHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, "fractals", [])
    context.alligatorHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, "alligator", [{
      name: "jawsPeriod", value: 13}, {name: "jawsShift", value: 8}, {
      name: "teethPeriod", value: 8}, {name: "teethShift", value: 5}, {
      name: "lipsPeriod", value: 5}, {name: "lipsShift", value: 3}, {
      name: "method", value: "smma"}])
    context.aoHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, "ao", [])
    context.acHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, "ac", [])

    context.chaos = {
      fractalsUpIdx: -1,
      fractalsDownIdx: -1,
      fractalsUp: 0,
      fractalsDown: 0,
      fractalsUpTriggered: false,
      fractalsDownTriggered: false,
      getFractalsSignal: function (arrUp, arrDown) {
        var cursor = arrUp.length - 4
        var latestUpIdx = -1
        var latestDownIdx = -1

        while (cursor >= 0) {
          if (arrUp[cursor] != 0) {
            if (latestUpIdx == -1) {
              latestUpIdx = cursor
            }
            if (latestDownIdx != -1) {
              break
            }
          }
          if (arrDown[cursor] != 0) {
            if (latestDownIdx == -1) {
              latestDownIdx = cursor
            }
            if (latestUpIdx != -1) {
              break
            }
          }
          cursor--
        }

        if (latestUpIdx != -1 && latestDownIdx != -1) {
          if (latestUpIdx != this.fractalsUpIdx) {
            this.fractalsUpIdx = latestUpIdx
            this.fractalsUpTriggered = false
          }
          if (latestDownIdx != this.fractalsDownIdx) {
            this.fractalsDownIdx = latestDownIdx
            this.fractalsDownTriggered = false
          }
          this.fractalsUp = arrUp[latestUpIdx]
          this.fractalsDown = arrDown[latestDownIdx]
        }
      },
      checkFractalsSignal: function (arrTeeth, currTick) {
        if (this.fractalsUp > 0) {
          if (!this.fractalsUpTriggered) {
            if (currTick > this.fractalsUp && currTick > arrTeeth[arrTeeth.length - 6]) {
              this.fractalsUpTriggered = true
              return 1
            }
          }
        }

        if (this.fractalsDown > 0) {
          if (!this.fractalsDownTriggered) {
            if (currTick < this.fractalsDown && currTick < arrTeeth[arrTeeth.length - 6]) {
              this.fractalsDownTriggered = true
              return 0
            }
          }
        }

        return -1
      },
      aoUpIdx1: -1,
      aoDownIdx1: -1,
      aoUp1: 0,
      aoDown1: 0,
      aoUpTriggered1: false,
      aoDownTriggered1: false,
      aoUpIdx2: -1,
      aoDownIdx2: -1,
      aoUp2: 0,
      aoDown2: 0,
      aoUpTriggered2: false,
      aoDownTriggered2: false,
      aoUpIdx3: -1,
      aoDownIdx3: -1,
      aoUp3: 0,
      aoDown3: 0,
      aoUpTriggered3: false,
      aoDownTriggered3: false,
      getAoSignal: function (arrUp, arrDown, arrHigh, arrLow) {
        var arrLen = arrHigh.length

        if (arrUp[arrLen - 2] > 0 && arrDown[arrLen - 3] > 0 && (arrUp[arrLen - 4] > arrDown[arrLen - 3] || arrDown[arrLen - 4] > arrDown[arrLen - 3])) {
          if (arrLen - 2 != this.aoUpIdx1) {
            this.aoUpIdx1 = arrLen - 2
            this.aoDownIdx1 = -1
            this.aoUp1 = arrHigh[arrLen - 2]
            this.aoDown1 = 0
            this.aoUpTriggered1 = false
            this.aoDownTriggered1 = false
          }
        } else if (arrDown[arrLen - 2] < 0 && arrUp[arrLen - 3] < 0 && (arrUp[arrLen - 4] < arrUp[arrLen - 3] || arrDown[arrLen - 4] < arrUp[arrLen - 3])) {
          if (arrLen - 2 != this.aoDownIdx1) {
            this.aoUpIdx1 = -1
            this.aoDownIdx1 = arrLen - 2
            this.aoUp1 = 0
            this.aoDown1 = arrLow[arrLen - 2]
            this.aoUpTriggered1 = false
            this.aoDownTriggered1 = false
          }
        } else {
          this.aoUpIdx1 = -1
          this.aoDownIdx1 = -1
          this.aoUp1 = 0
          this.aoDown1 = 0
          this.aoUpTriggered1 = false
          this.aoDownTriggered1 = false
        }

        if (arrUp[arrLen - 2] > 0 && (arrUp[arrLen - 3] < 0 || (arrUp[arrLen - 4] < 0 && arrUp[arrLen - 3] == 0 && arrDown[arrLen - 3] == 0))) {
          if (arrLen - 2 != this.aoUpIdx2) {
            this.aoUpIdx2 = arrLen - 2
            this.aoDownIdx2 = -1
            this.aoUp2 = arrHigh[arrLen - 2]
            this.aoDown2 = 0
            this.aoUpTriggered2 = false
            this.aoDownTriggered2 = false
          }
        } else if (arrDown[arrLen - 2] < 0 && (arrDown[arrLen - 3] > 0 || (arrDown[arrLen - 4] > 0 && arrUp[arrLen - 3] == 0 && arrDown[arrLen - 3] == 0))) {
          if (arrLen - 2 != this.aoDownIdx2) {
            this.aoUpIdx2 = -1
            this.aoDownIdx2 = arrLen - 2
            this.aoUp2 = 0
            this.aoDown2 = arrLow[arrLen - 2]
            this.aoUpTriggered2 = false
            this.aoDownTriggered2 = false
          }
        } else {
          this.aoUpIdx2 = -1
          this.aoDownIdx2 = -1
          this.aoUp2 = 0
          this.aoDown2 = 0
          this.aoUpTriggered2 = false
          this.aoDownTriggered2 = false
        }

        var cursor = arrLen - 3
        var latestPeakIdx1 = -1
        var latestPeakIdx2 = -1
        var arrData = []
        var bContinue = true

        while (cursor >= 0) {
          if ((arrUp[cursor] > 0 && arrDown[cursor + 1] > 0) ||
              (arrDown[cursor] > 0 && arrUp[cursor + 1] > 0) ||
              (arrUp[cursor] > 0 && arrUp[cursor + 1] > 0) ||
              (arrDown[cursor] > 0 && arrDown[cursor + 1] > 0) ||
              (arrUp[cursor] < 0 && arrDown[cursor + 1] < 0) ||
              (arrDown[cursor] < 0 && arrUp[cursor + 1] < 0) ||
              (arrUp[cursor] < 0 && arrUp[cursor + 1] < 0) ||
              (arrDown[cursor] < 0 && arrDown[cursor + 1] < 0)) {

          } else {
            bContinue = false
          }

          if (arrUp[cursor + 1] != 0) {
            arrData.push({
              ao: arrUp[cursor + 1],
              idx: cursor + 1
            })
          }
          if (arrDown[cursor + 1] != 0) {
            arrData.push({
              ao: arrDown[cursor + 1],
              idx: cursor + 1
            })
          }

          var arrDataLen = arrData.length

          if (arrDataLen > 1) {
            if (arrData[arrDataLen - 1].ao < 0) {
              if (arrDataLen == 2 && arrData[1].ao > arrData[0].ao) {
                break
              } else {
                if (arrDataLen > 2 && arrData[arrDataLen - 1].ao > arrData[arrDataLen - 2].ao && arrData[arrDataLen - 2].ao < arrData[arrDataLen - 3].ao) {
                  if (latestPeakIdx1 != -1) {
                    latestPeakIdx2 = arrData[arrDataLen - 2].idx
                    break
                  } else {
                    latestPeakIdx1 = arrData[arrDataLen - 2].idx
                  }
                }
              }
            } else {
              if (arrDataLen == 2 && arrData[1].ao < arrData[0].ao) {
                break
              } else {
                if (arrDataLen > 2 && arrData[arrDataLen - 1].ao < arrData[arrDataLen - 2].ao && arrData[arrDataLen - 2].ao > arrData[arrDataLen - 3].ao) {
                  if (latestPeakIdx1 != -1) {
                    latestPeakIdx2 = arrData[arrDataLen - 2].idx
                    break
                  } else {
                    latestPeakIdx1 = arrData[arrDataLen - 2].idx
                  }
                }
              }
            }
          }

          if (!bContinue) {
            break
          }

          cursor--
        }

        if (latestPeakIdx2 != -1) {
          if (arrData[0].ao < 0 && arrDown[latestPeakIdx1] > arrDown[latestPeakIdx2]) {
            if (latestPeakIdx1 + 1 != this.aoUpIdx3) {
              this.aoUpIdx3 = latestPeakIdx1 + 1
              this.aoDownIdx3 = -1
              this.aoUp3 = arrHigh[latestPeakIdx1 + 1]
              this.aoDown3 = 0
              this.aoUpTriggered3 = false
              this.aoDownTriggered3 = false
            }
          } else if (arrData[0].ao > 0 && arrUp[latestPeakIdx1] < arrUp[latestPeakIdx2]) {
            if (latestPeakIdx1 + 1 != this.aoDownIdx3) {
              this.aoUpIdx3 = -1
              this.aoDownIdx3 = latestPeakIdx1 + 1
              this.aoUp3 = 0
              this.aoDown3 = arrLow[latestPeakIdx1 + 1]
              this.aoUpTriggered3 = false
              this.aoDownTriggered3 = false
            }
          } else {
            this.aoUpIdx3 = -1
            this.aoDownIdx3 = -1
            this.aoUp3 = 0
            this.aoDown3 = 0
            this.aoUpTriggered3 = false
            this.aoDownTriggered3 = false
          }
        } else {
          this.aoUpIdx3 = -1
          this.aoDownIdx3 = -1
          this.aoUp3 = 0
          this.aoDown3 = 0
          this.aoUpTriggered3 = false
          this.aoDownTriggered3 = false
        }
      },
      checkAoSignal: function (currTick) {
        var signal1 = -1
        var signal2 = -1
        var signal3 = -1

        if (this.aoUp1 > 0) {
          if (!this.aoUpTriggered1) {
            if (currTick > this.aoUp1) {
              this.aoUpTriggered1 = true
              signal1 = 1
            }
          }
        }

        if (this.aoDown1 > 0) {
          if (!this.aoDownTriggered1) {
            if (currTick < this.aoDown1) {
              this.aoDownTriggered1 = true
              signal1 = 0
            }
          }
        }

        if (this.aoUp2 > 0) {
          if (!this.aoUpTriggered2) {
            if (currTick > this.aoUp2) {
              this.aoUpTriggered2 = true
              signal2 = 1
            }
          }
        }

        if (this.aoDown2 > 0) {
          if (!this.aoDownTriggered2) {
            if (currTick < this.aoDown2) {
              this.aoDownTriggered2 = true
              signal2 = 0
            }
          }
        }

        if (this.aoUp3 > 0) {
          if (!this.aoUpTriggered3) {
            if (currTick > this.aoUp3) {
              this.aoUpTriggered3 = true
              signal3 = 1
            }
          }
        }

        if (this.aoDown3 > 0) {
          if (!this.aoDownTriggered3) {
            if (currTick < this.aoDown3) {
              this.aoDownTriggered3 = true
              signal3 = 0
            }
          }
        }

        return {
          signal1: signal1,
          signal2: signal2,
          signal3: signal3
        }
      },
      acUpIdx1: -1,
      acDownIdx1: -1,
      acUp1: 0,
      acDown1: 0,
      acUpTriggered1: false,
      acDownTriggered1: false,
      acUpIdx2: -1,
      acDownIdx2: -1,
      acUp2: 0,
      acDown2: 0,
      acUpTriggered2: false,
      acDownTriggered2: false,
      getAcSignal: function (arrUp, arrDown, arrHigh, arrLow) {
        var arrLen = arrHigh.length

        if (arrDown[arrLen - 4] != 0 && arrUp[arrLen - 3] != 0 && arrUp[arrLen - 2] > 0) {
          if (arrLen - 2 != this.acUpIdx1) {
            this.acUpIdx1 = arrLen - 2
            this.acDownIdx1 = -1
            this.acUp1 = arrHigh[arrLen - 2]
            this.acDown1 = 0
            this.acUpTriggered1 = false
            this.acDownTriggered1 = false
          }
        } else if (arrUp[arrLen - 4] != 0 && arrDown[arrLen - 3] != 0 && arrDown[arrLen - 2] < 0) {
          if (arrLen - 2 != this.acDownIdx1) {
            this.acUpIdx1 = -1
            this.acDownIdx1 = arrLen - 2
            this.acUp1 = 0
            this.acDown1 = arrLow[arrLen - 2]
            this.acUpTriggered1 = false
            this.acDownTriggered1 = false
          }
        } else {
          this.acUpIdx1 = -1
          this.acDownIdx1 = -1
          this.acUp1 = 0
          this.acDown1 = 0
          this.acUpTriggered1 = false
          this.acDownTriggered1 = false
        }

        if (arrDown[arrLen - 5] < 0 && arrUp[arrLen - 4] < 0 && arrUp[arrLen - 3] < 0 && arrUp[arrLen - 2] != 0) {
          if (arrLen - 2 != this.acUpIdx2) {
            this.acUpIdx2 = arrLen - 2
            this.acDownIdx2 = -1
            this.acUp2 = arrHigh[arrLen - 2]
            this.acDown2 = 0
            this.acUpTriggered2 = false
            this.acDownTriggered2 = false
          }
        } else if (arrUp[arrLen - 5] > 0 && arrDown[arrLen - 4] > 0 && arrDown[arrLen - 3] > 0 && arrDown[arrLen - 2] != 0) {
          if (arrLen - 2 != this.acDownIdx2) {
            this.acUpIdx2 = -1
            this.acDownIdx2 = arrLen - 2
            this.acUp2 = 0
            this.acDown2 = arrLow[arrLen - 2]
            this.acUpTriggered2 = false
            this.acDownTriggered2 = false
          }
        } else {
          this.acUpIdx2 = -1
          this.acDownIdx2 = -1
          this.acUp2 = 0
          this.acDown2 = 0
          this.acUpTriggered2 = false
          this.acDownTriggered2 = false
        }
      },
      checkAcSignal: function (currTick) {
        var signal1 = -1
        var signal2 = -1

        if (this.acUp1 > 0) {
          if (!this.acUpTriggered1) {
            if (currTick > this.acUp1) {
              this.acUpTriggered1 = true
              signal1 = 1
            }
          }
        }

        if (this.acDown1 > 0) {
          if (!this.acDownTriggered1) {
            if (currTick < this.acDown1) {
              this.acDownTriggered1 = true
              signal1 = 0
            }
          }
        }

        if (this.acUp2 > 0) {
          if (!this.acUpTriggered2) {
            if (currTick > this.acUp2) {
              this.acUpTriggered2 = true
              signal2 = 1
            }
          }
        }

        if (this.acDown2 > 0) {
          if (!this.acDownTriggered2) {
            if (currTick < this.acDown2) {
              this.acDownTriggered2 = true
              signal2 = 0
            }
          }
        }

        return {
          signal1: signal1,
          signal2: signal2
        }
      },
      mapUpIdx: -1,
      mapDownIdx: -1,
      mapUp: 0,
      mapDown: 0,
      mapUpTriggered: false,
      mapDownTriggered: false,
      mapUpCnt: 0,
      mapDownCnt: 0,
      mapUpSl: 0,
      mapDownSl: 0,
      mapUpSlTriggered: false,
      mapDownSlTriggered: false,
      getMapSignal: function (arrAoUp, arrAoDown, arrAcUp, arrAcDown, arrClose, arrHigh, arrLow) {
        var arrLen = arrClose.length

        if (arrAoUp[arrLen - 2] != 0 && arrAcUp[arrLen - 2] != 0) {
          if (arrLen - 2 != this.mapUpIdx) {
            if (this.mapUpIdx == -1) {
              this.mapUpCnt = 1
            } else {
              this.mapUpCnt++
            }
            this.mapDownCnt = 0
            this.mapUpIdx = arrLen - 2
            this.mapDownIdx = -1
            this.mapUp = arrClose[arrLen - 2]
            this.mapDown = 0
            this.mapUpTriggered = false
            this.mapDownTriggered = false
            if (this.mapUpCnt >= 6) {
              this.mapUp = 0
              this.mapUpTriggered = false
              this.mapUpSl = arrLow[arrLen - 2]
              this.mapUpSlTriggered = false
            } else {
              this.mapUpSl = 0
              this.mapUpSlTriggered = false
            }
            this.mapDownSl = 0
            this.mapDownSlTriggered = false
          }
        } else if (arrAoDown[arrLen - 2] != 0 && arrAcDown[arrLen - 2] != 0) {
          if (arrLen - 2 != this.mapDownIdx) {
            this.mapUpCnt = 0
            if (this.mapDownIdx == -1) {
              this.mapDownCnt = 1
            } else {
              this.mapDownCnt++
            }
            this.mapUpIdx = -1
            this.mapDownIdx = arrLen - 2
            this.mapUp = 0
            this.mapDown = arrClose[arrLen - 2]
            this.mapUpTriggered = false
            this.mapDownTriggered = false
            this.mapUpSl = 0
            this.mapUpSlTriggered = false
            if (this.mapDownCnt >= 6) {
              this.mapDown = 0
              this.mapDownTriggered = false
              this.mapDownSl = arrHigh[arrLen - 2]
              this.mapDownSlTriggered = false
            } else {
              this.mapDownSl = 0
              this.mapDownSlTriggered = false
            }
          }
        } else {
          this.mapUpIdx = -1
          this.mapDownIdx = -1
          this.mapUp = 0
          this.mapDown = 0
          this.mapUpTriggered = false
          this.mapDownTriggered = false
          if (this.mapUpCnt >= 5) {
            this.mapUpSl = arrLow[arrLen - 2]
            this.mapUpSlTriggered = false
          } else {
            this.mapUpCnt = 0
            this.mapUpSl = 0
            this.mapUpSlTriggered = false
          }
          if (this.mapDownCnt >= 5) {
            this.mapDownSl = arrHigh[arrLen - 2]
            this.mapDownSlTriggered = false
          } else {
            this.mapDownCnt = 0
            this.mapDownSl = 0
            this.mapDownSlTriggered = false
          }
        }
      },
      checkMapSignal: function (currTick, prevHigh, prevLow) {
        var signal = -1

        if (this.mapUp > 0) {
          if (!this.mapUpTriggered) {
            if (currTick > this.mapUp) {
              if (this.mapUpCnt >= 5) {
                this.mapUp = 0
                this.mapUpTriggered = false
                this.mapUpSl = prevLow
                this.mapUpSlTriggered = false
              } else {
                this.mapUpTriggered = true
                this.mapUpSl = 0
                this.mapUpSlTriggered = false
              }
              this.mapDownSl = 0
              this.mapDownSlTriggered = false

              signal = 1
            }
          }
        }

        if (this.mapDown > 0) {
          if (!this.mapDownTriggered) {
            if (currTick < this.mapDown) {
              this.mapUpSl = 0
              this.mapUpSlTriggered = false
              if (this.mapDownCnt >= 5) {
                this.mapDown = 0
                this.mapDownTriggered = false
                this.mapDownSl = prevHigh
                this.mapDownSlTriggered = false
              } else {
                this.mapDownTriggered = true
                this.mapDownSl = 0
                this.mapDownSlTriggered = false
              }

              signal = 0
            }
          }
        }

        if (this.mapUpSl > 0) {
          if (!this.mapUpSlTriggered) {
            if (currTick < this.mapUpSl) {
              this.mapUpSlTriggered = true
              this.mapUpCnt = 0
              signal = 3
            }
          }
        }

        if (this.mapDownSl > 0) {
          if (!this.mapDownSlTriggered) {
            if (currTick > this.mapDownSl) {
              this.mapDownSlTriggered = true
              this.mapDownCnt = 0
              signal = 2
            }
          }
        }

        return signal
      },
      alligatorUpIdx1: -1,
      alligatorDownIdx1: -1,
      alligatorUp1: 0,
      alligatorDown1: 0,
      alligatorUpTriggered1: false,
      alligatorDownTriggered1: false,
      alligatorUpBase1: 0,
      alligatorDownBase1: 0,
      alligatorUpIdx2: -1,
      alligatorDownIdx2: -1,
      alligatorUp2: 0,
      alligatorDown2: 0,
      alligatorUpTriggered2: false,
      alligatorDownTriggered2: false,
      alligatorUpBase2: 0,
      alligatorDownBase2: 0,
      alligatorUpIdx3: -1,
      alligatorDownIdx3: -1,
      alligatorUp3: 0,
      alligatorDown3: 0,
      alligatorUpTriggered3: false,
      alligatorDownTriggered3: false,
      alligatorUpBase3: 0,
      alligatorDownBase3: 0,
      getAlligatorSignal: function (arrHigh, arrLow, currLip, currJaw, currAoUp, currAoDown, currAcUp, currAcDown) {
        var arrLen = arrHigh.length

        if (this.alligatorUpIdx1 != 0) {
          if (this.alligatorUpBase1 > arrHigh[arrLen - 2]) {
            this.alligatorUpIdx1 = -1
            this.alligatorUp1 = 0
            this.alligatorUpTriggered1 = false
            this.alligatorUpBase1 = 0
          }
        }
        if (this.alligatorDownIdx1 != 0) {
          if (this.alligatorDownBase1 < arrLow[arrLen - 2]) {
            this.alligatorDownIdx1 = -1
            this.alligatorDown1 = 0
            this.alligatorDownTriggered1 = false
            this.alligatorDownBase1 = 0
          }
        }

        if (arrHigh[arrLen - 3] > arrHigh[arrLen - 2] && arrHigh[arrLen - 2] > currLip) {
          if (arrLen - 3 != this.alligatorUpIdx1) {
            this.alligatorUpIdx1 = arrLen - 3
            this.alligatorUp1 = arrHigh[arrLen - 3]
            this.alligatorUpTriggered1 = false
            this.alligatorUpBase1 = arrHigh[arrLen - 2]
          }
        } else if (arrLow[arrLen - 3] < arrLow[arrLen - 2] && arrLow[arrLen - 2] < currLip) {
          if (arrLen - 3 != this.alligatorDownIdx1) {
            this.alligatorDownIdx1 = arrLen - 3
            this.alligatorDown1 = arrLow[arrLen - 3]
            this.alligatorDownTriggered1 = false
            this.alligatorDownBase1 = arrLow[arrLen - 2]
          }
        }

        if (this.alligatorUpIdx2 != 0) {
          if (this.alligatorUpBase2 > arrHigh[arrLen - 2]) {
            this.alligatorUpIdx2 = -1
            this.alligatorUp2 = 0
            this.alligatorUpTriggered2 = false
            this.alligatorUpBase2 = 0
          }
        }
        if (this.alligatorDownIdx2 != 0) {
          if (this.alligatorDownBase2 < arrLow[arrLen - 2]) {
            this.alligatorDownIdx2 = -1
            this.alligatorDown2 = 0
            this.alligatorDownTriggered2 = false
            this.alligatorDownBase2 = 0
          }
        }

        if (arrHigh[arrLen - 4] > arrHigh[arrLen - 3] && arrHigh[arrLen - 3] > arrHigh[arrLen - 2] && arrHigh[arrLen - 2] < currJaw &&
            ((currAoUp != 0 && currAcUp != 0) || (currAoUp != 0 && currAcDown != 0) || (currAoDown != 0 && currAcUp != 0))) {
          if (arrLen - 4 != this.alligatorUpIdx2) {
            this.alligatorUpIdx2 = arrLen - 4
            this.alligatorUp2 = arrHigh[arrLen - 4]
            this.alligatorUpTriggered2 = false
            this.alligatorUpBase2 = arrHigh[arrLen - 2]
          }
        } else if (arrLow[arrLen - 4] < arrLow[arrLen - 3] && arrLow[arrLen - 3] < arrLow[arrLen - 2] && arrLow[arrLen - 2] > currJaw &&
            ((currAoDown != 0 && currAcDown != 0) || (currAoUp != 0 && currAcDown != 0) || (currAoDown != 0 && currAcUp != 0))) {
          if (arrLen - 4 != this.alligatorDownIdx2) {
            this.alligatorDownIdx2 = arrLen - 4
            this.alligatorDown2 = arrLow[arrLen - 4]
            this.alligatorDownTriggered2 = false
            this.alligatorDownBase2 = arrLow[arrLen - 2]
          }
        }

        if (this.alligatorUpIdx3 != 0) {
          if (this.alligatorUpBase3 > arrHigh[arrLen - 2]) {
            this.alligatorUpIdx3 = -1
            this.alligatorUp3 = 0
            this.alligatorUpTriggered3 = false
            this.alligatorUpBase3 = 0
          }
        }
        if (this.alligatorDownIdx3 != 0) {
          if (this.alligatorDownBase3 < arrLow[arrLen - 2]) {
            this.alligatorDownIdx3 = -1
            this.alligatorDown3 = 0
            this.alligatorDownTriggered3 = false
            this.alligatorDownBase3 = 0
          }
        }

        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] &&
            arrHigh[arrLen - 2] < currJaw && currAoDown != 0 && currAcDown != 0) {
          if (arrLen - 6 != this.alligatorUpIdx3) {
            this.alligatorUpIdx3 = arrLen - 6
            this.alligatorUp3 = arrHigh[arrLen - 6]
            this.alligatorUpTriggered3 = false
            this.alligatorUpBase3 = arrHigh[arrLen - 2]
          }
        } 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] &&
            arrLow[arrLen - 2] > currJaw && currAoUp != 0 && currAcUp != 0) {
          if (arrLen - 6 != this.alligatorDownIdx3) {
            this.alligatorDownIdx3 = arrLen - 6
            this.alligatorDown3 = arrLow[arrLen - 6]
            this.alligatorDownTriggered3 = false
            this.alligatorDownBase3 = arrLow[arrLen - 2]
          }
        }
      },
      checkAlligatorSignal: function (currTick) {
        var signal1 = -1
        var signal2 = -1
        var signal3 = -1

        if (this.alligatorUp1 > 0) {
          if (!this.alligatorUpTriggered1) {
            if (currTick > this.alligatorUp1) {
              this.alligatorUpTriggered1 = true
              signal1 = 1
            }
          }
        }

        if (this.alligatorDown1 > 0) {
          if (!this.alligatorDownTriggered1) {
            if (currTick < this.alligatorDown1) {
              this.alligatorDownTriggered1 = true
              signal1 = 0
            }
          }
        }

        if (this.alligatorUp2 > 0) {
          if (!this.alligatorUpTriggered2) {
            if (currTick > this.alligatorUp2) {
              this.alligatorUpTriggered2 = true
              signal2 = 1
            }
          }
        }

        if (this.alligatorDown2 > 0) {
          if (!this.alligatorDownTriggered2) {
            if (currTick < this.alligatorDown2) {
              this.alligatorDownTriggered2 = true
              signal2 = 0
            }
          }
        }

        if (this.alligatorUp3 > 0) {
          if (!this.alligatorUpTriggered3) {
            if (currTick > this.alligatorUp3) {
              this.alligatorUpTriggered3 = true
              signal3 = 1
            }
          }
        }

        if (this.alligatorDown3 > 0) {
          if (!this.alligatorDownTriggered3) {
            if (currTick < this.alligatorDown3) {
              this.alligatorDownTriggered3 = true
              signal3 = 0
            }
          }
        }

        return {
          signal1: signal1,
          signal2: signal2,
          signal3: signal3
        }
      },
      checkCloseSignal: function (arrTeeth, arrClose) {
        var arrLen = arrClose.length

        if (arrTeeth[arrLen - 7] > arrClose[arrLen - 2] && arrClose[arrLen - 3] >= arrTeeth[arrLen - 8]) {
          return 3
        }
        if (arrTeeth[arrLen - 7] < arrClose[arrLen - 2] && arrClose[arrLen - 3] <= arrTeeth[arrLen - 8]) {
          return 2
        }

        return -1
      },
      trend: -1
    }
  },
  function (context) { // Deinit()
  },
  function (context) { // OnTick()
    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)
    var symbolName = getEAParameter(context, "symbolName")
    var volume = getEAParameter(context, "volume")
    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)
    var arrHigh = getData(context, context.chartHandle, DATA_NAME.HIGH)
    var arrLow = getData(context, context.chartHandle, DATA_NAME.LOW)
    var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)
    var arrTeeth = getData(context, context.alligatorHandle, "teeth")
    var arrLips = getData(context, context.alligatorHandle, "lips")
    var arrJaws = getData(context, context.alligatorHandle, "jaws")
    var arrUp = getData(context, context.fractalsHandle, "fractalsUp")
    var arrDown = getData(context, context.fractalsHandle, "fractalsDown")
    var arrAoUp = getData(context, context.aoHandle, "up")
    var arrAoDown = getData(context, context.aoHandle, "down")
    var arrAcUp = getData(context, context.acHandle, "up")
    var arrAcDown = getData(context, context.acHandle, "down")
    var arrLen = arrTime.length

    if (200 >= arrLen) throw new Error("No enough data.")

    var bGetSignals = false
    if (typeof context.currTime == "undefined") {
      context.currTime = arrTime[arrTime.length - 1]
      bGetSignals = true
    } else if (context.currTime != arrTime[arrTime.length - 1]) {
      context.currTime = arrTime[arrTime.length - 1]
      bGetSignals = true
    }

    if (bGetSignals) {
      context.chaos.getFractalsSignal(arrUp, arrDown)
      context.chaos.getAoSignal(arrAoUp, arrAoDown, arrHigh, arrLow)
      context.chaos.getAcSignal(arrAcUp, arrAcDown, arrHigh, arrLow)
      context.chaos.getMapSignal(arrAoUp, arrAoDown, arrAcUp, arrAcDown, arrClose, arrHigh, arrLow)
      context.chaos.getAlligatorSignal(arrHigh, arrLow, arrLips[arrLen - 2], arrJaws[arrLen - 2], arrAoUp[arrLen - 2], arrAoDown[arrLen - 2], arrAcUp[arrLen - 2], arrAcDown[arrLen - 2])
    }

    var signal = -1

    var fractalsSignal = context.chaos.checkFractalsSignal(arrTeeth, arrClose[arrLen - 1])
    if (fractalsSignal != -1) {
      signal = fractalsSignal
      context.chaos.trend = fractalsSignal
    }

    if (context.chaos.trend == -1) {
      return
    }

    var aoSignal = context.chaos.checkAoSignal(arrClose[arrLen - 1])
    if (aoSignal.signal1 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    if (aoSignal.signal2 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    if (aoSignal.signal3 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    var acSignal = context.chaos.checkAcSignal(arrClose[arrLen - 1])
    if (acSignal.signal1 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    if (acSignal.signal2 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    var mapSignal = context.chaos.checkMapSignal(arrClose[arrLen - 1], arrHigh[arrLen - 2], arrLow[arrLen - 2])
    if (mapSignal == context.chaos.trend) {
      signal = context.chaos.trend
    }
    var alligatorSignal = context.chaos.checkAlligatorSignal(arrClose[arrLen - 1])
    if (alligatorSignal.signal1 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    if (alligatorSignal.signal2 == context.chaos.trend) {
      signal = context.chaos.trend
    }
    if (alligatorSignal.signal3 == context.chaos.trend) {
      signal = context.chaos.trend
    }

    var closeSignal = context.chaos.checkCloseSignal(arrTeeth, arrClose)
    if (closeSignal != -1) {
      signal = closeSignal
    }
    if ((mapSignal == 3 && context.chaos.trend == 1) || (mapSignal == 2 && context.chaos.trend == 0)) {
      signal = mapSignal
    }

    if (signal == 1) {
      popupMessage("You received an OPEN LONG signal!")
    } else if (signal == 0) {
      popupMessage("You received an OPEN SHORT signal!")
    } else if (signal == 3) {
      if (bGetSignals) {
        popupMessage("You received a CLOSE LONG signal!")
      }
    } else if (signal == 2) {
      if (bGetSignals) {
        popupMessage("You received a CLOSE SHORT signal!")
      }
    }
  },
  function (context) { // OnTransaction()
  }
)


================================================
FILE: EA/Chaos/intro.txt
================================================
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.


================================================
FILE: EA/CopyTrading/README.md
================================================
This is just an example.


================================================
FILE: EA/CopyTrading/copy_trading_for_oanda.js
================================================
registerEA(
		"copy_trading_for_oanda",
		"An EA to copy trading for Oanda(v1.02)",
		[],
		function (context) { // Init()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		},
		function (context) { // OnTransaction()
		  if (typeof window.pluginForOanda != "undefined") {
		    var transType = getLatestTransType(context)

		    if (transType == "Open Trade") {
					var trade = getLatestTrans(context)
			    var tradeSymbolName = getSymbolName(trade)
			    var tradeOrderType = getOrderType(trade)
			    var tradeLots = getOpenLots(trade)

		      if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {
		        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_BUY, tradeLots)
		      } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {
		        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_SELL, tradeLots)
		      }
		    } else if (transType == "Trade Closed") {
					var trade = getLatestTrans(context)
			    var tradeSymbolName = getSymbolName(trade)
			    var tradeOrderType = getOrderType(trade)
			    var tradeLots = getOpenLots(trade)

		      if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {
		        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_SELL, tradeLots)
		      } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {
		        window.pluginForOanda.sendOrder(tradeSymbolName, ORDER_TYPE.OP_BUY, tradeLots)
		      }
		    }
		  }
		}
	)


================================================
FILE: EA/CopyTrading/copy_trading_for_oanda_guide.txt
================================================
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.

How to do?
1. A shares A's investor password with B.
Please note, enabling investor mode is not required for this step.
If you enable investor mode, then everyone can check your trading records.
If you disable investor mode(disabled by default), then only the followers that know your investor password can check your trading records.

2. B signs into both accounts.
B signs into A's account by entering A's investor password.
B signs into B's Oanda-based account by launching an EA named plugin_for_oanda.
You can get plugin_for_oanda on Fintechee's Github repo:
https://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/Plugin-for-Oanda/plugin_for_oanda.js
Oanda issues a token as login credential. So, B needs to input it into the corresponding parameter for oanda_loader.

3. B launches copy_trading_for_oanda via Fintechee WEB Trader.
You can get copy_trading_for_oanda on Fintechee's Github repo:
https://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/CopyTrading/copy_trading_for_oanda.js
There are no parameters because the EA will follow all the signals that it receives and trade via B's Oanda account.
B has logged into A's account in the investor mode, so all the signals that A issues will be seen by B.
The EA will send orders via the plugin_for_oanda launched in the 2nd step.

Done!



================================================
FILE: EA/CopyTrading/copy_trading_locally.js
================================================
registerEA(
"copy_trading_locally",
"A simple EA to copy trading locally(v1.01)",
[{
	name: "fromAccountId",
	value: "XXXXXXXXXX", // e.g. account id:1066149, investor password: 1
	required: true,
	type: "String",
	range: null,
	step: null
}, {
	name: "toAccountId",
	value: "XXXXXXXXXX",
	required: true,
	type: "String",
	range: null,
	step: null
}],
function (context) { // Init()
		},
function (context) { // Deinit()
		},
function (context) { // OnTick()
		},
function (context) { // OnTransaction()
  var account = getAccount(context, 0)
  var brokerName = getBrokerNameOfAccount(account)
  var fromAccountId = getEAParameter(context, "fromAccountId")
  var toAccountId = getEAParameter(context, "toAccountId")
  var volume = 0.01
  var transType = getLatestTransType(context)

  if (transType == "Open Trade" && tradeAccountId == fromAccountId) {
		var trade = getLatestTrans(context)
	  var tradeAccountId = getAccountId(trade)
	  var tradeSymbolName = getSymbolName(trade)
	  var tradeOrderType = getOrderType(trade)

    if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {
      sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
    } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {
      sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
    }
  } else if (transType == "Trade Closed" && tradeAccountId == fromAccountId) {
		var trade = getLatestTrans(context)
	  var tradeAccountId = getAccountId(trade)
	  var tradeSymbolName = getSymbolName(trade)
	  var tradeOrderType = getOrderType(trade)

    var tradeOrderType2 = null

    if (tradeOrderType == ORDER_TYPE.OP_BUY || tradeOrderType == ORDER_TYPE.OP_BUYLIMIT || tradeOrderType == ORDER_TYPE.OP_BUYSTOP) {
      tradeOrderType2 = ORDER_TYPE.OP_BUY
    } else if (tradeOrderType == ORDER_TYPE.OP_SELL || tradeOrderType == ORDER_TYPE.OP_SELLLIMIT || tradeOrderType == ORDER_TYPE.OP_SELLSTOP) {
      tradeOrderType2 = ORDER_TYPE.OP_SELL
    }

    var count = getOpenTradesListLength(context)
    var tradeId = null

    for (var i = count - 1; i >= 0; i--) {
      var openTrade = getOpenTrade(context, i)
      var accountId = getAccountId(openTrade)
      var symbolName = getSymbolName(openTrade)
      var orderType = getOrderType(openTrade)

      if (accountId == toAccountId && symbolName == tradeSymbolName && tradeOrderType2 == orderType) {
        tradeId = getTradeId(openTrade)
        break
      }
    }

    if (tradeId != null) {
      closeTrade(brokerName, toAccountId, tradeId, 0, 0)
    } else {
      if (tradeOrderType2 == ORDER_TYPE.OP_BUY) {
        sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
      } else if (tradeOrderType2 == ORDER_TYPE.OP_SELL) {
        sendOrder(brokerName, toAccountId, tradeSymbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
      }
    }
  }
})


================================================
FILE: EA/CopyTrading/copy_trading_locally_guide.txt
================================================
Use Case: A provides signals, B follows the signals from A to copy trade. Both accounts are Fintechee-based.

How to do?
1. A shares A's investor password with B.
Please note, enabling investor mode is not required for this step.
If you enable investor mode, then everyone can check your trading records.
If you disable investor mode(disabled by default), then only the followers that know your investor password can check your trading records.

2. B signs into both accounts.
B signs into A's account by entering A's investor password.
B signs into B's own account by entering B's password.

3. B launches copy_trading_locally via Fintechee WEB Trader.
If copy_trading_locally doesn't exist, you can get it on Fintechee's Github repo:
https://github.com/fintechees/Expert-Advisor-Studio/blob/master/EA/CopyTrading/copy_trading_locally.js
Copy the source codes and paste them into Fintechee WEB Trader's Javascript console and run it.
Then you can find it listed on the EA list and launch it.
There are two parameters: fromAccountId and toAccountId.
B sets fromAccountId to A's account ID and sets toAccountId to B's account ID.

Done!



================================================
FILE: EA/Martingale/improved_martingale.js
================================================
registerEA(
  "improved_martingale",
  "An EA based on an improved Martingale algorithm(v1.0)",
  [{
    name: "diffPrice",
    value: 0.002,
    required: true,
    type: PARAMETER_TYPE.NUMBER,
    range: [0, 100]
  }, {
    name: "diffPrice2",
    value: 0.001,
    required: true,
    type: PARAMETER_TYPE.NUMBER,
    range: [0, 100]
  }],
  function(context) { // Init()
    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)
    var symbolName = "EUR/USD"

    getQuotes(context, brokerName, accountId, symbolName)

    context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.H1)
    context.maxCost = Number.MAX_VALUE
    context.maxPos = 0
    context.openTrades = []
    context.res = []
  },
  function(context) { // Deinit()
  },
  function(context) { // OnTick()
    var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)

    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)
    var symbolName = "EUR/USD"
    var diffPrice = getEAParameter(context, "diffPrice")
		var diffPrice2 = getEAParameter(context, "diffPrice2")

		var 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.

    var ask = null
    var bid = null

    try {
      ask = getAsk(context, brokerName, accountId, symbolName)
      bid = getBid(context, brokerName, accountId, symbolName)
    } catch (e) {
      // 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.)
      printErrorMessage(e.message)
      return
    }

    var count = getOpenTradesListLength(context)
    var countL = 0
    var countS = 0
    var totalPLL = 0.0
    var totalPLS = 0.0
    var highPriceL = -Number.MAX_VALUE
    var lowPriceL = Number.MAX_VALUE
    var highPriceS = -Number.MAX_VALUE
    var lowPriceS = Number.MAX_VALUE

    for (var i = count - 1; i >= 0; i--) {
      var openTrade = getOpenTrade(context, i)

      var openPrice = getOpenPrice(openTrade)

      if (getOrderType(openTrade) == ORDER_TYPE.OP_BUY) {
        countL++
        totalPLL += getUnrealizedPL(openTrade)

        if (openPrice > highPriceL) highPriceL = openPrice
        if (openPrice < lowPriceL) lowPriceL = openPrice
      }
      if (getOrderType(openTrade) == ORDER_TYPE.OP_SELL) {
        countS++
        totalPLS += getUnrealizedPL(openTrade)

        if (openPrice > highPriceS) highPriceS = openPrice
        if (openPrice < lowPriceS) lowPriceS = openPrice
      }
    }

    if (totalPLL + totalPLS < context.maxCost) {
      context.maxCost = totalPLL + totalPLS
    }

    if (Math.abs(countL - countS) > Math.abs(context.maxPos)) {
      context.maxPos = countL - countS
    }

    if (typeof context.currTime == "undefined") {
      context.currTime = arrTime[arrTime.length - 1]
    } else if (context.currTime != arrTime[arrTime.length - 1]) {
      context.currTime = arrTime[arrTime.length - 1]
    } else {
      return
    }

    var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)

    var volume = 0.01

    if (countL == 0 && countS == 0) {
			if (signal == 1) {
        sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
			} else {
        sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
			}
		} else if (((countL + countS) > 1 && (totalPLL + totalPLS) > 0.1 * (countL + countS)) ||
							(countL == 1 && countS == 0 && signal == 0 && (arrClose[arrClose.length - 1] - highPriceL) > diffPrice) ||
							(countL == 0 && countS == 1 && signal == 1 && (lowPriceS - arrClose[arrClose.length - 1]) > diffPrice)) {

      var pos = Math.abs(countL - countS)
      if (typeof context.res[pos] == "undefined") {
        context.res[pos] = 1
      } else {
        context.res[pos]++
      }
      for (var i in context.res) {
        printMessage(i + ", " + context.res[i])
      }

      printMessage("Pos: " + (countL - countS) + ", Unrealized PL: " + (totalPLL + totalPLS) +
                  ", Max Cost: " + context.maxCost + ", Max Pos: " + context.maxPos)

      for (var i = count - 1; i >= 0; i--) {
        var openTrade = getOpenTrade(context, i)

        closeTrade(brokerName, accountId, getTradeId(openTrade), 0, 0)
      }
		} else if (countL == 1 && countS == 0 && signal == 0 && (highPriceL - arrClose[arrClose.length - 1]) > diffPrice) {
      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL == 0 && countS == 1 && signal == 1 && (arrClose[arrClose.length - 1] - lowPriceS) > diffPrice) {
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
    } else if (countL > 0 && countS > 0 && highPriceL > highPriceS && (arrClose[arrClose.length - 1] - highPriceL) > diffPrice && lowPriceL > lowPriceS) {
      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL > 0 && countS > 0 && highPriceS > highPriceL && (arrClose[arrClose.length - 1] - highPriceS) > diffPrice && lowPriceL < lowPriceS) {
      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL > 0 && countS > 0 && lowPriceL > lowPriceS && (lowPriceS - arrClose[arrClose.length - 1]) > diffPrice && highPriceL > highPriceS) {
      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL > 0 && countS > 0 && lowPriceS > lowPriceL && (lowPriceL - arrClose[arrClose.length - 1]) > diffPrice && highPriceL < highPriceS) {
      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
    } else if (countL > 0 && countS > 0 && highPriceL > highPriceS && (arrClose[arrClose.length - 1] - highPriceL) > diffPrice2 && lowPriceL < lowPriceS) {
      sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL > 0 && countS > 0 && highPriceS > highPriceL && (arrClose[arrClose.length - 1] - highPriceS) > diffPrice2 && lowPriceL > lowPriceS) {
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL > 0 && countS > 0 && lowPriceL > lowPriceS && (lowPriceS - arrClose[arrClose.length - 1]) > diffPrice2 && highPriceL < highPriceS) {
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
		} else if (countL > 0 && countS > 0 && lowPriceS > lowPriceL && (lowPriceL - arrClose[arrClose.length - 1]) > diffPrice2 && highPriceL > highPriceS) {
			sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
    }
  },
  function(context) { // OnTransaction()
  }
)


================================================
FILE: EA/Martingale/improved_martingale.txt
================================================
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.
If 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.


================================================
FILE: EA/Martingale/sample_martingale.js
================================================
registerEA(
	"sample_martingale",
	"A test EA based on Martingale algorithm(v1.03)",
	[{ // parameters
		name: "period",
		value: 5,
		required: true,
		type: PARAMETER_TYPE.INTEGER,
		range: [1, 100]
	}],
	function (context) { // Init()
		var account = getAccount(context, 0)
		var brokerName = getBrokerNameOfAccount(account)
		var accountId = getAccountIdOfAccount(account)
		var symbolName = "EUR/USD"

		context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
		var period = getEAParameter(context, "period")
		context.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "sma", [{
			name: "period",
			value: period
		}])
	},
	function (context) { // Deinit()
	},
	function (context) { // OnTick()
		var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)
		if (typeof context.currTime == "undefined") {
			context.currTime = arrTime[arrTime.length - 1]
		} else if (context.currTime != arrTime[arrTime.length - 1]) {
			context.currTime = arrTime[arrTime.length - 1]
		} else {
			return
		}

		var account = getAccount(context, 0)
		var brokerName = getBrokerNameOfAccount(account)
		var accountId = getAccountIdOfAccount(account)
		var symbolName = "EUR/USD"

		var count = getOpenTradesListLength(context)
		var totalPL = 0.0
		var highPrice = 0.0
		var lowPrice = 100000000.0
		var orientation = null

		for (var i = count - 1; i >= 0; i--) {
			var openTrade = getOpenTrade(context, i)

			totalPL += getUnrealizedPL(openTrade)

			var openPrice = getOpenPrice(openTrade)

			if (openPrice > highPrice) highPrice = openPrice
			if (openPrice < lowPrice) lowPrice = openPrice
			if (getOrderType(openTrade) == ORDER_TYPE.OP_BUY) orientation = ORDER_TYPE.OP_BUY
			if (getOrderType(openTrade) == ORDER_TYPE.OP_SELL) orientation = ORDER_TYPE.OP_SELL
		}

		var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)
		var arrSma = getData(context, context.indiHandle, "sma")

		var volume = 0.01

		if (count > 0 && totalPL > 0.1 * count) {
			for (var i = count - 1; i >= 0; i--) {
				var openTrade = getOpenTrade(context, i)

				closeTrade(brokerName, accountId, getTradeId(openTrade), 0, 0)
			}
		} else if (count == 0) {
			if (arrClose[arrClose.length - 3] < arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] > arrSma[arrSma.length - 2]) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
			} else if (arrClose[arrClose.length - 3] > arrSma[arrSma.length - 3] && arrClose[arrClose.length - 2] < arrSma[arrSma.length - 2]) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
			}
		} else {
			if (orientation == ORDER_TYPE.OP_BUY && (lowPrice - arrClose[arrClose.length - 1]) > 0.0005) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, 0, 0, "", 0, 0)
			}
			if (orientation == ORDER_TYPE.OP_SELL && (arrClose[arrClose.length - 1] - highPrice) > 0.0005) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, 0, 0, "", 0, 0)
			}
		}
	},
	function (context) { // OnTransaction()
		printMessage("test OnTransaction: " + getLatestTransId(context) + " " + getLatestTransType(context))
	}
)


================================================
FILE: EA/NeuralNetwork/nn_example.js
================================================
// Please check this post to know how to use this EA: https://www.fintecher.org/daily-trading/added-genetic-algorithm-for-trading.html
registerEA(
"nn_example",
"A test EA to run neuron model for XOR(v1.0)",
[
// hidden layer(1st neuron)
{name: "h11", value: 20, required: true, type: "Number", range: [-100, 100], step: 10},
{name: "h12", value: 20, required: true, type: "Number", range: [-100, 100], step: 10},
{name: "b1", value: -10, required: true, type: "Number", range: [-100, 100], step: 10},
// hidden layer(2nd neuron)
{name: "h21", value: -20, required: true, type: "Number", range: [-100, 100], step: 10},
{name: "h22", value: -20, required: true, type: "Number", range: [-100, 100], step: 10},
{name: "b2", value: 30, required: true, type: "Number", range: [-100, 100], step: 10},
// output layer
{name: "o1", value: 20, required: true, type: "Number", range: [-100, 100], step: 10},
{name: "o2", value: 20, required: true, type: "Number", range: [-100, 100], step: 10},
{name: "b", value: -30, required: true, type: "Number", range: [-100, 100], step: 10},
],
function (context) { // Init()
    // Please don't remove the source codes below, they are required to make an EA get boosted
	var account = getAccount(context, 0)
	var brokerName = getBrokerNameOfAccount(account)
	var accountId = getAccountIdOfAccount(account)
	var symbolName = "EUR/USD"

	getQuotes (context, brokerName, accountId, symbolName)

},
function (context) { // Deinit()
	var h11 = getEAParameter(context, "h11") // weight
	var h12 = getEAParameter(context, "h12") // weight
	var b1 = getEAParameter(context, "b1") // bias
	var h21 = getEAParameter(context, "h21")
	var h22 = getEAParameter(context, "h22")
	var b2 = getEAParameter(context, "b2")
	var o1 = getEAParameter(context, "o1") // weight
	var o2 = getEAParameter(context, "o2") // weight
	var b = getEAParameter(context, "b") // bias

	var sigmoid = function (t) {
		return 1 / (1 + Math.pow(Math.E, -t))
	}

	var nn = function (p1, p2) {
		return sigmoid(o1 * sigmoid(h11 * p1 + h12 * p2 + b1) + o2 * sigmoid(h21 * p1 + h22 * p2 + b2) + b)
	}

	var error = 0

	error += nn(1, 1)
	error += 1 - nn(1, 0)
	error += 1 - nn(0, 1)
	error += nn(0, 0)

	setOptimizationResult(context, -error)

	printMessage("error: " + error + ", " + Math.round(nn(1, 1)) + " " + Math.round(nn(1, 0)) + " " + Math.round(nn(0, 1)) + " " + Math.round(nn(0, 0)))
},
function (context) { // OnTick()
})


================================================
FILE: EA/NeuralNetwork/sample_run_neuron_model.js
================================================
registerEA(
		"sample_run_neuron_model",
		"A test EA to run neuron model(v1.04)",
		[{ // parameters
			name: "period",
			value: 20,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		},{
			name: "inputNum",
			value: 20,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		},{
			name: "threshold",
			value: 0.3,
			required: true,
			type: PARAMETER_TYPE.NUMBER,
			range: [0, 1]
		},{
			name: "takeProfit",
			value: 0.0001,
			required: true,
			type: PARAMETER_TYPE.NUMBER,
			range: [0, 100]
		}],
		function (context) { // Init()
			// We use localstorage.reservedZone to store the neural network.
			// Please don't change the name "reservedZone" or your data stored in this zone will be removed while the version is updated.
			if (typeof localStorage.reservedZone == "undefined") return

			var reservedZone = JSON.parse(localStorage.reservedZone)
			if (typeof reservedZone.sample_training_neuron_model == "undefined") return
			context.myPerceptron = synaptic.Network.fromJSON(reservedZone.sample_training_neuron_model)

			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			getQuotes (context, brokerName, accountId, symbolName)
			context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
			var period = getEAParameter(context, "period")
			context.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
				name: "period",
				value: period
			}])
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
			var arrTime = getData(context, context.chartHandle, DATA_NAME.TIME)
			if (typeof context.currTime == "undefined") {
				context.currTime = arrTime[arrTime.length - 1]
			} else if (context.currTime != arrTime[arrTime.length - 1]) {
				context.currTime = arrTime[arrTime.length - 1]
			} else {
				return
			}

			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			var period = getEAParameter(context, "period")
			var inputNum = getEAParameter(context, "inputNum")
			var threshold = getEAParameter(context, "threshold")
			var takeProfit = getEAParameter(context, "takeProfit")
			var arrRsi = getData(context, context.indiHandle, "rsi")

			if (inputNum + period - 1 > arrRsi.length) throw new Error("No enough data.")

			var input = []

			for (var i = arrRsi.length - inputNum - 1; i < arrRsi.length - 1; i++) {
				input.push(arrRsi[i] / 100)
			}

			var result = context.myPerceptron.activate(input)[0]
			printMessage(result)

			var ask = null
			var bid = null
			var volume = 0.01

			try {
				ask = getAsk(context, brokerName, accountId, symbolName)
				bid = getBid(context, brokerName, accountId, symbolName)
			} catch (e) {
				// 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.)
				printErrorMessage(e.message)
				return
			}

			if (result < 0.5 - threshold) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, ask+takeProfit, bid-3*takeProfit, "", 0, 0)
			} else if (result > 0.5 + threshold) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, bid-takeProfit, ask+3*takeProfit, "", 0, 0)
			}
		}
	)


================================================
FILE: EA/NeuralNetwork/sample_training_neuron_model.js
================================================
registerEA(
		"sample_training_neuron_model",
		"A test EA to train neuron model(v1.03)",
		[{ // parameters
			name: "period",
			value: 20,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		},{
			name: "inputNum",
			value: 20,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		},{
			name: "hiddenNum",
			value: 50,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [1, 100]
		},{
			name: "diffPrice",
			value: 0.0001,
			required: true,
			type: PARAMETER_TYPE.NUMBER,
			range: [0, 10]
		}],
		function (context) { // Init()
			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
			var period = getEAParameter(context, "period")
			context.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
				name: "period",
				value: period
			}])
		},
		function (context) { // Deinit()
			var period = getEAParameter(context, "period")
			var inputNum = getEAParameter(context, "inputNum")
			var hiddenNum = getEAParameter(context, "hiddenNum")
			var arrOpen = getData(context, context.chartHandle, DATA_NAME.OPEN)
			var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE)
			var arrRsi = getData(context, context.indiHandle, "rsi")

			if (arrRsi.length <= period + 1) return
			if (inputNum + period - 1 > arrRsi.length) throw new Error("No enough data.")

			// extend the prototype chain
			Perceptron.prototype = new synaptic.Network()
			Perceptron.prototype.constructor = Perceptron

			var myPerceptron = new Perceptron(inputNum, hiddenNum, 1)
			var myTrainer = new synaptic.Trainer(myPerceptron)

			var diffPrice = getEAParameter(context, "diffPrice")
			var trainingSet = []
			var longCount = 0
			var shortCount = 0

			for (var i = period - 1; i < arrRsi.length - inputNum; i++) {
				if (arrClose[i * inputNum + inputNum] - arrOpen[i * inputNum + inputNum] > diffPrice) {
					var input = []

					for (var j = 0; j < inputNum; j++) {
						input.push(arrRsi[i * inputNum + j] / 100)
					}

					trainingSet.push({
						input: input,
						output: [0]
					})

					longCount++
				} else if (arrOpen[i * inputNum + inputNum] - arrClose[i * inputNum + inputNum] > diffPrice) {
					var input = []

					for (var j = 0; j < inputNum; j++) {
						input.push(arrRsi[i * inputNum + j] / 100)
					}

					trainingSet.push({
						input: input,
						output: [1]
					})

					shortCount++
				}
			}

			myTrainer.train(trainingSet)

			// We use localstorage.reservedZone to store the neural network.
			// Please don't change the name "reservedZone" or your data stored in this zone will be removed while the version is updated.
			if (typeof localStorage.reservedZone == "undefined") {
				localStorage.reservedZone = JSON.stringify({sample_training_neuron_model: myPerceptron.toJSON()})
			} else {
				var reservedZone = JSON.parse(localStorage.reservedZone)
				reservedZone.sample_training_neuron_model = myPerceptron.toJSON()
				localStorage.reservedZone = JSON.stringify(reservedZone)
			}

			printMessage(longCount + ", " + shortCount)
			printMessage(JSON.stringify(trainingSet))
			printMessage(JSON.stringify(myPerceptron.toJSON()))
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/NeuralNetwork/usage.txt
================================================
“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.
“sample_training_neuron_model” trains the model, while “sample_run_neuron_model” generates signals based on the model trained by “sample_training_neuron_model”.

To help understand how a neural network works, we have included a simple example called “nn_example”.

The 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.


================================================
FILE: EA/Oldie/README.md
================================================
This folder contains the deprecated programs.


================================================
FILE: EA/Oldie/README.txt
================================================
This folder contains deprecated programs.


================================================
FILE: EA/Oldie/fixapi_oanda_arbitrage.js
================================================
// Deprecated. A new version has been released. Please refer to EA/fintechee_external_arbitrage.js.
registerEA(
  "fixapi_oanda_arbitrage",
  "A test EA to trade arbitrage based on the price difference between FIX API and Oanda(v1.10)",
  [{
    name: "autoLoad",
    value: true,
    required: true,
    type: PARAMETER_TYPE.BOOLEAN,
    range: null
  }, {
    name: "autoSave",
    value: true,
    required: true,
    type: PARAMETER_TYPE.BOOLEAN,
    range: null
  }, {
    name: "backgroundColor",
    value: "#dfc29a",
    required: true,
    type: PARAMETER_TYPE.STRING,
    range: null
  }],
  function (context) { // Init()
    var account = getAccount(context, 0)
    var brokerName = getBrokerNameOfAccount(account)
    var accountId = getAccountIdOfAccount(account)
    window.autoLoadArbitrageStats = getEAParameter(context, "autoLoad")
    window.autoSaveArbitrageStats = getEAParameter(context, "autoSave")
    window.arbitrageBgColor = getEAParameter(context, "backgroundColor")
    window.latestDay = new Date().getDay()

    if (typeof window.oandaLoaded != "undefined" && window.oandaLoaded) {
      window.latestFIXTickTime = new Date().getTime()
      window.latestSaveTime = window.latestFIXTickTime

      if (typeof window.arbitrageStatistics == "undefined") {
        for (var i in window.oandaApiLoader.oandaQuotes) {
          getQuotes(context, brokerName, accountId, i.replace("_", "/"))
        }

        window.arbitrageStatistics = []

        for (var i in window.oandaApiLoader.oandaQuotes) {
          window.arbitrageStatistics[i] = {
            h: [],
            h2: [],
            ph: [],
            ph2: []
          }
          for (var j = 0; j <= 23; j++) {
            window.arbitrageStatistics[i].h.push(0)
            window.arbitrageStatistics[i].h2.push(0)
            window.arbitrageStatistics[i].ph.push(0)
            window.arbitrageStatistics[i].ph2.push(0)
          }
        }

        window.loadArbitrageStatistics = function (arbitrageStatistics) {
          if (typeof localStorage.reservedZone != "undefined") {
            var reservedZone = JSON.parse(localStorage.reservedZone)

            if (typeof reservedZone.arbitrageStatistics != "undefined" && typeof reservedZone.arbitrageStatistics.statistics != "undefined") {
              if (new Date(reservedZone.arbitrageStatistics.latestSaveTime).getDay() < window.latestDay) {
                for (var i in reservedZone.arbitrageStatistics.statistics) {
                  var statistics = reservedZone.arbitrageStatistics.statistics[i]
                  arbitrageStatistics[statistics.symbolName] = {
                    h: [],
                    h2: [],
                    ph: statistics.h,
                    ph2: statistics.h2
                  }
                  for (var j = 0; j <= 23; j++) {
                    arbitrageStatistics[statistics.symbolName].h.push(0)
                    arbitrageStatistics[statistics.symbolName].h2.push(0)
                  }
                }
              } else {
                for (var i in reservedZone.arbitrageStatistics.statistics) {
                  var statistics = reservedZone.arbitrageStatistics.statistics[i]
                  arbitrageStatistics[statistics.symbolName] = {
                    h: statistics.h,
                    h2: statistics.h2,
                    ph: statistics.ph,
                    ph2: statistics.ph2
                  }
                }
              }
            }
          }
        }

        window.saveArbitrageStatistics = function (arbitrageStatistics) {
          var reservedZone = {}

          if (typeof localStorage.reservedZone != "undefined") {
            reservedZone = JSON.parse(localStorage.reservedZone)
          }

          reservedZone.arbitrageStatistics = {
            latestSaveTime: new Date().getTime(),
            statistics: []
          }

          for (var i in arbitrageStatistics) {
            reservedZone.arbitrageStatistics.statistics.push({
              symbolName: i,
              h: arbitrageStatistics[i].h,
              h2: arbitrageStatistics[i].h2,
              ph: arbitrageStatistics[i].ph,
              ph2: arbitrageStatistics[i].ph2
            })
          }

          localStorage.reservedZone = JSON.stringify(reservedZone)
        }

        window.countArbitrage = function (symbolName, hour) {
          window.arbitrageStatistics[symbolName].h[hour]++
        }

        window.countArbitrage2 = function (symbolName, hour) {
          window.arbitrageStatistics[symbolName].h2[hour]++
        }
      }

      if (typeof $("#arbitrage_dashboard").html() != "undefined") {
        $("#arbitrage_dashboard").remove()
      }

      var arbitrageChartPanel = '<div id="arbitrage_chart_dashboard" style="background:' + window.arbitrageBgColor + ';height:100%">' +
        '<div class="row" style="background:' + window.arbitrageBgColor + ';text-align:center">' +
          '<div class="ui buttons">' +
            // '<div class="ui button" style="background:' + window.arbitrageBgColor + '" id="btn_show_arbitrage_prices">List</div>' +
            '<div class="ui button" style="background:' + window.arbitrageBgColor + '" id="btn_load_arbitrage_statistics">Load</div>' +
            '<div class="ui button" style="background:' + window.arbitrageBgColor + '" id="btn_save_arbitrage_statistics">Save</div>' +
          '</div>' +
        '</div>' +
        '<div class="row">' +
          '<table id="arbitrage_prices" class="cell-border">' +
          '</table>' +
        '</div>' +
        '<div class="row">' +
          '<div class="chart-container" style="background:' + window.arbitrageBgColor + ';position:relative;height:35vh">' +
            '<canvas id="arbitrage_chart"></canvas>' +
          '</div>' +
        '</div>' +
      '</div>'

      var arbitragePricesPanel = '<div class="ui fullscreen modal" id="arbitrage_prices_dashboard">' +
        '<div class="content">' +
        '</div>' +
      '</div>'

      $("#reserved_zone").append(arbitragePricesPanel)

      if (getLayoutId() != 3) {
  			changeLayout(3)
  		}

  		window.chartIds = getLayout(2)
  		for (var i in window.chartIds) {
  			moveLayout(window.chartIds[i], 1)
  		}

      embedHtml(arbitrageChartPanel, 2)

      if (!$.fn.dataTable.isDataTable("#arbitrage_prices")) {
  			window.arbitragePricesTable = $("#arbitrage_prices").DataTable({
  				data: [],
  				columns: [
            {title: "Instruments"},
            {title: "FIX-Oanda",
  					render: function (data, type, row) {
  							if (data > 0) {
  								return '<p style = "background:#21BA45;color:#FFFFFF" >' + data + '</p>'
  							} else {
  								return '<p style = "background:' + window.arbitrageBgColor + ';color:#DB2828" >' + data + '</p>'
  							}
  						}
  					},
            {title: "Oanda-FIX",
  					render: function (data, type, row) {
                if (data > 0) {
                  return '<p style = "background:#21BA45;color:#FFFFFF" >' + data + '</p>'
                } else {
                  return '<p style = "background:' + window.arbitrageBgColor + ';color:#DB2828" >' + data + '</p>'
                }
  						}
  					},
            {title: "Oanda"},
            {title: "Op"}
  				],
          headerCallback: function (thead, data, start, end, display) {
            $(thead).css("background-color", window.arbitrageBgColor)
          },
          rowCallback: function (row, data, index) {
            $("td", row).css("background-color", window.arbitrageBgColor)
          },
          ordering: false,
          searching: false,
          bPaginate: false,
          bLengthChange: false,
          bFilter: false,
          bInfo: false,
          scrollY: "50vh",
          scrollCollapse: true,
          paging: false,
          columnDefs: [
            {width: "20%", targets: 0, className: "dt-body-center"},
            {width: "20%", targets: 1, className: "dt-body-right"},
            {width: "20%", targets: 2, className: "dt-body-right"},
            {width: "20%", targets: 3, className: "dt-body-right"},
            {width: "20%", targets: 4, className: "dt-body-center"},
            {width: "20%", targets: [0], className: "dt-head-center"},
            {width: "20%", targets: [1], className: "dt-head-center"},
            {width: "20%", targets: [2], className: "dt-head-center"},
            {width: "20%", targets: [3], className: "dt-head-center"},
            {width: "20%", targets: [4], className: "dt-head-center"},
            {
              targets: -1,
              data: null,
              defaultContent: '<button id="btn_check_arbitrage" class="ui button" style="padding:0;background:' + window.arbitrageBgColor + '"><i class="tachometer alternate blue icon"></i></button>' +
                              '<button id="btn_sell" class="ui button" style="padding:0;background:' + window.arbitrageBgColor + ';color:#DB2828">S</button>' +
                              '<button id="btn_buy" class="ui button" style="padding:0;background:' + window.arbitrageBgColor + ';color:#21BA45">B</button>'
            }
          ]
  			})

        for (var i in window.oandaApiLoader.oandaQuotes) {
          $("#arbitrage_prices").DataTable().row.add([
            i,
            "",
            "",
            "",
            ""
          ]).draw(false)
        }

        $("#arbitrage_prices tbody").on("click", "[id*=btn_check_arbitrage]", function () {
          if (typeof window.arbitragePricesTable != "undefined") {
            var data = window.arbitragePricesTable.row($(this).parents("tr")).data()
            if (typeof data == "undefined") {
              data = window.arbitragePricesTable.row($(this)).data()
            }

            window.currentChartSymbolName = data[0]
            window.arbitrageChart.data.datasets[0].label = window.currentChartSymbolName + "(F-O)"
            window.arbitrageChart.data.datasets[1].label = window.currentChartSymbolName + "(O-F)"
            window.arbitrageChart.data.datasets[2].label = window.currentChartSymbolName + "(F-O)"
            window.arbitrageChart.data.datasets[3].label = window.currentChartSymbolName + "(O-F)"
            window.updateArbitrageChart(data[0], true, -1)
            window.updateArbitrageChart2(data[0], true, -1)
          }
        })

        $("#btn_load_arbitrage_statistics").on("click", function () {
          window.loadArbitrageStatistics(window.arbitrageStatistics)
        })

        $("#btn_save_arbitrage_statistics").on("click", function () {
          window.saveArbitrageStatistics(window.arbitrageStatistics)
        })
  		}

      if (window.autoLoadArbitrageStats) {
        window.loadArbitrageStatistics(window.arbitrageStatistics)
      }

      if (typeof window.initArbitrageChart != "undefined") {
        window.initArbitrageChart(window.arbitrageStatistics)
      } else {
        var script = document.createElement("script")
        document.body.appendChild(script)
        script.onload = function () {
          window.initArbitrageChart = function (arbitrageStatistics) {
            var ctx = document.getElementById("arbitrage_chart").getContext("2d")
            window.currentChartSymbolName = "EUR/USD"
            var statistics = arbitrageStatistics[window.currentChartSymbolName]

            var labels = []
            var data = []
            var data2 = []
            var pdata = []
            var pdata2 = []
            for (var i = 0; i <= 23; i++) {
              labels.push(i + "")
              data.push(statistics.h[i])
              data2.push(statistics.h2[i])
              pdata.push(statistics.ph[i])
              pdata2.push(statistics.ph2[i])
            }

            window.arbitrageChart = new Chart(ctx, {
                type: "line",
                data: {
                    labels: labels,
                    datasets: [{
                        label: window.currentChartSymbolName + "(F-O)",
                        backgroundColor: "rgba(255,255,255,0)",
                        borderColor: "#DB2828",
                        data: data
                    }, {
                        label: window.currentChartSymbolName + "(O-F)",
                        backgroundColor: "rgba(255,255,255,0)",
                        borderColor: "#21BA45",
                        data: data2
                    }, {
                        label: window.currentChartSymbolName + "(F-O)",
                        backgroundColor: "rgba(255,255,255,0)",
                        borderColor: "#DB2828",
                        borderDash: [2, 3],
                        data: pdata
                    }, {
                        label: window.currentChartSymbolName + "(O-F)",
                        backgroundColor: "rgba(255,255,255,0)",
                        borderColor: "#21BA45",
                        borderDash: [2, 3],
                        data: pdata2
                    }]
                },
                options: {
                  responsive: true,
                  maintainAspectRatio: false
                }
            })
          }

          window.updateArbitrageChart = function (symbolName, bAll, hour) {
            if (bAll) {
              for (var i = 0; i <= 23; i++) {
                window.arbitrageChart.data.datasets[0].data[i] = window.arbitrageStatistics[symbolName].h[i]
                window.arbitrageChart.data.datasets[2].data[i] = window.arbitrageStatistics[symbolName].ph[i]
              }
            } else {
              window.arbitrageChart.data.datasets[0].data[hour] = window.arbitrageStatistics[symbolName].h[hour]
            }

            window.arbitrageChart.update()
          }

          window.updateArbitrageChart2 = function (symbolName, bAll, hour) {
            if (bAll) {
              for (var i = 0; i <= 23; i++) {
                window.arbitrageChart.data.datasets[1].data[i] = window.arbitrageStatistics[symbolName].h2[i]
                window.arbitrageChart.data.datasets[3].data[i] = window.arbitrageStatistics[symbolName].ph2[i]
              }
            } else {
              window.arbitrageChart.data.datasets[1].data[hour] = window.arbitrageStatistics[symbolName].h2[hour]
            }

            window.arbitrageChart.update()
          }

          window.updatePrevArbitrage = function () {
            for (var i in window.arbitrageStatistics) {
              window.arbitrageStatistics[i].ph = window.arbitrageStatistics[i].h
              window.arbitrageStatistics[i].ph2 = window.arbitrageStatistics[i].h2
              window.arbitrageStatistics[i].h = []
              window.arbitrageStatistics[i].h2 = []

              for (var j = 0; j <= 23; j++) {
                window.arbitrageStatistics[i].h.push(0)
                window.arbitrageStatistics[i].h2.push(0)
              }
            }
          }

          window.initArbitrageChart(window.arbitrageStatistics)
        }
        script.onerror = function () {
          alert("Failed to load required libs. Please refresh this page again.")
        }
        script.async = true
        script.src = "https://cdn.jsdelivr.net/npm/chart.js@2.8.0"
      }

      window.arbitrageNotification = ""
    } else {
      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.")
    }
  },
  function (context) { // Deinit()
    embedHtml("", 2)

		for (var i in window.chartIds) {
			moveLayout(window.chartIds[i], 2)
		}
  },
  function (context) { // OnTick()
    if (typeof window.oandaLoaded != "undefined" && window.oandaLoaded) {
      if (typeof window.latestFIXTickTime == "undefined" || typeof window.latestOandaTickTime == "undefined") return

      var currTime = new Date().getTime()
      var hour = new Date(currTime).getHours()
      var day = new Date(currTime).getDay()
      if (currTime - window.latestOandaTickTime > 30000) {
        window.oandaApiLoader.resetupSocket()
        window.oandaLoaded = false
        return
      }

      if (window.autoSaveArbitrageStats && currTime - window.latestSaveTime > 60000) {
        window.saveArbitrageStatistics(window.arbitrageStatistics)
        window.latestSaveTime = currTime
      }

      window.latestFIXTickTime = currTime

      var account = getAccount(context, 0)
      var brokerName = getBrokerNameOfAccount(account)
      var accountId = getAccountIdOfAccount(account)

      var currentTick = getCurrentTick(context)
      var symbolName = currentTick.symbolName
      var askFIXAPI = currentTick.ask
      var bidFIXAPI = currentTick.bid

      if (window.latestDay != day) {
        window.updatePrevArbitrage()
        window.updateArbitrageChart(symbolName, true, -1)
        window.updateArbitrageChart2(symbolName, true, -1)
        window.latestDay = day
      }

      if (window.oandaApiLoader.oandaQuotes[symbolName] == null) return

      var askOanda = window.oandaApiLoader.oandaQuotes[symbolName].ask
      var bidOanda = window.oandaApiLoader.oandaQuotes[symbolName].bid

      if (askFIXAPI != null && bidFIXAPI != null && askOanda != null && bidOanda != null) {
        var table = $('#arbitrage_prices').DataTable()
        var tb = $('#arbitrage_prices').dataTable()

        table.columns().eq(0).each(function (index) {
          if (index == 0) {
            var column = table.column(index).data()
            for (var i in column) {
              if (isNaN(i)) continue

              var rowId = parseInt(i)

              if (column[i] == symbolName) {
                tb.fnUpdate(Math.round((bidOanda - askFIXAPI) * 100000) / 100000, rowId, 1, false, false)
                tb.fnUpdate(Math.round((bidFIXAPI - askOanda) * 100000) / 100000, rowId, 2, false, false)
                tb.fnUpdate(Math.round((askOanda + bidOanda) / 2 * 100000) / 100000, rowId, 3, false, false)
                break
              }
            }
          }
        })

        if (bidOanda > askFIXAPI) {
          window.countArbitrage(symbolName, hour)
          if (symbolName == window.currentChartSymbolName) {
            window.updateArbitrageChart(symbolName, false, hour)
          }
          // var msg = new Date() + " " + symbolName + " Chance!! Oanda Bid: " + bidOanda + ", FIXAPI Ask: " + askFIXAPI + ", Difference: " + (bidOanda - askFIXAPI) + "\n"
          // printMessage(msg)
        }
        if (bidFIXAPI > askOanda) {
          window.countArbitrage2(symbolName, hour)
          if (symbolName == window.currentChartSymbolName) {
            window.updateArbitrageChart2(symbolName, false, hour)
          }
          // var msg = new Date() + " " + symbolName + " Chance!! FIXAPI Bid: " + bidFIXAPI + ", Oanda Ask: " + askOanda + ", Difference: " + (bidFIXAPI - askOanda) + "\n"
          // printMessage(msg)
        }
      }
    }
  }
)


================================================
FILE: EA/Plugin-for-Deribit/plugin_for_deribit.js
================================================
registerEA(
"plugin_for_deribit",
"A plugin to trade cryptocurrency options(v0.08)",
[{
	name: "interval",
	value: 30,
	required: true,
	type: "Integer",
	range: null,
	step: null
}],
function (context) { // Init()
      var orderBookId = null
      var loaded = false
      var latestHb = null

      var interval = getEAParameter(context, "interval") * 1000

      function convertOptionName (rawName) {
        var name = rawName.split("-")
        var year = name[1].substring(5, 7)
        var mon = name[1].substring(2, 5)
        var dt = name[1].substring(0, 2)
        var month = "00"
        if (mon == "JAN") {
          month = "01"
        } else if (mon == "FEB") {
          month = "02"
        } else if (mon == "MAR") {
          month = "03"
        } else if (mon == "APR") {
          month = "04"
        } else if (mon == "MAY") {
          month = "05"
        } else if (mon == "JUN") {
          month = "06"
        } else if (mon == "JUL") {
          month = "07"
        } else if (mon == "AUG") {
          month = "08"
        } else if (mon == "SEP") {
          month = "09"
        } else if (mon == "OCT") {
          month = "10"
        } else if (mon == "NOV") {
          month = "11"
        } else if (mon == "DEC") {
          month = "12"
        }
        var expiration = parseInt(year + month + dt)
        var optionName2 = name[0] + "-" + dt + mon + year

        return {
          optionName: name[0] + "-" + expiration,
          optionName2: optionName2,
          instrument: name[0],
          expiration: expiration,
          year: year,
          month: month,
          dt: dt,
          strikePrice: parseFloat(name[2]),
          callOrPut: name[3]
        }
      }

      function parseOrderBook (data) {
        var orderBookData = []

        for (var i in data) {
          var optionName = convertOptionName(data[i].instrument_name)

          if (typeof orderBookData[optionName.optionName] == "undefined") {
            orderBookData[optionName.optionName] = {
              optionName: optionName.optionName,
              optionName2: optionName.optionName2,
              instrument: optionName.instrument,
              expiration: optionName.expiration,
              year: optionName.year,
              month: optionName.month,
              dt: optionName.dt,
              prices: [],
              arrPrices: []
            }
          }

          if (typeof orderBookData[optionName.optionName].prices[optionName.strikePrice] == "undefined") {
            orderBookData[optionName.optionName].prices[optionName.strikePrice] = {
              strikePrice: optionName.strikePrice,
              bidC: optionName.callOrPut == "C" ? data[i].bid_price : null,
              askC: optionName.callOrPut == "C" ? data[i].ask_price : null,
              bidP: optionName.callOrPut == "P" ? data[i].bid_price : null,
              askP: optionName.callOrPut == "P" ? data[i].ask_price : null
            }
          } else {
            var price = orderBookData[optionName.optionName].prices[optionName.strikePrice]
            if (price.bidC == null) {
              price.bidC = optionName.callOrPut == "C" ? data[i].bid_price : null
            }
            if (price.askC == null) {
              price.askC = optionName.callOrPut == "C" ? data[i].ask_price : null
            }
            if (price.bidP == null) {
              price.bidP = optionName.callOrPut == "P" ? data[i].bid_price : null
            }
            if (price.askP == null) {
              price.askP = optionName.callOrPut == "P" ? data[i].ask_price : null
            }
          }
        }

        for (var i in orderBookData) {
          for (var j in orderBookData[i].prices) {
            orderBookData[i].arrPrices.push(orderBookData[i].prices[j])
          }
        }

        var expirations = []

        for (var i in orderBookData) {
          expirations.push({
            expiration: orderBookData[i].expiration,
            optionName: orderBookData[i].optionName,
            optionName2: orderBookData[i].optionName2
          })
        }

        expirations.sort(function (a, b) {return a.expiration - b.expiration})

        return {
          expirations: expirations,
          orderBookData: orderBookData
        }
      }

      function showOptions (expirations) {
        var optionsHtml = ""

        for (var i in expirations) {
          optionsHtml += '<div class="item" data-value="' + expirations[i].optionName + '">' + expirations[i].optionName2 + '</div>'
        }

        $("#crypto_options").empty()
        $("#crypto_options").html(optionsHtml)
        $("#crypto_options_dashboard").find(".ui.dropdown").dropdown("clear")
        $("#crypto_options_dashboard").find(".ui.dropdown").dropdown({
          autoFocus: false,
          showOnFocus: false,
          onChange: function (val) {
            for (var i in window.subscriptionIds) {
              unsubscribeIt(i)
            }
            window.subscriptionIds = []
            showOrderBook(val, window.orderBookData.orderBookData)
          }
        })
      }

      function checkHb () {
        if (new Date().getTime() - latestHb > interval) {
          printMessage("Timeout... Refreshing...")
          if (typeof window.wsockOpened != "undefined" && window.wsockOpened) {
            loaded = true
          }
          initCryptoOptionsWS()
        }
      }

      function showOrderBook (optionName, orderBookData) {
        if ($.fn.dataTable.isDataTable("#crypto_options_orderbook")) {
    			$("#crypto_options_orderbook").DataTable().clear().draw()

          for (var i in orderBookData) {
            if (orderBookData[i].optionName == optionName) {
              for (var j in orderBookData[i].arrPrices) {
                $("#crypto_options_orderbook").DataTable().row.add([
                  orderBookData[i].arrPrices[j].bidC != null ? orderBookData[i].arrPrices[j].bidC : "",
                  orderBookData[i].arrPrices[j].askC != null ? orderBookData[i].arrPrices[j].askC : "",
                  orderBookData[i].arrPrices[j].strikePrice,
                  orderBookData[i].arrPrices[j].bidP != null ? orderBookData[i].arrPrices[j].bidP : "",
                  orderBookData[i].arrPrices[j].askP != null ? orderBookData[i].arrPrices[j].askP : "",
                  0,
                  0,
                  0,
                  0
                ]).draw(false)

                subscribeIt(orderBookData[i].optionName2 + "-" + orderBookData[i].arrPrices[j].strikePrice + "-" + "C")
                subscribeIt(orderBookData[i].optionName2 + "-" + orderBookData[i].arrPrices[j].strikePrice + "-" + "P")
              }
            }
          }
        }
      }

      function initCryptoOptionsWS () {
        $("#disconnect_ws").html("Loading...")
        $("#disconnect_ws").addClass("disabled")
        $("#disconnect_ws").addClass("loading")

        if (typeof window.wsock != "undefined" && typeof window.subscriptionIds != "undefined") {
          for (var i in window.subscriptionIds) {
            unsubscribeIt(i)
          }
        }

        window.wsock = new WebSocket("wss://test.deribit.com/ws/api/v2")
        window.wsockOpened = false

        window.wsock.onmessage = function (e) {
          var resData = JSON.parse(e.data)
          if (orderBookId != null && typeof resData.id != "undefined" && orderBookId == resData.id) {
            window.orderBookData = parseOrderBook(resData.result)
            showOptions(window.orderBookData.expirations)
            showOrderBook(window.orderBookData.expirations[0].optionName, window.orderBookData.orderBookData)
            $("#disconnect_ws").html("Disconnect")
            $("#disconnect_ws").removeClass("loading")
            $("#disconnect_ws").removeClass("disabled")
          } else if (typeof resData.params != "undefined" &&
            typeof resData.params.data != "undefined" && typeof resData.params.data.instrument_name != "undefined" &&
            typeof window.subscriptionIds[resData.params.data.instrument_name] != "undefined") {

            latestHb = new Date().getTime()
            var name = resData.params.data.instrument_name.split("-")
            var bid = (resData.params.data.best_bid_price != null && resData.params.data.best_bid_price != 0) ? resData.params.data.best_bid_price : ""
            var ask = (resData.params.data.best_ask_price != null && resData.params.data.best_ask_price != 0) ? resData.params.data.best_ask_price : ""

            var table = $("#crypto_options_orderbook").DataTable()
            var tb = $("#crypto_options_orderbook").dataTable()

            table.columns().eq(0).each(function (index) {
              if (index == 2) {
                var column = table.column(index).data()
                for (var i in column) {
                  var rowId = parseInt(i)

                  var row = table.row(rowId).data()

                  if (column[i] == parseFloat(name[2])) {
                    if (name[3] == "C") {
                      if (row[0] != null && row[0] != "" && bid != "") {
                        tb.fnUpdate(bid - row[0], rowId, 5, false, false)
                      } else {
                        tb.fnUpdate(0, rowId, 5, false, false)
                      }
                      if (row[1] != null && row[1] != "" && ask != "") {
                        tb.fnUpdate(ask - row[1], rowId, 6, false, false)
                      } else {
                        tb.fnUpdate(0, rowId, 6, false, false)
                      }
                      tb.fnUpdate(bid, rowId, 0, false, false)
                      tb.fnUpdate(ask, rowId, 1, false, false)
                    } else if (name[3] == "P") {
                      if (row[3] != null && row[3] != "" && bid != "") {
                        tb.fnUpdate(bid - row[3], rowId, 7, false, false)
                      } else {
                        tb.fnUpdate(0, rowId, 7, false, false)
                      }
                      if (row[4] != null && row[4] != "" && ask != "") {
                        tb.fnUpdate(ask - row[4], rowId, 8, false, false)
                      } else {
                        tb.fnUpdate(0, rowId, 8, false, false)
                      }
                      tb.fnUpdate(bid, rowId, 3, false, false)
                      tb.fnUpdate(ask, rowId, 4, false, false)
                    }
                    break
                  }
                }
              }
            })
          }
        }

        window.wsock.onopen = function () {
          latestHb = new Date().getTime()
          window.wsockOpened = true
          if (loaded) {
            for (var i in window.subscriptionIds) {
              subscribeIt(i)
            }

            $("#disconnect_ws").html("Disconnect")
            $("#disconnect_ws").removeClass("loading")
            $("#disconnect_ws").removeClass("disabled")
          } else {
            getOrderBook("BTC")
          }
        }
      }

      function disconnectCryptoOptionsWS () {
        if (typeof window.wsockOpened != "undefined" && window.wsockOpened) {
          $("#disconnect_ws").html("Disconnected")
          $("#disconnect_ws").addClass("disabled")

          for (var i in window.subscriptionIds) {
            unsubscribeIt(i)
          }

          if (typeof window.wsTimer != "undefined") {
            clearInterval(window.wsTimer)
          }
          window.wsock.close()
          delete window.wsock
          delete window.wsockOpened
          delete window.wsTimer
        }
      }

      function getOrderBook (currency) {
        if (typeof window.wsockOpened != "undefined" && window.wsockOpened) {
          $("#disconnect_ws").html("Loading...")
          $("#disconnect_ws").addClass("disabled")
          $("#disconnect_ws").addClass("loading")

          for (var i in window.subscriptionIds) {
            unsubscribeIt(i)
          }
          window.subscriptionIds = []

          orderBookId = new Date().getTime()

          var msg = {
            jsonrpc: "2.0",
            id: orderBookId,
            method: "public/get_book_summary_by_currency",
            params: {
              currency: currency,
              kind: "option"
            }
          }

          window.wsock.send(JSON.stringify(msg))
        }
      }

      function subscribeIt (instrument) {
        if (typeof window.wsockOpened != "undefined" && window.wsockOpened) {
          window.subscriptionIds[instrument] = new Date().getTime()

          var msg = {
            jsonrpc: "2.0",
            id: window.subscriptionIds[instrument],
            method: "public/subscribe",
            params: {
              channels: [
                "ticker." + instrument + ".raw" // "deribit_price_index.btc_usd"
              ]
            }
          }

          window.wsock.send(JSON.stringify(msg))
        }
      }

      function unsubscribeIt (instrument) {
        if (typeof window.wsockOpened != "undefined" && window.wsockOpened) {
          var msg = {
            jsonrpc: "2.0",
            id: new Date().getTime(),
            method: "public/unsubscribe",
            params: {
              channels: [
                "ticker." + instrument + ".raw" // "deribit_price_index.btc_usd"
              ]
            }
          }

          window.wsock.send(JSON.stringify(msg))
        }
      }

      if (typeof $("#crypto_options_dashboard").html() == "undefined") {
        var panel = '<div class="ui modal" id="crypto_options_dashboard">' +
          '<i class="close icon"></i>' +
          '<div class="content">' +
            '<div class="ui button" id="get_btc">BTC</div>' +
            '<div class="ui button" id="get_eth">ETH</div>' +
            '<div class="ui selection dropdown" style="width:200px">' +
              '<input type="hidden" name="crypto_option">' +
              '<i class="dropdown icon"></i>' +
              '<div class="default text" id="current_crypto_option">Options</div>' +
              '<div class="menu" id="crypto_options">' +
              '</div>' +
            '</div>' +
          '</div>' +
          '<div class="content">' +
            '<div class="description">' +
              '<table id="crypto_options_orderbook" class="cell-border" cellspacing="0">' +
        			'</table>' +
            '</div>' +
          '</div>' +
          '<div class="actions">' +
            '<div class="ui button" id="disconnect_ws">Disconnect</div>' +
          '</div>' +
        '</div>'

        $("#reserved_zone").append(panel)
        window.subscriptionIds = []
      } else {
        loaded = true
      }

      if (!$.fn.dataTable.isDataTable("#crypto_options_orderbook")) {
  			$("#crypto_options_orderbook").DataTable({
  				data: [],
  				columns: [
  					{title: "Bid(C)",
              render: function (data, type, row) {
  							if (row[5] == 0) {
                  return '<p style = "color:#222222" >' + data + '</p>'
                } else if (row[5] > 0) {
  								return '<p style = "color:#21BA45" >' + data + '</p>'
  							} else {
  								return '<p style = "color:#DB2828" >' + data + '</p>'
  							}
  						}
            },
  					{title: "Ask(C)",
              render: function (data, type, row) {
                if (row[6] == 0) {
                  return '<p style = "color:#222222" >' + data + '</p>'
                } else if (row[6] > 0) {
                  return '<p style = "color:#21BA45" >' + data + '</p>'
                } else {
                  return '<p style = "color:#DB2828" >' + data + '</p>'
                }
              }
            },
            {title: "Strike Price"},
  					{title: "Bid(P)",
              render: function (data, type, row) {
                if (row[7] == 0) {
                  return '<p style = "color:#222222" >' + data + '</p>'
                } else if (row[7] > 0) {
                  return '<p style = "color:#21BA45" >' + data + '</p>'
                } else {
                  return '<p style = "color:#DB2828" >' + data + '</p>'
                }
              }
            },
  					{title: "Ask(P)",
              render: function (data, type, row) {
                if (row[8] == 0) {
                  return '<p style = "color:#222222" >' + data + '</p>'
                } else if (row[8] > 0) {
                  return '<p style = "color:#21BA45" >' + data + '</p>'
                } else {
                  return '<p style = "color:#DB2828" >' + data + '</p>'
                }
              }
            },
            {title: "Diff(BC)"},
            {title: "Diff(AC)"},
            {title: "Diff(BP)"},
            {title: "Diff(AP)"}
  				],
          ordering: false,
          searching: false,
          bPaginate: false,
          bLengthChange: false,
          bFilter: false,
          bInfo: false,
          scrollY: '50vh',
          scrollCollapse: true,
          paging: false,
          columnDefs: [
            {width: "20%", targets: 0, className: "dt-body-right"},
            {width: "20%", targets: 1, className: "dt-body-right"},
            {width: "20%", targets: 2, className: "dt-body-center"},
            {width: "20%", targets: 3, className: "dt-body-right"},
            {width: "20%", targets: 4, className: "dt-body-right"},
            {width: "20%", targets: [0, 1, 2, 3, 4], className: "dt-head-center"},
            {targets: [5, 6, 7, 8], visible: false}
          ]
  			})
  		}

      $("#get_btc").on("click", function () {
        getOrderBook("BTC")
      })
      $("#get_eth").on("click", function () {
        getOrderBook("ETH")
      })
      $("#disconnect_ws").on("click", function () {
        disconnectCryptoOptionsWS()
      })

      initCryptoOptionsWS()

      $("#crypto_options_dashboard").modal("show")

      if (typeof window.wsTimer != "undefined") {
        clearInterval(window.wsTimer)
      }
      window.wsTimer = setInterval(function () {
        checkHb()
      }, interval)
		},
function (context) { // Deinit()
		},
function (context) { // OnTick()
		})


================================================
FILE: EA/Plugin-for-Deribit/usage.txt
================================================
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.


================================================
FILE: EA/Plugin-for-EOS/decentralized_exchange_eos_approve.js
================================================
registerEA(
		"decentralized_exchange_eos_approve",
		"A decentralized exchange plugin to approve a proposal for exchanging digital assets via EOS platform(v1.0)",
		[{ // parameters
			name: "proposalName",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "proposer",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "approver",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var proposalName = getEAParameter(context, "proposalName")
			var proposer = getEAParameter(context, "proposer")
			var approver = getEAParameter(context, "approver")

			if (proposalName == null || proposalName == "") {
				popupErrorMessage("The proposal name should not be empty.")
				return
			}
			if (proposer == null || proposer == "") {
				popupErrorMessage("The proposer should not be empty.")
				return
			}
			if (approver == null || approver == "") {
				popupErrorMessage("The approver should not be empty.")
				return
			}

			(async () => {
				try {
					const result = await window.eos_api.transact({
						actions: [{
							account: "eosio.msig",
							name: "approve",
							authorization: [{
								actor: approver,
								permission: "active"
							}],
							data: {
								proposer: proposer,
								proposal_name: proposalName,
								level: {
									actor: approver,
									permission: "active",
								}
							}
						}]
					}, {
						blocksBehind: 3,
						expireSeconds: 30,
						broadcast: true,
						sign: true
					})

					popupMessage("Approved!\n\n" + JSON.stringify(result, null, 2))
				} catch (e) {
					popupErrorMessage("Caught exception: " + e)

	        if (e instanceof window.eosjs_jsonrpc.RpcError) {
						popupErrorMessage(JSON.stringify(e.json, null, 2))
					}
	      }
			})()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/decentralized_exchange_eos_cancel.js
================================================
registerEA(
		"decentralized_exchange_eos_cancel",
		"A decentralized exchange plugin to cancel a proposal for exchanging digital assets via EOS platform(v1.0)",
		[{ // parameters
			name: "proposalName",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "proposer",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "canceler",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var proposalName = getEAParameter(context, "proposalName")
			var proposer = getEAParameter(context, "proposer")
			var canceler = getEAParameter(context, "canceler")

			if (proposalName == null || proposalName == "") {
				popupErrorMessage("The proposal name should not be empty.")
				return
			}
			if (proposer == null || proposer == "") {
				popupErrorMessage("The proposer should not be empty.")
				return
			}
			if (canceler == null || canceler == "") {
				popupErrorMessage("The canceler should not be empty.")
				return
			}

			(async () => {
				try {
					const result = await window.eos_api.transact({
						actions: [{
							account: "eosio.msig",
							name: "cancel",
							authorization: [{
								actor: canceler,
								permission: "active"
							}],
							data: {
								proposer: proposer,
								proposal_name: proposalName,
								canceler: canceler
							}
						}]
					}, {
						blocksBehind: 3,
						expireSeconds: 30,
						broadcast: true,
						sign: true
					})

					popupMessage("Canceled!\n\n" + JSON.stringify(result, null, 2))
				} catch (e) {
					popupErrorMessage("Caught exception: " + e)

	        if (e instanceof window.eosjs_jsonrpc.RpcError) {
						popupErrorMessage(JSON.stringify(e.json, null, 2))
					}
	      }
			})()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/decentralized_exchange_eos_exec.js
================================================
registerEA(
		"decentralized_exchange_eos_exec",
		"A decentralized exchange plugin to execute a transaction of exchanging digital assets via EOS platform(v1.0)",
		[{ // parameters
			name: "proposalName",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "proposer",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "executor",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var proposalName = getEAParameter(context, "proposalName")
			var proposer = getEAParameter(context, "proposer")
			var executor = getEAParameter(context, "executor")

			if (proposalName == null || proposalName == "") {
				popupErrorMessage("The proposal name should not be empty.")
				return
			}
			if (proposer == null || proposer == "") {
				popupErrorMessage("The proposer should not be empty.")
				return
			}
			if (executor == null || executor == "") {
				popupErrorMessage("The executor should not be empty.")
				return
			}

			(async () => {
				try {
					const result = await window.eos_api.transact({
						actions: [{
							account: "eosio.msig",
							name: "exec",
							authorization: [{
								actor: executor,
								permission: "active"
							}],
							data: {
								proposer: proposer,
								proposal_name: proposalName,
								executer: executor
							}
						}]
					}, {
						blocksBehind: 3,
						expireSeconds: 30,
						broadcast: true,
						sign: true
					})

					popupMessage("Transaction pushed!\n\n" + JSON.stringify(result, null, 2))
				} catch (e) {
					popupErrorMessage("Caught exception: " + e)

	        if (e instanceof window.eosjs_jsonrpc.RpcError) {
						popupErrorMessage(JSON.stringify(e.json, null, 2))
					}
	      }
			})()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/decentralized_exchange_eos_propose.js
================================================
registerEA(
		"decentralized_exchange_eos_propose",
		"A decentralized exchange plugin to propose for exchanging digital assets via EOS platform(v1.01)",
		[{ // parameters
			name: "proposalName",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "asset",
			value: "eosio.token",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "proposer",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "exchange",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "escrow",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "amount",
			value: 0,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [0, null]
		}, {
			name: "currency",
			value: "SYS",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "memo",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var proposalName = getEAParameter(context, "proposalName")
			var asset = getEAParameter(context, "asset")
			var proposer = getEAParameter(context, "proposer")
			var exchange = getEAParameter(context, "exchange")
			var escrow = getEAParameter(context, "escrow")
			var amount = getEAParameter(context, "amount")
			var currency = getEAParameter(context, "currency")
			var memo = getEAParameter(context, "memo")

			if (proposalName == null || proposalName == "") {
				popupErrorMessage("The proposal name should not be empty.")
				return
			}
			if (proposer == null || proposer == "") {
				popupErrorMessage("The proposer should not be empty.")
				return
			}
			if (exchange == null || exchange == "") {
				popupErrorMessage("The exchange should not be empty.")
				return
			}
			if (escrow == null || escrow == "") {
				popupErrorMessage("The escrow account should not be empty.")
				return
			}
			if (amount <= 0) {
				popupErrorMessage("The amount should be greater than zero.")
				return
			}
			if (memo == null) {
				memo = ""
			}

			const actions = [{
				account: asset,
				name: "transfer",
				authorization: [{
					actor: escrow,
					permission: "active",
				}],
				data: {
					from: escrow,
					to: exchange,
					quantity: Math.floor(amount) + ".0000 " + currency,
					memo: memo
				}
			}];

			(async () => {
				try {
				  const serialized_actions = await window.eos_api.serializeActions(actions)

					const proposeInput = {
						proposer: proposer,
						proposal_name: proposalName,
						// 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.
						requested: [{
							actor: exchange,
							permission: "active"
						}],
						trx: {
							expiration: new Date(new Date().getTime() + 3600000).toISOString().slice(0,19),
							ref_block_num: 0,
							ref_block_prefix: 0,
							max_net_usage_words: 0,
							max_cpu_usage_ms: 0,
							delay_sec: 0,
							context_free_actions: [],
							actions: serialized_actions,
							transaction_extensions: []
						}
					}

					const result = await window.eos_api.transact({
						actions: [{
							account: "eosio.msig",
							name: "propose",
							authorization: [{
								actor: proposer,
								permission: "active"
							}],
							data: proposeInput
						}]
					}, {
						blocksBehind: 3,
						expireSeconds: 30,
						broadcast: true,
						sign: true
					})

					popupMessage("Proposed!\n\n" + JSON.stringify(result, null, 2))
				} catch (e) {
					popupErrorMessage("Caught exception: " + e)

	        if (e instanceof window.eosjs_jsonrpc.RpcError) {
						popupErrorMessage(JSON.stringify(e.json, null, 2))
					}
	      }
			})()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/decentralized_exchange_eos_unapprove.js
================================================
registerEA(
		"decentralized_exchange_eos_unapprove",
		"A decentralized exchange plugin to unapprove a proposal for exchanging digital assets via EOS platform(v1.0)",
		[{ // parameters
			name: "proposalName",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "proposer",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "actor",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var proposalName = getEAParameter(context, "proposalName")
			var proposer = getEAParameter(context, "proposer")
			var actor = getEAParameter(context, "actor")

			if (proposalName == null || proposalName == "") {
				popupErrorMessage("The proposal name should not be empty.")
				return
			}
			if (proposer == null || proposer == "") {
				popupErrorMessage("The proposer should not be empty.")
				return
			}
			if (actor == null || actor == "") {
				popupErrorMessage("The actor should not be empty.")
				return
			}

			(async () => {
				try {
					const result = await window.eos_api.transact({
						actions: [{
							account: "eosio.msig",
							name: "unapprove",
							authorization: [{
								actor: actor,
								permission: "active"
							}],
							data: {
								proposer: proposer,
								proposal_name: proposalName,
								level: {
									actor: actor,
									permission: "active",
								}
							}
						}]
					}, {
						blocksBehind: 3,
						expireSeconds: 30,
						broadcast: true,
						sign: true
					})

					popupMessage("Unapproved!\n\n" + JSON.stringify(result, null, 2))
				} catch (e) {
					popupErrorMessage("Caught exception: " + e)

	        if (e instanceof window.eosjs_jsonrpc.RpcError) {
						popupErrorMessage(JSON.stringify(e.json, null, 2))
					}
	      }
			})()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/payment_gateway_eos.js
================================================
registerEA(
		"payment_gateway_eos",
		"A payment gateway plugin to make you fund(deposit or withdraw) via EOS platform(v1.03)",
		[{ // parameters
			name: "asset",
			value: "eosio.token",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "from",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "to",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "amount",
			value: 0,
			required: true,
			type: PARAMETER_TYPE.INTEGER,
			range: [0, null]
		}, {
			name: "currency",
			value: "SYS",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "memo",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var asset = getEAParameter(context, "asset")
			var from = getEAParameter(context, "from")
			var to = getEAParameter(context, "to")
			var amount = getEAParameter(context, "amount")
			var currency = getEAParameter(context, "currency")
			var memo = getEAParameter(context, "memo")

			if (from == null || from == "") {
				popupErrorMessage("The sender should not be empty.")
				return
			}
			if (to == null || to == "") {
				popupErrorMessage("The recipient should not be empty.")
				return
			}
			if (amount <= 0) {
				popupErrorMessage("The amount should be greater than zero.")
				return
			}
			if (memo == null) {
				memo = ""
			}

	    (async () => {
	      try {
	        const result = await window.eos_api.transact({
	          actions: [{
	              account: asset,
	              name: "transfer",
	              authorization: [{
	                  actor: from,
	                  permission: "active",
	              }],
	              data: {
	                  from: from,
	                  to: to,
	                  quantity: Math.floor(amount) + ".0000 " + currency,
	                  memo: memo
	              }
	          }]
	        }, {
	          blocksBehind: 3,
	          expireSeconds: 30
	        })

	        popupMessage("Transaction pushed!\n\n" + JSON.stringify(result, null, 2))
	      } catch (e) {
					popupErrorMessage("Caught exception: " + e)

	        if (e instanceof window.eosjs_jsonrpc.RpcError) {
						popupErrorMessage(JSON.stringify(e.json, null, 2))
					}
	      }
	    })()
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/payment_gateway_eos_lib_loader.js
================================================
registerEA(
		"payment_gateway_eos_lib_loader",
		"A payment gateway plugin to load EOS libraries(v1.01)",
		[{ // parameters
			name: "privateKey",
			value: "",
			required: false,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "jsonRpcUrl",
			value: "https://nodes.get-scatter.com",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "jssig",
			value: "https://www.fintechee.com/js/eos/eosjs-jssig.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "jsonrpc",
			value: "https://www.fintechee.com/js/eos/eosjs-jsonrpc.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "api",
			value: "https://www.fintechee.com/js/eos/eosjs-api.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var defaultPrivateKey = getEAParameter(context, "privateKey")
			var jsonRpcUrl = getEAParameter(context, "jsonRpcUrl")
			var jssig = getEAParameter(context, "jssig")
			var jsonrpc = getEAParameter(context, "jsonrpc")
			var api = getEAParameter(context, "api")

			if (defaultPrivateKey == null || defaultPrivateKey == "") {
				popupErrorMessage("The private key should not be empty.")
				return
			}

			var tags = document.getElementsByTagName("script")
			for (var i = tags.length - 1; i >= 0; i--) {
				if (tags[i] && tags[i].getAttribute("src") != null && (tags[i].getAttribute("src") == jssig || tags[i].getAttribute("src") == jsonrpc || tags[i].getAttribute("src") == api)) {
					tags[i].parentNode.removeChild(tags[i])
				}
			}

			var script1 = document.createElement("script")
	    document.body.appendChild(script1)
	    script1.onload = function () {
	      var script2 = document.createElement("script")
	      document.body.appendChild(script2)
	      script2.onload = function () {
	        var script3 = document.createElement("script")
	        document.body.appendChild(script3)
	        script3.onload = function () {
						window.eosjs_jsonrpc = eosjs_jsonrpc
						var eos_rpc = new eosjs_jsonrpc.JsonRpc(jsonRpcUrl)
					  var eos_signatureProvider = new eosjs_jssig.JsSignatureProvider([defaultPrivateKey])
					  window.eos_api = new eosjs_api.Api({rpc: eos_rpc, signatureProvider: eos_signatureProvider})
					}
	        script3.onerror = function () {}
	        script3.async = true
	        script3.src = jssig
	      }
	      script2.onerror = function () {}
	      script2.async = true
	      script2.src = jsonrpc
	    }
	    script1.onerror = function () {}
	    script1.async = true
	    script1.src = api
		},
		function (context) { // Deinit()
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/payment_gateway_eos_scatter.js
================================================
registerEA(
		"payment_gateway_eos_scatter",
		"A payment gateway plugin to load the libraries of EOS and Scatter(v1.0)",
		[{ // parameters
			name: "jsonRpcUrl",
			value: "https://nodes.get-scatter.com",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "chainId",
			value: "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "scatterCore",
			value: "https://www.fintechee.com/js/eos/scatterjs-core.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "scatterEos",
			value: "https://www.fintechee.com/js/eos/scatterjs-plugin-eosjs2.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "jsonrpc",
			value: "https://www.fintechee.com/js/eos/eosjs-jsonrpc.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}, {
			name: "api",
			value: "https://www.fintechee.com/js/eos/eosjs-api.min.js",
			required: true,
			type: PARAMETER_TYPE.STRING,
			range: null
		}],
		function (context) { // Init()
			var jsonRpcUrl = getEAParameter(context, "jsonRpcUrl")
			var chainId = getEAParameter(context, "chainId")
			var scatterCore = getEAParameter(context, "scatterCore")
			var scatterEos = getEAParameter(context, "scatterEos")
			var jsonrpc = getEAParameter(context, "jsonrpc")
			var api = getEAParameter(context, "api")

			var tags = document.getElementsByTagName("script")
			for (var i = tags.length - 1; i >= 0; i--) {
				if (tags[i] && tags[i].getAttribute("src") != null &&
					(tags[i].getAttribute("src") == scatterCore || tags[i].getAttribute("src") == scatterEos || tags[i].getAttribute("src") == jsonrpc || tags[i].getAttribute("src") == api)) {

					tags[i].parentNode.removeChild(tags[i])
				}
			}

			var script1 = document.createElement("script")
	    document.body.appendChild(script1)
	    script1.onload = function () {
	      var script2 = document.createElement("script")
	      document.body.appendChild(script2)
	      script2.onload = function () {
	        var script3 = document.createElement("script")
	        document.body.appendChild(script3)
	        script3.onload = function () {
						var script4 = document.createElement("script")
		        document.body.appendChild(script4)
		        script4.onload = function () {
							var parsedJsonRpcUrl = jsonRpcUrl.split("://")
							var parsedJsonRpcUrl2 = parsedJsonRpcUrl[1].split(":")
							const network = ScatterJS.Network.fromJson({
								blockchain: "eos",
								protocol: parsedJsonRpcUrl[0],
								host: parsedJsonRpcUrl2[0],
								port: parsedJsonRpcUrl2.length == 1 ? 443 : parseInt(parsedJsonRpcUrl2[1]),
								chainId: chainId
							})
							ScatterJS.plugins(new ScatterEOS())
							ScatterJS.scatter.connect("www.fintechee.com", {network}).then(function (connected) {
								if(!connected) {
									popupErrorMessage("Failed to connect to your Scatter APP.")
									return false
								}

								const scatter = ScatterJS.scatter

								window.eosjs_jsonrpc = eosjs_jsonrpc
								var eos_rpc = new eosjs_jsonrpc.JsonRpc(jsonRpcUrl)

								window.eos_api = scatter.eos(network, eosjs_api.Api, {rpc: eos_rpc});

								(async function () {
									if (scatter.identity) {
										scatter.logout()
									}

									await scatter.login()
									window.scatter = scatter

									popupMessage("Connected to Scatter successfully!")
								})()
								window.ScatterJS = null
							})
						}
		        script4.onerror = function () {}
		        script4.async = true
		        script4.src = scatterEos
					}
	        script3.onerror = function () {}
	        script3.async = true
	        script3.src = scatterCore
	      }
	      script2.onerror = function () {}
	      script2.async = true
	      script2.src = jsonrpc
	    }
	    script1.onerror = function () {}
	    script1.async = true
	    script1.src = api
		},
		function (context) { // Deinit()
			window.scatter.logout()
			window.scatter = null
		},
		function (context) { // OnTick()
		}
	)


================================================
FILE: EA/Plugin-for-EOS/usage.txt
================================================
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.

Furthermore, it is possible to extend these plugins to support a different blockchain, if needed.



================================================
FILE: EA/Plugin-for-FXCM/README.md
================================================
## Developing. Will be coming soon.


================================================
FILE: EA/Plugin-for-MQL/README.md
================================================
# Expert-Advisor-Cpp-Compiler

This 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.

To 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

![Fintechee C/C++/MQL compiler](https://github.com/fintechee/Expert-Advisor-Cpp-Compiler/blob/main/cpp.png)
![Fintechee C/C++/MQL compiler](https://raw.githubusercontent.com/fintechee/Expert-Advisor-Cpp-Compiler/main/cppcompiler.png)

## Prerequisite
Emscripten is required to compile C/C++/MQL files.
So, you need to install it in advance.
https://emscripten.org/docs/getting_started/downloads.html#installation-instructions

## Usage
1. Installation

Please access this repo: https://github.com/fintechees/Expert-Advisor-Cpp-Compiler

- Download the git repo, and then extract the zip file.
- cd the directory
- npm i

2. Run

- node app.js
- Access https://www.fintechee.com/web-trader/
- Click the "Console" on the menubar(on the left of the page).
- Choose "C/C++" tab on the panel.
- 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.
- Click "Compile Indicator" or "Compile EA" after you finish modifying your original codes.
- 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.

Please access this page to know more details: https://www.fintechee.com/compatible-with-mql/

The tool in the page: https://www.fintechee.com/compatible-with-mql/ is an alternative generator to the "Generate Indicator" or "Generate EA" function.

3. Output files

- The output files(js and WebAssembly) will be stored in the sub-directory: ./static
- you can access ./static via http://127.0.0.1:3000/js/[your_output_js_file_name] (/js refers to ./static)

## Tutorials
The tutorials will be coming soon.

## License

MIT


================================================
FILE: EA/Plugin-for-MQL/mqlea2fintechee.h
================================================
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <climits>
#include <float.h>
#include <unistd.h>
#include <iomanip>
#include <ctime>
#include <cmath>
#include <chrono>
#include <emscripten.h>
using namespace std;

typedef time_t datetime; // Please note that time_t can't handle dates beyond Y2038
typedef int color;

enum ENUM_TIMEFRAMES {
  PERIOD_CURRENT = 0,
  PERIOD_M1 = 1,
  PERIOD_M5 = 5,
  PERIOD_M15 = 15,
  PERIOD_M30 = 30,
  PERIOD_H1 = 60,
  PERIOD_H4 = 240,
  PERIOD_D1 = 1440,
  PERIOD_W1 = 10080,
  PERIOD_MN1 = 43200
};
enum ENUM_APPLIED_PRICE {
  PRICE_CLOSE = 0,
  PRICE_OPEN = 1,
  PRICE_HIGH = 2,
  PRICE_LOW = 3,
  PRICE_MEDIAN = 4,
  PRICE_TYPICAL = 5,
  PRICE_WEIGHTED = 6
};
enum ENUM_MA_METHOD {
  MODE_SMA = 0,
  MODE_EMA = 1,
  MODE_SMMA = 2,
  MODE_LWMA = 3
};
enum ENUM_INIT_RETCODE {
  INIT_SUCCEEDED = 0,
  INIT_FAILED = -1,
  INIT_PARAMETERS_INCORRECT = -1
};

const int OP_BUY = 0;
const int OP_SELL = 1;
const int OP_BUYLIMIT = 2;
const int OP_SELLLIMIT = 3;
const int OP_BUYSTOP = 4;
const int OP_SELLSTOP = 5;

const int MODE_MAIN = 0;
const int MODE_SIGNAL = 1;
const int MODE_PLUSDI = 1;
const int MODE_MINUSDI = 2;
const int MODE_UPPER = 1;
const int MODE_LOWER = 2;
const int MODE_GATORJAW = 1;
const int MODE_GATORTEETH = 2;
const int MODE_GATORLIPS = 3;
const int MODE_TENKANSEN = 1;
const int MODE_KIJUNSEN = 2;
const int MODE_SENKOUSPANA = 3;
const int MODE_SENKOUSPANB = 4;
const int MODE_CHIKOUSPAN = 5;
const int MODE_OPEN = 0;
const int MODE_LOW = 1;
const int MODE_HIGH = 2;
const int MODE_CLOSE = 3;
const int MODE_VOLUME = 4;
const int MODE_TIME = 5;
const int MODE_BID = 9;
const int MODE_ASK = 10;
const int MODE_POINT = 11;
const int MODE_DIGITS = 12;
const int MODE_SPREAD = 13;
const int MODE_SWAPLONG = 18;
const int MODE_SWAPSHORT = 19;
const int MODE_TRADEALLOWED = 22;
const int MODE_MINLOT = 23;
const int MODE_LOTSTEP = 24;
const int MODE_MAXLOT = 25;

// MQL has no these enumerations.
const int INDI_OHLC = 0;
const int INDI_ADX = 1;
const int INDI_ALLIGATOR = 2;
const int INDI_BANDS = 3;
const int INDI_ENVELOPES = 4;
const int INDI_FRACTALS = 5;
const int INDI_ICHIMOKU = 6;
const int INDI_MACD = 7;
const int INDI_RVI = 8;
const int INDI_STOCHASTIC = 9;

// MQL may define different values.
const int SELECT_BY_POS = 1;
const int SELECT_BY_TICKET = 2;
const int MODE_TRADES = 1;
const int MODE_HISTORY = 2;

const int MODE_ASCEND = 1;
const int MODE_DESCEND = 2;

const int TIME_DATE = 4;
const int TIME_MINUTES = 2;
const int TIME_SECONDS = 1;

const int Green = 0;
const int Red = 0;
const int Violet = 0;
const int White = 0;
const int Yellow = 0;
const int Blue = 0;
const int FireBrick = 0;
const int Pink = 0;
const int Lime = 0;

const int EMPTY = -1;
const int EMPTY_VALUE = 0x7FFFFFFF;
const int CLR_NONE = -1;
const int clrNONE = -1;
const int CHARTS_MAX = 100;
const int INVALID_HANDLE = -1;
const int WHOLE_ARRAY = 0;
const int WRONG_VALUE = -1;

enum ENUM_OBJECT {
  OBJ_ARROW_CHECK = 1,
  OBJ_TREND = 2
};

enum ENUM_OBJECT_PROPERTY {
  OBJPROP_TIME1 = 0,
  OBJPROP_PRICE1 = 1,
  OBJPROP_TIME2 = 2,
  OBJPROP_PRICE2 = 3
};

const char* convertTimeFrame (int timeframe) {
  if (PERIOD_M1 == timeframe) {
    return "M1";
  } else if (PERIOD_M5 == timeframe) {
    return "M5";
  } else if (PERIOD_M15 == timeframe) {
    return "M15";
  } else if (PERIOD_M30 == timeframe) {
    return "M30";
  } else if (PERIOD_H1 == timeframe) {
    return "H1";
  } else if (PERIOD_H4 == timeframe) {
    return "H4";
  } else if (PERIOD_D1 == timeframe) {
    return "D";
  } else if (PERIOD_W1 == timeframe) {
    return "W";
  } else if (PERIOD_MN1 == timeframe) {
    return "M";
  } else {
    return "0";
  }
}
const char* convertMode (int mode, int indi) {
  if (MODE_SIGNAL == mode && (indi == INDI_MACD || indi == INDI_RVI || indi == INDI_STOCHASTIC)) {
    return "signal";
  } else if (MODE_PLUSDI == mode && indi == INDI_ADX) {
    return "plusDi";
  } else if (MODE_MINUSDI == mode && indi == INDI_ADX) {
    return "minusDi";
  } else if (MODE_UPPER == mode && (indi == INDI_BANDS || indi == INDI_ENVELOPES)) {
    return "upper";
  } else if (MODE_LOWER == mode && (indi == INDI_BANDS || indi == INDI_ENVELOPES)) {
    return "lower";
  } else if (MODE_UPPER == mode && indi == INDI_FRACTALS) {
    return "fractalsUp";
  } else if (MODE_LOWER == mode && indi == INDI_FRACTALS) {
    return "fractalsDown";
  } else if (MODE_GATORJAW == mode && indi == INDI_ALLIGATOR) {
    return "jaws";
  } else if (MODE_GATORTEETH == mode && indi == INDI_ALLIGATOR) {
    return "teeth";
  } else if (MODE_GATORLIPS == mode && indi == INDI_ALLIGATOR) {
    return "lips";
  } else if (MODE_TENKANSEN == mode && indi == INDI_ICHIMOKU) {
    return "tenkan";
  } else if (MODE_KIJUNSEN == mode && indi == INDI_ICHIMOKU) {
    return "kijun";
  } else if (MODE_SENKOUSPANA == mode && indi == INDI_ICHIMOKU) {
    return "spana";
  } else if (MODE_SENKOUSPANB == mode && indi == INDI_ICHIMOKU) {
    return "spanb";
  } else if (MODE_CHIKOUSPAN == mode && indi == INDI_ICHIMOKU) {
    return "chikou";
  } else if (MODE_OPEN == mode && indi == INDI_OHLC) {
    return "Open";
  } else if (MODE_LOW == mode && indi == INDI_OHLC) {
    return "Low";
  } else if (MODE_HIGH == mode && indi == INDI_OHLC) {
    return "High";
  } else if (MODE_CLOSE == mode && indi == INDI_OHLC) {
    return "Close";
  } else if (MODE_VOLUME == mode && indi == INDI_OHLC) {
    return "Volume";
  } else if (MODE_TIME == mode && indi == INDI_OHLC) {
    return "Time";
  } else {
    return "main";
  }
}
const char* convertMAMethod (int ma_method) {
  if (MODE_EMA == ma_method) {
    return "ema";
  } else if (MODE_SMMA == ma_method) {
    return "smma";
  } else if (MODE_LWMA == ma_method) {
    return "lwma";
  } else {
    return "sma";
  }
}
const char* convertCmd (int cmd) {
  if (OP_BUY == cmd) {
    return "BUY";
  } else if (OP_SELL == cmd) {
    return "SELL";
  } else if (OP_BUYLIMIT == cmd) {
    return "BUY LIMIT";
  } else if (OP_SELLLIMIT == cmd) {
    return "SELL LIMIT";
  } else if (OP_BUYSTOP == cmd) {
    return "BUY STOP";
  } else {
    return "SELL STOP";
  }
}

void (*jPrint) (int, const char*);
long (*jChartClose) (int, long);
long (*jChartID) (int);
long (*jChartOpen) (int, const char*, const char*);
int (*jChartPeriod) (int, long);
const char* (*jChartSymbol) (int, long);
int (*jPeriod) (int);
const char* (*jSymbol) (int);
double (*jAccountBalance) (int);
const char* (*jAccountCompany) (int);
const char* (*jAccountCurrency) (int);
double (*jAccountEquity) (int);
double (*jAccountFreeMargin) (int);
double (*jAccountMargin) (int);
double (*jAccountProfit) (int);
int (*jOrdersTotal) (int);
int (*jOrdersHistoryTotal) (int);
int (*jOrderSelect) (int, int, int, int);
double (*jOrderOpenPrice) (int);
int (*jOrderType) (int);
double (*jOrderTakeProfit) (int);
double (*jOrderStopLoss) (int);
double (*jOrderLots) (int);
double (*jOrderProfit) (int);
const char* (*jOrderSymbol) (int);
int (*jOrderTicket) (int);
int (*jOrderMagicNumber) (int);
datetime (*jOrderOpenTime) (int);
const char* (*jOrderComment) (int);
datetime (*jOrderExpiration) (int);
void (*jOrderPrint) (int);
int (*jiTimeInit) (int, const char*, const char*);
datetime (*jiTime) (int, int, int);
int (*jiOpenInit) (int, const char*, const char*);
double (*jiOpen) (int, int, int);
int (*jiHighInit) (int, const char*, const char*);
double (*jiHigh) (int, int, int);
int (*jiLowInit) (int, const char*, const char*);
double (*jiLow) (int, int, int);
int (*jiCloseInit) (int, const char*, const char*);
double (*jiClose) (int, int, int);
int (*jiVolumeInit) (int, const char*, const char*);
long (*jiVolume) (int, int, int);
int (*jiHighest) (int, int, const char*, int, int);
int (*jiLowest) (int, int, const char*, int, int);
int (*jiACInit) (int, const char*, const char*);
double (*jiAC) (int, int, int);
int (*jiADXInit) (int, const char*, const char*, int, int);
double (*jiADX) (int, int, const char*, int);
int (*jiAlligatorInit) (int, const char*, const char*, int, int, int, int, int, int, const char*, int);
double (*jiAlligator) (int, int, int, int, int, const char*, int);
int (*jiAOInit) (int, const char*, const char*);
double (*jiAO) (int, int, int);
int (*jiATRInit) (int, const char*, const char*, int);
double (*jiATR) (int, int, int);
int (*jiBearsPowerInit) (int, const char*, const char*, int, int);
double (*jiBearsPower) (int, int, int);
int (*jiBandsInit) (int, const char*, const char*, int, double, int, int);
double (*jiBands) (int, int, int, const char*, int);
double (*jiBandsOnArray) (int, double*, int, int, double, int, const char*, int);
int (*jiBullsPowerInit) (int, const char*, const char*, int, int);
double (*jiBullsPower) (int, int, int);
int (*jiCCIInit) (int, const char*, const char*, int, int);
double (*jiCCI) (int, int, int);
double (*jiCCIOnArray) (int, double*, int, int, int);
int (*jiCustomInit) (int, const char*, const char*, const char*, const char*);
double (*jiCustom) (int, int, const char*, int);
int (*jiDeMarkerInit) (int, const char*, const char*, int);
double (*jiDeMarker) (int, int, int);
int (*jiEnvelopesInit) (int, const char*, const char*, int, const char*, int, int, double);
double (*jiEnvelopes) (int, int, int, const char*, int);
double (*jiEnvelopesOnArray) (int, double*, int, int, const char*, int, double, const char*, int);
int (*jiFractalsInit) (int, const char*, const char*);
double (*jiFractals) (int, int, const char*, int);
int (*jiIchimokuInit) (int, const char*, const char*, int, int, int);
double (*jiIchimoku) (int, int, int, const char*, int);
int (*jiMAInit) (int, const char*, const char*, int, int, int, int);
double (*jiMA) (int, int, int, const char*, int);
double (*jiMAOnArray) (int, double*, int, int, int, const char*, int);
int (*jiMACDInit) (int, const char*, const char*, int, int, int, int);
double (*jiMACD) (int, int, const char*, int);
int (*jiMFIInit) (int, const char*, const char*, int);
double (*jiMFI) (int, int, int);
int (*jiMomentumInit) (int, const char*, const char*, int, int);
double (*jiMomentum) (int, int, int);
double (*jiMomentumOnArray) (int, double*, int, int, int);
int (*jiRSIInit) (int, const char*, const char*, int, int);
double (*jiRSI) (int, int, int);
double (*jiRSIOnArray) (int, double*, int, int, int);
int (*jiRVIInit) (int, const char*, const char*, int);
double (*jiRVI) (int, int, const char*, int);
int (*jiSARInit) (int, const char*, const char*, double, double);
double (*jiSAR) (int, int, int);
int (*jiStochasticInit) (int, const char*, const char*, int, int, int, const char*);
double (*jiStochastic) (int, int, const char*, int);
int (*jiWPRInit) (int, const char*, const char*, int);
double (*jiWPR) (int, int, int);
int (*jObjectCreate) (int, long, const char*, int, datetime, double, datetime, double);
int (*jObjectDelete) (int, const char*);
double (*jObjectGet) (int, const char*, int);
int (*jObjectSet) (int, const char*, int, double);
int (*jIsTesting) ();
double (*jMarketInfo) (int, const char*, int);
int (*jCreateNeuralNetwork) (int, const char*, const char*);
double (*jActivateNeuralNetwork) (int, const char*, double*, int);

// Deprecated
EM_JS(bool, jSCompareL, (int uid, const char* str, long l), {
  try {
    var obj = window.mqlEAsBuffer[uid + ""];
    var UTF8ToString = window.mqlEAs[obj.name].module.UTF8ToString;
    var s = UTF8ToString(str);
    return parseInt(s) >= l;
  } catch (e) {
    return false;
  }
});

EM_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), {
   return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      var UTF8ToString = window.mqlEAs[obj.name].module.UTF8ToString;

      var symbolName = UTF8ToString(symbol);
      const orderType = UTF8ToString(cmd);
      const cmmnt = UTF8ToString(comment);
      if (symbolName == "") {
        symbolName = obj.symbolName;
      }
      obj.lock = true;
      document.addEventListener("customevent", function (e) {
        window.mqlEAsBuffer[uid + ""].lock = false;
        wakeUp(parseInt(e.detail));
			}, {once: true});
      sendOrder(obj.brokerName, obj.accountId, symbolName, orderType, price, slippage, volume, takeprofit, stoploss, cmmnt, magic, expiration);
    } catch (e) {
      printErrorMessage(e.message);
      var event = new CustomEvent("customevent", {detail: -1});
  		document.dispatchEvent(event);
    }
  });
});

EM_JS(int, jOrderModify, (int uid, int ticket, double price, double stoploss, double takeprofit, datetime expiration, int arrow_color), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      obj.lock = true;

      var orderOrTrade = getOrderOrTradeById(obj.context, ticket + "");
      var type = orderOrTrade.type;

      if (type == "P") {
        document.addEventListener("customevent", function (e) {
          window.mqlEAsBuffer[uid + ""].lock = false;
          if (e.detail != null) {
            wakeUp(1);
          } else {
            wakeUp(0);
          }
  			}, {once: true});
        modifyOrder(obj.brokerName, obj.accountId, ticket + "", getSymbolName(orderOrTrade), getOrderType(orderOrTrade), price, 0, getLots(orderOrTrade),
          takeprofit, stoploss, getComment(orderOrTrade), getMagicNumber(orderOrTrade), getExpiration(orderOrTrade));
      } else if (type == "T") {
        document.addEventListener("customevent", function (e) {
          window.mqlEAsBuffer[uid + ""].lock = false;
          if (e.detail != null) {
            wakeUp(1);
          } else {
            wakeUp(0);
          }
  			}, {once: true});
        modifyTpSlOfTrade(obj.brokerName, obj.accountId, ticket + "", takeprofit, stoploss);
      } else {
        throw new Error("Failed to modify the order.");
      }
    } catch (e) {
      printErrorMessage(e.message);
      var event = new CustomEvent("customevent", {detail: null});
  		document.dispatchEvent(event);
    }
  });
});

EM_JS(int, jOrderClose, (int uid, int ticket, double lots, double price, int slippage, int arrow_color), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      obj.lock = true;
      document.addEventListener("customevent", function (e) {
        window.mqlEAsBuffer[uid + ""].lock = false;
        if (e.detail != null) {
          wakeUp(1);
        } else {
          wakeUp(0);
        }
			}, {once: true});
      closeTrade(obj.brokerName, obj.accountId, ticket + "", price, slippage);
    } catch (e) {
      printErrorMessage(e.message);
      var event = new CustomEvent("customevent", {detail: null});
  		document.dispatchEvent(event);
    }
  });
});

EM_JS(int, jOrderDelete, (int uid, int ticket, int arrow_color), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      obj.lock = true;
      document.addEventListener("customevent", function (e) {
        window.mqlEAsBuffer[uid + ""].lock = false;
        if (e.detail != null) {
          wakeUp(1);
        } else {
          wakeUp(0);
        }
			}, {once: true});
      cancelOrder(obj.brokerName, obj.accountId, ticket + "");
    } catch (e) {
      printErrorMessage(e.message);
      var event = new CustomEvent("customevent", {detail: null});
  		document.dispatchEvent(event);
    }
  });
});

EM_JS(bool, jVeriSig, (int uid, const char* fintechee_data, const char* fintechee_signature, const char* fintechee_public_key), {
  return Asyncify.handleSleep(function (wakeUp) {
    if (typeof veriSig == "undefined") {
      wakeUp(false);
      return;
    }

    var obj = window.mqlEAsBuffer[uid + ""];
    var UTF8ToString = window.mqlEAs[obj.name].module.UTF8ToString;

    const data = UTF8ToString(fintechee_data);
    const signature = UTF8ToString(fintechee_signature);
    const public_key = UTF8ToString(fintechee_public_key);

    veriSig(true, data, signature, public_key)
    .then(function (res) {
      if (res) {
        wakeUp(res);
      } else {
        printErrorMessage("Signature verification failed.");
        wakeUp(res);
      }
    })
    .catch(function (e) {
      printErrorMessage(e.message);
      wakeUp(false);
    })
  });
});

EM_JS(void, jPreventCleanUp, (int uid), {
  try {
    window.mqlEAsBuffer[uid + ""].bPreventCleanUp = true;
  } catch (e) {
    printErrorMessage(e.message);
  }
});

EM_JS(bool, jBuildCNN, (int uid, const char* name, int inputNum, int hiddenNum), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);
      if (nnName == "") {
        printErrorMessage("Please enter the name of your CNN model.");
        wakeUp(false);
        return;
      }

      if (typeof window.buildCnn == "undefined") {
        printErrorMessage("Please run the plugin to load your CNN model first.");
        wakeUp(false);
      } else {
        window.buildCnn(inputNum, inputNum, hiddenNum, inputNum).then(function (tfModel) {
          obj.neuralNetworks[nnName] = {
            cnn: tfModel
          };
          wakeUp(true);
        })
        .catch(function (e) {
          printErrorMessage(e.message);
          wakeUp(false);
        })
      }
    } catch (e) {
      printErrorMessage(e.message);
      wakeUp(false);
    }
  });
});

EM_JS(bool, jTrainCNN, (int uid, const char* name, double* dataInput, double* dataOutput, long trainingSetNum, int inputNum, long iterations, int batchSize, bool bMonitor), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);
      if (nnName == "") {
        printErrorMessage("Please enter the name of your CNN model.");
        wakeUp(false);
        return;
      }

      if (typeof obj.neuralNetworks[nnName] != "undefined" && typeof obj.neuralNetworks[nnName].cnn != "undefined") {
        if (typeof window.trainCnn == "undefined") {
          printErrorMessage("Please run the plugin to load your CNN model first.");
          wakeUp(false);
        } else {
          var nByteDouble = 8;
          var trainingSetI = new Array(trainingSetNum * inputNum);
          for (var i = 0; i < trainingSetI.length; i++) {
            trainingSetI[i] = window.mqlEAs[obj.name].module.getValue(dataInput + i * nByteDouble, "double");
          }
          var trainingSetO = new Array(trainingSetNum * 2);
          for (var i = 0; i < trainingSetO.length; i++) {
            trainingSetO[i] = window.mqlEAs[obj.name].module.getValue(dataOutput + i * nByteDouble, "double");
          }

          var tensorSet = {
            input: window.tf.tensor3d(trainingSetI, [trainingSetNum, inputNum, 1]),
            output: window.tf.tensor2d(trainingSetO, [trainingSetNum, 2])
          };

          printMessage("Start training!");

          window.trainCnn(obj.neuralNetworks[nnName].cnn, tensorSet, iterations, batchSize, bMonitor).then(function () {
            printMessage("Training is done!");
            wakeUp(true);
          })
          .catch(function (e) {
            printErrorMessage(e.message);
            wakeUp(false);
          })
        }
      } else {
        printErrorMessage("The specific CNN model doesn't exist.");
        wakeUp(false);
      }
    } catch (e) {
      printErrorMessage(e.message);
      wakeUp(false);
    }
  });
});

EM_JS(double, jRunCNN, (int uid, const char* name, double* dataInput, int inputNum), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);
      if (nnName == "") {
        printErrorMessage("Please enter the name of your CNN model.");
        wakeUp(-1);
        return;
      }

      if (typeof obj.neuralNetworks[nnName] != "undefined" && typeof obj.neuralNetworks[nnName].cnn != "undefined") {
        if (typeof window.tf == "undefined") {
          printErrorMessage("Please run the plugin to load your CNN model first.");
          wakeUp(-1);
        } else {
          var nByteDouble = 8;
          var trainingSetI = new Array(inputNum);
          for (var i = 0; i < trainingSetI.length; i++) {
            trainingSetI[i] = window.mqlEAs[obj.name].module.getValue(dataInput + i * nByteDouble, "double");
          }

          wakeUp(window.runCnn(obj.neuralNetworks[nnName].cnn, trainingSetI, inputNum));
        }
      } else {
        printErrorMessage("The specific CNN model doesn't exist.");
        wakeUp(-1);
      }
    } catch (e) {
      printErrorMessage(e.message);
      wakeUp(-1);
    }
  });
});

EM_JS(bool, jSaveCNN, (int uid, const char* name), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);
      if (nnName == "") {
        printErrorMessage("Please enter the name of your CNN model.");
        wakeUp(false);
        return;
      }

      if (typeof obj.neuralNetworks[nnName] != "undefined" && typeof obj.neuralNetworks[nnName].cnn != "undefined") {
        if (typeof window.tf == "undefined") {
          printErrorMessage("Please run the plugin to load your CNN model first.");
          wakeUp(false);
        } else {
          window.saveCnn(obj.neuralNetworks[nnName].cnn, nnName).then(function () {
            wakeUp(true);
          })
          .catch(function (msg) {
            wakeUp(false);
          })
        }
      } else {
        printErrorMessage("The specific CNN model doesn't exist.");
        wakeUp(false);
      }
    } catch (e) {
      printErrorMessage(e.message);
      wakeUp(false);
    }
  });
});

EM_JS(bool, jLoadCNN, (int uid, const char* name), {
  return Asyncify.handleSleep(function (wakeUp) {
    try {
      var obj = window.mqlEAsBuffer[uid + ""];
      var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name);
      if (nnName == "") {
        printErrorMessage("Please enter the name of your CNN model.");
        wakeUp(false);
        return;
      }

      if (typeof window.tf == "undefined") {
        printErrorMessage("Please run the plugin to load your CNN model first.");
        wakeUp(false);
      } else {
        window.loadCnn(nnName).then(function (tfModel) {
          if (typeof tfModel != "undefined") {
            obj.neuralNetworks[nnName] = {
              cnn: tfModel
            };
            wakeUp(true);
          } else {
            printErrorMessage("The specific CNN model doesn't exist.");
            wakeUp(false);
          }
        })
        .catch(function (msg) {
          wakeUp(false);
        })
      }
    } catch (e) {
      printErrorMessage(e.message);
      wakeUp(false);
    }
  });
});

void Sleep (int milliseconds) {
  sleep(milliseconds / 1000);
}
int GetLastError () {
  return 0;
}
string ErrorDescription (int code) {
  return "";
}
bool IsStopped () {
  return false;
}
bool IsTradeAllowed () {
  return true;
}
bool IsTradeAllowed (const string symbol, datetime tested_time) {
  return true;
}
bool RefreshRates () {
  return true;
}
double MathAbs (double val) {
  return abs(val);
}
double MathArccos (double val) {
  return acos(val);
}
double MathArcsin (double val) {
  return asin(val);
}
double MathArctan (double val) {
  return atan(val);
}
double MathCeil (double val) {
  return ceil(val);
}
double MathCos (double val) {
  return cos(val);
}
double MathExp (double val) {
  return exp(val);
}
double MathFloor (double val) {
  return floor(val);
}
double MathLog (double val) {
  return log(val);
}
double MathLog10 (double val) {
  return log10(val);
}
double MathMax (double a, double b) {
  return max(a, b);
}
double MathMin (double a, double b) {
  return min(a, b);
}
double MathMod (double a, double b) {
  return fmod(a, b);
}
double MathPow (double base, double exponent) {
  return pow(base, exponent);
}
int MathRand () {
  return rand();
}
double MathRound (double val) {
  return round(val);
}
double MathSin (double val) {
  return sin(val);
}
double MathSqrt (double val) {
  return sqrt(val);
}
void MathSrand (int seed) {
  srand(seed);
}
double MathTan (double val) {
  return tan(val);
}
int StringLen (const string string_value) {
  return string_value.length();
}
int StringReplace (string str, const string find, const string replacement) {
  if(find.empty()) {
    return 0;
  }
  size_t start_pos = 0;
  int count = 0;
  while((start_pos = str.find(find, start_pos)) != string::npos) {
    str.replace(start_pos, find.length(), replacement);
    start_pos += replacement.length();
    count++;
  }
  return count;
}
string StringSubstr (const string string_value, int start_pos, int length) {
  if (start_pos < 0 || start_pos >= string_value.length() || length <= 0 || start_pos + length > string_value.length()) {
    return "";
  }
  return string_value.substr(start_pos, length);
}
bool StringToLower (string string_var) {
  transform(string_var.begin(), string_var.end(), string_var.begin(), [](unsigned char c){ return tolower(c);});
  return true;
}
bool StringToUpper (string string_var) {
  transform(string_var.begin(), string_var.end(), string_var.begin(), [](unsigned char c){ return toupper(c);});
  return true;
}
string StringTrimLeft(const string text) {
  string s = text;
  s.erase(s.begin(), find_if(s.begin(), s.end(), [](int c) {return !isspace(c);}));
  return s;
}
string StringTrimRight(const string text) {
  string s = text;
  s.erase(find_if(s.rbegin(), s.rend(), [](int c) {return !isspace(c);}).base(), s.end());
  return s;
}
string DoubleToString (double value, int dijits) {
  stringstream stream;
  stream << fixed << setprecision(dijits) << value;
  return stream.str();
}
string DoubleToString (double value) {
  return DoubleToString(value, 8);
}
string DoubleToStr (double value, int dijits) {
  return DoubleToString(value, dijits);
}
string DoubleToStr (double value) {
  return DoubleToString(value, 8);
}
string IntegerToString (long number, int str_len, unsigned short fill_symbol) {
  return to_string(number);
}
string ShortToString (unsigned short symbol_code) {
  return to_string(symbol_code);
}
string TimeToString (datetime value, int mode) {
  time_t tim = value;
  tm * ptm = localtime(&tim);
  if (mode == 7 || mode == 5) {
    char buffer[20];
    strftime(buffer, 20, "%Y.%m.%d %H:%M:%S", ptm);
    return string(buffer);
  } else if (mode == 4) {
    char buffer[11];
    strftime(buffer, 11, "%Y.%m.%d", ptm);
    return string(buffer);
  } else if (mode == 3 || mode == 1) {
    char buffer[9];
    strftime(buffer, 9, "%H:%M:%S", ptm);
    return string(buffer);
  } else if (mode == 2) {
    char buffer[6];
    strftime(buffer, 6, "%H:%M", ptm);
    return string(buffer);
  } else {
    char buffer[17];
    strftime(buffer, 17, "%Y.%m.%d %H:%M", ptm);
    return string(buffer);
  }
}
string TimeToString (datetime value) {
  return TimeToString(value, 5);
}
string TimeToStr (datetime value, int mode) {
  return TimeToString(value, mode);
}
string TimeToStr (datetime value) {
  return TimeToString(value, 5);
}
double NormalizeDouble (double value, int digits) {
  return (round(value * pow(10, digits))) / pow(10, digits);
}
double StringToDouble (const string value) {
  return stod(value);
}
double StrToDouble (const string value) {
  return StringToDouble(value);
}
int StringToInteger (const string value) {
  return stoi(value);
}
int StrToInteger (const string value) {
  return StringToInteger(value);
}
datetime StringToTime (const string value) {
  struct tm tm;
  if (value.length() == 19) {
    strptime(value.c_str(), "%Y.%m.%d %H:%M:%S", &tm);
    return mktime(&tm);
  } else if (value.length() == 10) {
    strptime(value.c_str(), "%Y.%m.%d", &tm);
    return mktime(&tm);
  } else if (value.length() == 16) {
    strptime(value.c_str(), "%Y.%m.%d %H:%M", &tm);
    return mktime(&tm);
  } else {
    return 0;
  }
}
datetime StrToTime (const string value) {
  return StringToTime(value);
}
int StringCompare (const string str1, const string str2, bool case_sensitive = true) {
  if (case_sensitive) {
    return strcmp(str1.c_str(), str2.c_str());
  } else {
    return strcasecmp(str1.c_str(), str2.c_str());
  }
}
datetime TimeCurrent () {
  return chrono::system_clock::to_time_t(chrono::system_clock::now());
}
datetime TimeGMT () {
  return TimeCurrent();
}
datetime CurTime () {
  return TimeCurrent();
}
int Day () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_mday;
}
int DayOfWeek () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_wday;
}
int DayOfYear () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_yday + 1;
}
int Hour () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_hour;
}
int Minute () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_min;
}
int Month () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_mon + 1;
}
int Seconds () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_sec;
}
int TimeDay (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_mday;
}
int TimeDayOfWeek (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_wday;
}
int TimeDayOfYear (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_yday + 1;
}
int TimeHour (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_hour;
}
int TimeMinute (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_min;
}
int TimeMonth (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_mon + 1;
}
int TimeSeconds (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_sec;
}
int TimeYear (datetime ltime) {
  time_t theTime = ltime;
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_year + 1900;
}
int Year () {
  time_t theTime = time(NULL);
  struct tm *aTime = localtime(&theTime);
  return aTime->tm_year + 1900;
}
int ArrayCopy (char* dst_array, const char* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (char)));
    return count;
  }
}
int ArrayCopy (short* dst_array, const short* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (short)));
    return count;
  }
}
int ArrayCopy (int* dst_array, const int* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (int)));
    return count;
  }
}
int ArrayCopy (long* dst_array, const long* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (long)));
    return count;
  }
}
int ArrayCopy (float* dst_array, const float* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (float)));
    return count;
  }
}
int ArrayCopy (double* dst_array, const double* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (double)));
    return count;
  }
}
int ArrayCopy (bool* dst_array, const bool* src_array, int dst_start, int src_start, int count) {
  if (count <= 0) {
    return 0;
  } else {
    memcpy(dst_array, src_array, count * (sizeof (bool)));
    return count;
  }
}
void ArrayFree (void* array) {
  free(array);
}
void ArrayInitialize (char* array, char value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayInitialize (short* array, short value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayInitialize (int* array, int value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayInitialize (long* array, long value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayInitialize (float* array, float value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayInitialize (double* array, double value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayInitialize (bool* array, bool value, int count) {
  if (count > 0) {
    for (int i = 0; i < count; i++) {
      array[i] = value;
    }
  }
}
void ArrayFill (char* array, int start, int count, char value) {
  ArrayInitialize(array, value, count);
}
void ArrayFill (short* array, int start, int count, short value) {
  ArrayInitialize(array, value, count);
}
void ArrayFill (int* array, int start, int count, int value) {
  ArrayInitialize(array, value, count);
}
void ArrayFill (long* array, int start, int count, long value) {
  ArrayInitialize(array, value, count);
}
void ArrayFill (float* array, int start, int count, float value) {
  ArrayInitialize(array, value, count);
}
void ArrayFill (double* array, int start, int count, double value) {
  ArrayInitialize(array, value, count);
}
void ArrayFill (bool* array, int start, int count, bool value) {
  ArrayInitialize(array, value, count);
}
int ArrayMaximum (const short* array, int count, int start) {
  if (count > 0) {
    short high = SHRT_MIN;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] > high) {
        high = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMaximum (const int* array, int count, int start) {
  if (count > 0) {
    int high = INT_MIN;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] > high) {
        high = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMaximum (const long* array, int count, int start) {
  if (count > 0) {
    long high = LONG_MIN;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] > high) {
        high = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMaximum (const float* array, int count, int start) {
  if (count > 0) {
    float high = FLT_MIN;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] > high) {
        high = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMaximum (const double* array, int count, int start) {
  if (count > 0) {
    double high = DBL_MIN;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] > high) {
        high = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMinimum (const short* array, int count, int start) {
  if (count > 0) {
    short low = SHRT_MAX;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] < low) {
        low = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMinimum (const int* array, int count, int start) {
  if (count > 0) {
    int low = INT_MAX;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] < low) {
        low = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMinimum (const long* array, int count, int start) {
  if (count > 0) {
    long low = LONG_MAX;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] < low) {
        low = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMinimum (const float* array, int count, int start) {
  if (count > 0) {
    float low = FLT_MAX;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] < low) {
        low = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayMinimum (const double* array, int count, int start) {
  if (count > 0) {
    double low = DBL_MAX;
    int index = -1;
    for (int i = 0; i < count; i++) {
      if (array[i] < low) {
        low = array[i];
        index = i;
      }
    }
    return index;
  } else {
    return -1;
  }
}
int ArrayResize (char** array, int new_size, int reserve_size) {
  if (new_size > 0) {
    int size = new_size * (sizeof (char));
    char* newArr = (char*)malloc(size);
    if (*array != NULL) {
      memcpy(newArr, *array, size);
      free(*array);
    }
    *array = newArr;
    return new_size;
  } else {
    return -1;
  }
}
int ArrayResize (short** array, int new_size, int reserve_size) {
  if (new_size > 0) {
    int size = new_size * (sizeof (short));
    short* newArr = (short*)malloc(size);
    if (*array != NULL) {
      memcpy(newArr, *array, size);
      free(*array);
    }
    *array = newArr;
    return new_size;
  } else {
    return -1;
  }
}
int ArrayResize (int** array, int new_size, int reserve_size) {
  if (new_size > 0) {
    int size = new_size * (sizeof (int));
    int* newArr = (int*)malloc(size);
    if (*array != NULL) {
      memcpy(newArr, *array, size);
      free(*array);
    }
    *array = newArr;
    return new_size;
  } el
Download .txt
gitextract_dqvm1vq7/

├── AI/
│   ├── aitrader_12_eurusd.json
│   ├── aitrader_12_gbpusd.json
│   └── readme.md
├── EA/
│   ├── Arbitrage/
│   │   ├── README.md
│   │   ├── fintechee_external_arbitrage.js
│   │   ├── guide_for_fintechee_external_arbitrage.txt
│   │   └── sample_trading_arbitrage.js
│   ├── Built-in/
│   │   ├── README.md
│   │   ├── sample_using_rsi.js
│   │   └── sample_using_sma.js
│   ├── Chaos/
│   │   ├── chaos.js
│   │   └── intro.txt
│   ├── CopyTrading/
│   │   ├── README.md
│   │   ├── copy_trading_for_oanda.js
│   │   ├── copy_trading_for_oanda_guide.txt
│   │   ├── copy_trading_locally.js
│   │   └── copy_trading_locally_guide.txt
│   ├── Martingale/
│   │   ├── improved_martingale.js
│   │   ├── improved_martingale.txt
│   │   └── sample_martingale.js
│   ├── NeuralNetwork/
│   │   ├── nn_example.js
│   │   ├── sample_run_neuron_model.js
│   │   ├── sample_training_neuron_model.js
│   │   └── usage.txt
│   ├── Oldie/
│   │   ├── README.md
│   │   ├── README.txt
│   │   └── fixapi_oanda_arbitrage.js
│   ├── Plugin-for-Deribit/
│   │   ├── plugin_for_deribit.js
│   │   └── usage.txt
│   ├── Plugin-for-EOS/
│   │   ├── decentralized_exchange_eos_approve.js
│   │   ├── decentralized_exchange_eos_cancel.js
│   │   ├── decentralized_exchange_eos_exec.js
│   │   ├── decentralized_exchange_eos_propose.js
│   │   ├── decentralized_exchange_eos_unapprove.js
│   │   ├── payment_gateway_eos.js
│   │   ├── payment_gateway_eos_lib_loader.js
│   │   ├── payment_gateway_eos_scatter.js
│   │   └── usage.txt
│   ├── Plugin-for-FXCM/
│   │   └── README.md
│   ├── Plugin-for-MQL/
│   │   ├── README.md
│   │   ├── mqlea2fintechee.h
│   │   ├── mqlindi2fintechee.h
│   │   ├── plugin_for_mql.js
│   │   ├── runtestcnn.cpp
│   │   ├── testcnn.cpp
│   │   ├── testverisig.cpp
│   │   └── usage.txt
│   ├── Plugin-for-Oanda/
│   │   ├── plugin_for_oanda.js
│   │   └── usage.txt
│   ├── Plugin-for-SNS/
│   │   ├── plugin_for_sns.js
│   │   └── usage.txt
│   ├── Plugin-for-SNS-with-OpenAI/
│   │   ├── plugin_for_sns_with_openai.js
│   │   └── usage.txt
│   ├── Plugin-for-Tensorflow/
│   │   ├── import_export_model.js
│   │   ├── plugin_to_load_tensorflow.js
│   │   ├── sample_running_cnn_model.js
│   │   ├── sample_training_cnn_model.js
│   │   ├── test_loading_tensorflow.js
│   │   ├── test_xor_powered_by_tensorflow.js
│   │   └── usage.txt
│   ├── Plugin-for-TradingView/
│   │   └── plugin_for_tradingview.js
│   ├── Plugin-for-TrailingStop/
│   │   └── plugin_for_trailingstop.js
│   ├── Plugin-for-XCoinCH/
│   │   ├── market_maker_bot.js
│   │   └── usage.txt
│   ├── PriceAction/
│   │   └── price_action.js
│   ├── Sample-for-Workflow/
│   │   ├── callee.js
│   │   └── caller.js
│   ├── Tips/
│   │   ├── about_API_getData.txt
│   │   └── how_to_rename.txt
│   └── Utility/
│       ├── historical_data_cleaner.js
│       ├── historical_data_viewer.js
│       └── usage.txt
├── Indicators/
│   ├── Built-in/
│   │   ├── README.md
│   │   ├── ac.js
│   │   ├── adx.js
│   │   ├── alligator.js
│   │   ├── ao.js
│   │   ├── atr.js
│   │   ├── bands.js
│   │   ├── bears.js
│   │   ├── bidask.js
│   │   ├── bulls.js
│   │   ├── cci.js
│   │   ├── common.js
│   │   ├── demarker.js
│   │   ├── ema.js
│   │   ├── envelopes.js
│   │   ├── fractals.js
│   │   ├── heikin-ashi.js
│   │   ├── ichimoku.js
│   │   ├── lwma.js
│   │   ├── macd.js
│   │   ├── mfi.js
│   │   ├── momentum.js
│   │   ├── rsi.js
│   │   ├── rvi.js
│   │   ├── sar.js
│   │   ├── sma.js
│   │   ├── smma.js
│   │   ├── stochastic.js
│   │   ├── volume.js
│   │   ├── wpr.js
│   │   └── zigzag.js
│   ├── Oldie/
│   │   ├── README.md
│   │   ├── README.txt
│   │   ├── fintechee_oanda_loader.js
│   │   └── line_segment_sample.js
│   ├── Plugin-for-Data-API/
│   │   ├── crypto_loader.js
│   │   └── usage.txt
│   ├── Plugin-for-Youtube/
│   │   ├── tutorial_videos.js
│   │   └── usage.txt
│   ├── atr_comparison/
│   │   ├── README.md
│   │   ├── atr_comparison.js
│   │   ├── atr_comparison_guide.txt
│   │   └── atr_exporter.js
│   ├── barrage/
│   │   └── barrage.js
│   ├── chart_elements/
│   │   ├── README.md
│   │   ├── chart_elements.js
│   │   ├── chart_elements_intro.txt
│   │   ├── toggle_signals_intro.txt
│   │   └── toggle_trading_signals.js
│   ├── cursor/
│   │   ├── cursor.js
│   │   └── usage.txt
│   ├── extra_fractals/
│   │   ├── README.md
│   │   ├── extra_fractals.js
│   │   └── usage.txt
│   ├── extra_mfi/
│   │   ├── extra_mfi.js
│   │   └── extra_mfi_guide.txt
│   ├── extra_sar/
│   │   └── extra_sar.js
│   ├── fibonacci_retracements/
│   │   ├── README.md
│   │   ├── fibonacci_retracements.js
│   │   └── usage.txt
│   ├── order_buttons/
│   │   ├── README.md
│   │   └── order_buttons.js
│   └── unrealized_pl_and_equity_curve/
│       ├── equity_curve.js
│       ├── equity_curve_viewer.js
│       ├── how_to_use_equity_curve_unrealized_pl.txt
│       ├── unrealized_pl.js
│       └── unrealized_pl_viewer.js
├── LICENSE
├── README.md
├── screenshot/
│   └── README.md
└── simple_manual.txt
Download .txt
SYMBOL INDEX (662 symbols across 8 files)

FILE: EA/Plugin-for-Deribit/plugin_for_deribit.js
  function convertOptionName (line 19) | function convertOptionName (rawName) {
  function parseOrderBook (line 66) | function parseOrderBook (data) {
  function showOptions (line 135) | function showOptions (expirations) {
  function checkHb (line 158) | function checkHb () {
  function showOrderBook (line 168) | function showOrderBook (optionName, orderBookData) {
  function initCryptoOptionsWS (line 195) | function initCryptoOptionsWS () {
  function disconnectCryptoOptionsWS (line 291) | function disconnectCryptoOptionsWS () {
  function getOrderBook (line 310) | function getOrderBook (currency) {
  function subscribeIt (line 337) | function subscribeIt (instrument) {
  function unsubscribeIt (line 356) | function unsubscribeIt (instrument) {

FILE: EA/Plugin-for-MQL/mqlea2fintechee.h
  type time_t (line 19) | typedef time_t datetime;
  type color (line 20) | typedef int color;
  type ENUM_TIMEFRAMES (line 22) | enum ENUM_TIMEFRAMES {
  type ENUM_APPLIED_PRICE (line 34) | enum ENUM_APPLIED_PRICE {
  type ENUM_MA_METHOD (line 43) | enum ENUM_MA_METHOD {
  type ENUM_INIT_RETCODE (line 49) | enum ENUM_INIT_RETCODE {
  type ENUM_OBJECT (line 138) | enum ENUM_OBJECT {
  type ENUM_OBJECT_PROPERTY (line 143) | enum ENUM_OBJECT_PROPERTY {
  function catch (line 360) | catch (e) {
  function catch (line 383) | catch (e) {
  function catch (line 424) | catch (e) {
  function catch (line 446) | catch (e) {
  function catch (line 468) | catch (e) {
  function catch (line 509) | catch (e) {
  function catch (line 540) | catch (e) {
  function catch (line 593) | catch (e) {
  function catch (line 628) | catch (e) {
  function catch (line 662) | catch (e) {
  function catch (line 699) | catch (e) {
  function Sleep (line 706) | void Sleep (int milliseconds) {
  function GetLastError (line 709) | int GetLastError () {
  function string (line 712) | string ErrorDescription (int code) {
  function IsStopped (line 715) | bool IsStopped () {
  function IsTradeAllowed (line 718) | bool IsTradeAllowed () {
  function IsTradeAllowed (line 721) | bool IsTradeAllowed (const string symbol, datetime tested_time) {
  function RefreshRates (line 724) | bool RefreshRates () {
  function MathAbs (line 727) | double MathAbs (double val) {
  function MathArccos (line 730) | double MathArccos (double val) {
  function MathArcsin (line 733) | double MathArcsin (double val) {
  function MathArctan (line 736) | double MathArctan (double val) {
  function MathCeil (line 739) | double MathCeil (double val) {
  function MathCos (line 742) | double MathCos (double val) {
  function MathExp (line 745) | double MathExp (double val) {
  function MathFloor (line 748) | double MathFloor (double val) {
  function MathLog (line 751) | double MathLog (double val) {
  function MathLog10 (line 754) | double MathLog10 (double val) {
  function MathMax (line 757) | double MathMax (double a, double b) {
  function MathMin (line 760) | double MathMin (double a, double b) {
  function MathMod (line 763) | double MathMod (double a, double b) {
  function MathPow (line 766) | double MathPow (double base, double exponent) {
  function MathRand (line 769) | int MathRand () {
  function MathRound (line 772) | double MathRound (double val) {
  function MathSin (line 775) | double MathSin (double val) {
  function MathSqrt (line 778) | double MathSqrt (double val) {
  function MathSrand (line 781) | void MathSrand (int seed) {
  function MathTan (line 784) | double MathTan (double val) {
  function StringLen (line 787) | int StringLen (const string string_value) {
  function StringReplace (line 790) | int StringReplace (string str, const string find, const string replaceme...
  function string (line 803) | string StringSubstr (const string string_value, int start_pos, int lengt...
  function StringToLower (line 809) | bool StringToLower (string string_var) {
  function StringToUpper (line 813) | bool StringToUpper (string string_var) {
  function string (line 817) | string StringTrimLeft(const string text) {
  function string (line 822) | string StringTrimRight(const string text) {
  function string (line 827) | string DoubleToString (double value, int dijits) {
  function string (line 832) | string DoubleToString (double value) {
  function string (line 835) | string DoubleToStr (double value, int dijits) {
  function string (line 838) | string DoubleToStr (double value) {
  function string (line 841) | string IntegerToString (long number, int str_len, unsigned short fill_sy...
  function string (line 844) | string ShortToString (unsigned short symbol_code) {
  function string (line 847) | string TimeToString (datetime value, int mode) {
  function string (line 872) | string TimeToString (datetime value) {
  function string (line 875) | string TimeToStr (datetime value, int mode) {
  function string (line 878) | string TimeToStr (datetime value) {
  function NormalizeDouble (line 881) | double NormalizeDouble (double value, int digits) {
  function StringToDouble (line 884) | double StringToDouble (const string value) {
  function StrToDouble (line 887) | double StrToDouble (const string value) {
  function StringToInteger (line 890) | int StringToInteger (const string value) {
  function StrToInteger (line 893) | int StrToInteger (const string value) {
  function datetime (line 896) | datetime StringToTime (const string value) {
  function datetime (line 911) | datetime StrToTime (const string value) {
  function datetime (line 921) | datetime TimeCurrent () {
  function datetime (line 924) | datetime TimeGMT () {
  function datetime (line 927) | datetime CurTime () {
  function Day (line 930) | int Day () {
  function DayOfWeek (line 935) | int DayOfWeek () {
  function DayOfYear (line 940) | int DayOfYear () {
  function Hour (line 945) | int Hour () {
  function Minute (line 950) | int Minute () {
  function Month (line 955) | int Month () {
  function Seconds (line 960) | int Seconds () {
  function TimeDay (line 965) | int TimeDay (datetime ltime) {
  function TimeDayOfWeek (line 970) | int TimeDayOfWeek (datetime ltime) {
  function TimeDayOfYear (line 975) | int TimeDayOfYear (datetime ltime) {
  function TimeHour (line 980) | int TimeHour (datetime ltime) {
  function TimeMinute (line 985) | int TimeMinute (datetime ltime) {
  function TimeMonth (line 990) | int TimeMonth (datetime ltime) {
  function TimeSeconds (line 995) | int TimeSeconds (datetime ltime) {
  function TimeYear (line 1000) | int TimeYear (datetime ltime) {
  function Year (line 1005) | int Year () {
  function ArrayCopy (line 1010) | int ArrayCopy (char* dst_array, const char* src_array, int dst_start, in...
  function ArrayCopy (line 1018) | int ArrayCopy (short* dst_array, const short* src_array, int dst_start, ...
  function ArrayCopy (line 1026) | int ArrayCopy (int* dst_array, const int* src_array, int dst_start, int ...
  function ArrayCopy (line 1034) | int ArrayCopy (long* dst_array, const long* src_array, int dst_start, in...
  function ArrayCopy (line 1042) | int ArrayCopy (float* dst_array, const float* src_array, int dst_start, ...
  function ArrayCopy (line 1050) | int ArrayCopy (double* dst_array, const double* src_array, int dst_start...
  function ArrayCopy (line 1058) | int ArrayCopy (bool* dst_array, const bool* src_array, int dst_start, in...
  function ArrayFree (line 1066) | void ArrayFree (void* array) {
  function ArrayInitialize (line 1069) | void ArrayInitialize (char* array, char value, int count) {
  function ArrayInitialize (line 1076) | void ArrayInitialize (short* array, short value, int count) {
  function ArrayInitialize (line 1083) | void ArrayInitialize (int* array, int value, int count) {
  function ArrayInitialize (line 1090) | void ArrayInitialize (long* array, long value, int count) {
  function ArrayInitialize (line 1097) | void ArrayInitialize (float* array, float value, int count) {
  function ArrayInitialize (line 1104) | void ArrayInitialize (double* array, double value, int count) {
  function ArrayInitialize (line 1111) | void ArrayInitialize (bool* array, bool value, int count) {
  function ArrayFill (line 1118) | void ArrayFill (char* array, int start, int count, char value) {
  function ArrayFill (line 1121) | void ArrayFill (short* array, int start, int count, short value) {
  function ArrayFill (line 1124) | void ArrayFill (int* array, int start, int count, int value) {
  function ArrayFill (line 1127) | void ArrayFill (long* array, int start, int count, long value) {
  function ArrayFill (line 1130) | void ArrayFill (float* array, int start, int count, float value) {
  function ArrayFill (line 1133) | void ArrayFill (double* array, int start, int count, double value) {
  function ArrayFill (line 1136) | void ArrayFill (bool* array, int start, int count, bool value) {
  function ArrayMaximum (line 1139) | int ArrayMaximum (const short* array, int count, int start) {
  function ArrayMaximum (line 1154) | int ArrayMaximum (const int* array, int count, int start) {
  function ArrayMaximum (line 1169) | int ArrayMaximum (const long* array, int count, int start) {
  function ArrayMaximum (line 1184) | int ArrayMaximum (const float* array, int count, int start) {
  function ArrayMaximum (line 1199) | int ArrayMaximum (const double* array, int count, int start) {
  function ArrayMinimum (line 1214) | int ArrayMinimum (const short* array, int count, int start) {
  function ArrayMinimum (line 1229) | int ArrayMinimum (const int* array, int count, int start) {
  function ArrayMinimum (line 1244) | int ArrayMinimum (const long* array, int count, int start) {
  function ArrayMinimum (line 1259) | int ArrayMinimum (const float* array, int count, int start) {
  function ArrayMinimum (line 1274) | int ArrayMinimum (const double* array, int count, int start) {
  function ArrayResize (line 1289) | int ArrayResize (char** array, int new_size, int reserve_size) {
  function ArrayResize (line 1303) | int ArrayResize (short** array, int new_size, int reserve_size) {
  function ArrayResize (line 1317) | int ArrayResize (int** array, int new_size, int reserve_size) {
  function ArrayResize (line 1331) | int ArrayResize (long** array, int new_size, int reserve_size) {
  function ArrayResize (line 1345) | int ArrayResize (float** array, int new_size, int reserve_size) {
  function ArrayResize (line 1359) | int ArrayResize (double** array, int new_size, int reserve_size) {
  function ArrayResize (line 1373) | int ArrayResize (bool** array, int new_size, int reserve_size) {
  function ArrayResize (line 1387) | int ArrayResize (char** array, int new_size) {
  function ArrayResize (line 1390) | int ArrayResize (short** array, int new_size) {
  function ArrayResize (line 1393) | int ArrayResize (int** array, int new_size) {
  function ArrayResize (line 1396) | int ArrayResize (long** array, int new_size) {
  function ArrayResize (line 1399) | int ArrayResize (float** array, int new_size) {
  function ArrayResize (line 1402) | int ArrayResize (double** array, int new_size) {
  function ArrayResize (line 1405) | int ArrayResize (bool** array, int new_size) {
  function ArraySort (line 1408) | bool ArraySort (char* array, int count, int start, int direction) {
  function ArraySort (line 1420) | bool ArraySort (short* array, int count, int start, int direction) {
  function ArraySort (line 1432) | bool ArraySort (int* array, int count, int start, int direction) {
  function ArraySort (line 1444) | bool ArraySort (long* array, int count, int start, int direction) {
  function ArraySort (line 1456) | bool ArraySort (float* array, int count, int start, int direction) {
  function ArraySort (line 1468) | bool ArraySort (double* array, int count, int start, int direction) {
  function ArrayBsearch (line 1480) | int ArrayBsearch (const char* array, char value, int count, int start, i...
  function ArrayBsearch (line 1501) | int ArrayBsearch (const short* array, short value, int count, int start,...
  function ArrayBsearch (line 1522) | int ArrayBsearch (const int* array, int value, int count, int start, int...
  function ArrayBsearch (line 1543) | int ArrayBsearch (const long* array, long value, int count, int start, i...
  function ArrayBsearch (line 1564) | int ArrayBsearch (const float* array, float value, int count, int start,...
  function ArrayBsearch (line 1585) | int ArrayBsearch (const double* array, double value, int count, int star...
  type Parameter (line 1607) | struct Parameter {
  type GlobalVar (line 1615) | struct GlobalVar {
  type ParamHandleItem (line 1620) | struct ParamHandleItem {
  function setParam (line 1641) | void setParam (int uid, const struct Parameter & parameter) {
  function datetime (line 1651) | datetime setGlobalVar (int uid, const string name, double value) {
  function checkGlobalVar (line 1667) | bool checkGlobalVar (int uid, const string name) {
  function getGlobalVar (line 1675) | double getGlobalVar (int uid, const string name) {
  function delGlobalVar (line 1683) | bool delGlobalVar (int uid, const string name) {
  function EMSCRIPTEN_KEEPALIVE (line 1698) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1705) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1712) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1719) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1726) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1730) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1734) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1738) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1742) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1746) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1750) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1754) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1758) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1762) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1766) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1770) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1774) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1778) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1782) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1786) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1790) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1794) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1798) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1802) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1806) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1810) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1814) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1818) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1822) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1826) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1830) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1834) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1838) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1842) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1846) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1850) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1854) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1858) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1862) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1866) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1870) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1874) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1878) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1882) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1886) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1890) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1894) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1898) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1902) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1906) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1910) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1914) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1918) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1922) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1926) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1930) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1934) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1938) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1942) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1946) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1950) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1954) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1958) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1962) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1966) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1970) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1974) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1978) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1982) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1986) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1990) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1994) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1998) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2002) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2006) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2010) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2014) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2018) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2022) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2026) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2030) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2034) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2038) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2042) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2046) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2050) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2054) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2058) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2062) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2066) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2070) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2074) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2078) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2082) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2086) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2090) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2094) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2098) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2102) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2106) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2110) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2114) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2118) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2122) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2126) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2130) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2134) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2138) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 2142) | EMSCRIPTEN_KEEPALIVE
  function ChartClose (line 2149) | bool ChartClose (long chart_id) {
  function iDeMarker (line 2679) | double iDeMarker (const string symbol, int timeframe, int period, int sh...
  function iDeMarker (line 2690) | double iDeMarker (long symbol, int timeframe, int period, int shift) {
  function iEnvelopes (line 2694) | double iEnvelopes (const string symbol, int timeframe, int ma_period, in...
  function iEnvelopes (line 2705) | double iEnvelopes (long symbol, int timeframe, int ma_period, int ma_met...
  function iEnvelopesOnArray (line 2708) | double iEnvelopesOnArray (double* array, int total, int ma_period, int m...
  function iFractals (line 2713) | double iFractals (const string symbol, int timeframe, int mode, int shif...
  function iFractals (line 2724) | double iFractals (long symbol, int timeframe, int mode, int shift) {
  function iIchimoku (line 2728) | double iIchimoku (const string symbol, int timeframe, int tenkan_sen, in...
  function iIchimoku (line 2749) | double iIchimoku (long symbol, int timeframe, int tenkan_sen, int kijun_...
  function iMA (line 2753) | double iMA (const string symbol, int timeframe, int ma_period, int ma_sh...
  function iMA (line 2764) | double iMA (long symbol, int timeframe, int ma_period, int ma_shift, int...
  function iMAOnArray (line 2767) | double iMAOnArray (double* array, int total, int ma_period, int ma_shift...
  function iMACD (line 2772) | double iMACD (const string symbol, int timeframe, int fast_ema_period, i...
  function iMACD (line 2783) | double iMACD (long symbol, int timeframe, int fast_ema_period, int slow_...
  function iMFI (line 2787) | double iMFI (const string symbol, int timeframe, int period, int shift) {
  function iMFI (line 2798) | double iMFI (long symbol, int timeframe, int period, int shift) {
  function iMomentum (line 2802) | double iMomentum (const string symbol, int timeframe, int period, int ap...
  function iMomentum (line 2813) | double iMomentum (long symbol, int timeframe, int period, int applied_pr...
  function iMomentumOnArray (line 2816) | double iMomentumOnArray (double* array, int total, int period, int shift) {
  function iRSI (line 2821) | double iRSI (const string symbol, int timeframe, int period, int applied...
  function iRSI (line 2832) | double iRSI (long symbol, int timeframe, int period, int applied_price, ...
  function iRSIOnArray (line 2835) | double iRSIOnArray (double* array, int total, int period, int shift) {
  function iRVI (line 2840) | double iRVI (const string symbol, int timeframe, int period, int mode, i...
  function iRVI (line 2851) | double iRVI (long symbol, int timeframe, int period, int mode, int shift) {
  function iSAR (line 2855) | double iSAR (const string symbol, int timeframe, double step, double max...
  function iSAR (line 2866) | double iSAR (long symbol, int timeframe, double step, double maximum, in...
  function iStochastic (line 2870) | double iStochastic (const string symbol, int timeframe, int Kperiod, int...
  function iStochastic (line 2881) | double iStochastic (long symbol, int timeframe, int Kperiod, int Dperiod...
  function iWPR (line 2885) | double iWPR (const string symbol, int timeframe, int period, int shift) {
  function iWPR (line 2896) | double iWPR (long symbol, int timeframe, int period, int shift) {
  function ObjectDelete (line 2909) | bool ObjectDelete (const string object_name) {
  function ObjectDelete (line 2913) | bool ObjectDelete (long chart_id, const string object_name) {
  function ObjectGet (line 2917) | double ObjectGet (const string object_name, int property_index) {
  function ObjectSet (line 2922) | bool ObjectSet (const string object_name, int property_index, double val...
  function OrderSend (line 2927) | int OrderSend (const string symbol, int cmd, double volume, double price...
  function OrderSend (line 2931) | int OrderSend (long symbol, int cmd, double volume, double price, int sl...
  function OrderModify (line 2936) | bool OrderModify (int ticket, double price, double stoploss, double take...
  function OrderClose (line 2941) | bool OrderClose(int ticket, double lots, double price, int slippage, int...
  function OrderDelete (line 2946) | bool OrderDelete(int ticket, int arrow_color) {
  function OrderDelete (line 2950) | bool OrderDelete(int ticket) {
  function datetime (line 2955) | datetime GlobalVariableSet (const string name, double value) {
  function GlobalVariableCheck (line 2959) | bool GlobalVariableCheck (const string name) {
  function GlobalVariableGet (line 2963) | double GlobalVariableGet (const string name) {
  function GlobalVariableDel (line 2967) | bool GlobalVariableDel (const string name) {
  function IsTesting (line 2971) | bool IsTesting () {
  function MarketInfo (line 2975) | double MarketInfo (const string symbol, int type) {
  function MarketInfo (line 2992) | double MarketInfo (long symbol, int type) {
  function SCompareL (line 2998) | bool SCompareL (const string str, long l) {
  function VeriSig (line 3003) | bool VeriSig (const string fintechee_data, const string fintechee_signat...
  function CreateNeuralNetwork (line 3047) | bool CreateNeuralNetwork (const string nnName, const string nnJson) {
  function ActivateNeuralNetwork (line 3053) | double ActivateNeuralNetwork (const string nnName, double* input, int in...
  function PreventCleanUp (line 3059) | void PreventCleanUp () {
  function BuildCNN (line 3065) | bool BuildCNN (const string nnName, int inputNum, int hiddenNum) {
  function TrainCNN (line 3071) | bool TrainCNN (const string nnName, double* dataInput, double* dataOutpu...
  function RunCNN (line 3077) | double RunCNN (const string nnName, double* dataInput, int inputNum) {
  function SaveCNN (line 3083) | bool SaveCNN (const string nnName) {
  function LoadCNN (line 3089) | bool LoadCNN (const string nnName) {

FILE: EA/Plugin-for-MQL/mqlindi2fintechee.h
  type time_t (line 19) | typedef time_t datetime;
  type color (line 20) | typedef int color;
  type ENUM_TIMEFRAMES (line 22) | enum ENUM_TIMEFRAMES {
  type ENUM_APPLIED_PRICE (line 34) | enum ENUM_APPLIED_PRICE {
  type ENUM_MA_METHOD (line 43) | enum ENUM_MA_METHOD {
  type ENUM_INIT_RETCODE (line 49) | enum ENUM_INIT_RETCODE {
  type ENUM_OBJECT (line 125) | enum ENUM_OBJECT {
  function catch (line 293) | catch (e) {
  function Sleep (line 328) | void Sleep (int milliseconds) {
  function GetLastError (line 331) | int GetLastError () {
  function string (line 334) | string ErrorDescription (int code) {
  function IsStopped (line 337) | bool IsStopped () {
  function RefreshRates (line 340) | bool RefreshRates () {
  function MathAbs (line 343) | double MathAbs (double val) {
  function MathArccos (line 346) | double MathArccos (double val) {
  function MathArcsin (line 349) | double MathArcsin (double val) {
  function MathArctan (line 352) | double MathArctan (double val) {
  function MathCeil (line 355) | double MathCeil (double val) {
  function MathCos (line 358) | double MathCos (double val) {
  function MathExp (line 361) | double MathExp (double val) {
  function MathFloor (line 364) | double MathFloor (double val) {
  function MathLog (line 367) | double MathLog (double val) {
  function MathLog10 (line 370) | double MathLog10 (double val) {
  function MathMax (line 373) | double MathMax (double a, double b) {
  function MathMin (line 376) | double MathMin (double a, double b) {
  function MathMod (line 379) | double MathMod (double a, double b) {
  function MathPow (line 382) | double MathPow (double base, double exponent) {
  function MathRand (line 385) | int MathRand () {
  function MathRound (line 388) | double MathRound (double val) {
  function MathSin (line 391) | double MathSin (double val) {
  function MathSqrt (line 394) | double MathSqrt (double val) {
  function MathSrand (line 397) | void MathSrand (int seed) {
  function MathTan (line 400) | double MathTan (double val) {
  function StringLen (line 403) | int StringLen (const string string_value) {
  function StringReplace (line 406) | int StringReplace (string str, const string find, const string replaceme...
  function string (line 419) | string StringSubstr (const string string_value, int start_pos, int lengt...
  function StringToLower (line 425) | bool StringToLower (string string_var) {
  function StringToUpper (line 429) | bool StringToUpper (string string_var) {
  function string (line 433) | string StringTrimLeft(const string text) {
  function string (line 438) | string StringTrimRight(const string text) {
  function string (line 443) | string DoubleToString (double value, int dijits) {
  function string (line 448) | string DoubleToString (double value) {
  function string (line 451) | string DoubleToStr (double value, int dijits) {
  function string (line 454) | string DoubleToStr (double value) {
  function string (line 457) | string IntegerToString (long number, int str_len, unsigned short fill_sy...
  function string (line 460) | string ShortToString (unsigned short symbol_code) {
  function string (line 463) | string TimeToString (datetime value, int mode) {
  function string (line 488) | string TimeToString (datetime value) {
  function string (line 491) | string TimeToStr (datetime value, int mode) {
  function string (line 494) | string TimeToStr (datetime value) {
  function NormalizeDouble (line 497) | double NormalizeDouble (double value, int digits) {
  function StringToDouble (line 500) | double StringToDouble (const string value) {
  function StrToDouble (line 503) | double StrToDouble (const string value) {
  function StringToInteger (line 506) | int StringToInteger (const string value) {
  function StrToInteger (line 509) | int StrToInteger (const string value) {
  function datetime (line 512) | datetime StringToTime (const string value) {
  function datetime (line 527) | datetime StrToTime (const string value) {
  function datetime (line 537) | datetime TimeCurrent () {
  function datetime (line 540) | datetime TimeGMT () {
  function datetime (line 543) | datetime CurTime () {
  function Day (line 546) | int Day () {
  function DayOfWeek (line 551) | int DayOfWeek () {
  function DayOfYear (line 556) | int DayOfYear () {
  function Hour (line 561) | int Hour () {
  function Minute (line 566) | int Minute () {
  function Month (line 571) | int Month () {
  function Seconds (line 576) | int Seconds () {
  function TimeDay (line 581) | int TimeDay (datetime ltime) {
  function TimeDayOfWeek (line 586) | int TimeDayOfWeek (datetime ltime) {
  function TimeDayOfYear (line 591) | int TimeDayOfYear (datetime ltime) {
  function TimeHour (line 596) | int TimeHour (datetime ltime) {
  function TimeMinute (line 601) | int TimeMinute (datetime ltime) {
  function TimeMonth (line 606) | int TimeMonth (datetime ltime) {
  function TimeSeconds (line 611) | int TimeSeconds (datetime ltime) {
  function TimeYear (line 616) | int TimeYear (datetime ltime) {
  function Year (line 621) | int Year () {
  function ArrayCopy (line 626) | int ArrayCopy (char* dst_array, const char* src_array, int dst_start, in...
  function ArrayCopy (line 634) | int ArrayCopy (short* dst_array, const short* src_array, int dst_start, ...
  function ArrayCopy (line 642) | int ArrayCopy (int* dst_array, const int* src_array, int dst_start, int ...
  function ArrayCopy (line 650) | int ArrayCopy (long* dst_array, const long* src_array, int dst_start, in...
  function ArrayCopy (line 658) | int ArrayCopy (float* dst_array, const float* src_array, int dst_start, ...
  function ArrayCopy (line 666) | int ArrayCopy (double* dst_array, const double* src_array, int dst_start...
  function ArrayCopy (line 674) | int ArrayCopy (bool* dst_array, const bool* src_array, int dst_start, in...
  function ArrayFree (line 682) | void ArrayFree (void* array) {
  function ArrayInitialize (line 685) | void ArrayInitialize (char* array, char value, int count) {
  function ArrayInitialize (line 692) | void ArrayInitialize (short* array, short value, int count) {
  function ArrayInitialize (line 699) | void ArrayInitialize (int* array, int value, int count) {
  function ArrayInitialize (line 706) | void ArrayInitialize (long* array, long value, int count) {
  function ArrayInitialize (line 713) | void ArrayInitialize (float* array, float value, int count) {
  function ArrayInitialize (line 720) | void ArrayInitialize (double* array, double value, int count) {
  function ArrayInitialize (line 727) | void ArrayInitialize (bool* array, bool value, int count) {
  function ArrayFill (line 734) | void ArrayFill (char* array, int start, int count, char value) {
  function ArrayFill (line 737) | void ArrayFill (short* array, int start, int count, short value) {
  function ArrayFill (line 740) | void ArrayFill (int* array, int start, int count, int value) {
  function ArrayFill (line 743) | void ArrayFill (long* array, int start, int count, long value) {
  function ArrayFill (line 746) | void ArrayFill (float* array, int start, int count, float value) {
  function ArrayFill (line 749) | void ArrayFill (double* array, int start, int count, double value) {
  function ArrayFill (line 752) | void ArrayFill (bool* array, int start, int count, bool value) {
  function ArrayMaximum (line 755) | int ArrayMaximum (const short* array, int count, int start) {
  function ArrayMaximum (line 770) | int ArrayMaximum (const int* array, int count, int start) {
  function ArrayMaximum (line 785) | int ArrayMaximum (const long* array, int count, int start) {
  function ArrayMaximum (line 800) | int ArrayMaximum (const float* array, int count, int start) {
  function ArrayMaximum (line 815) | int ArrayMaximum (const double* array, int count, int start) {
  function ArrayMinimum (line 830) | int ArrayMinimum (const short* array, int count, int start) {
  function ArrayMinimum (line 845) | int ArrayMinimum (const int* array, int count, int start) {
  function ArrayMinimum (line 860) | int ArrayMinimum (const long* array, int count, int start) {
  function ArrayMinimum (line 875) | int ArrayMinimum (const float* array, int count, int start) {
  function ArrayMinimum (line 890) | int ArrayMinimum (const double* array, int count, int start) {
  function ArrayResize (line 905) | int ArrayResize (char** array, int new_size, int reserve_size) {
  function ArrayResize (line 919) | int ArrayResize (short** array, int new_size, int reserve_size) {
  function ArrayResize (line 933) | int ArrayResize (int** array, int new_size, int reserve_size) {
  function ArrayResize (line 947) | int ArrayResize (long** array, int new_size, int reserve_size) {
  function ArrayResize (line 961) | int ArrayResize (float** array, int new_size, int reserve_size) {
  function ArrayResize (line 975) | int ArrayResize (double** array, int new_size, int reserve_size) {
  function ArrayResize (line 989) | int ArrayResize (bool** array, int new_size, int reserve_size) {
  function ArrayResize (line 1003) | int ArrayResize (char** array, int new_size) {
  function ArrayResize (line 1006) | int ArrayResize (short** array, int new_size) {
  function ArrayResize (line 1009) | int ArrayResize (int** array, int new_size) {
  function ArrayResize (line 1012) | int ArrayResize (long** array, int new_size) {
  function ArrayResize (line 1015) | int ArrayResize (float** array, int new_size) {
  function ArrayResize (line 1018) | int ArrayResize (double** array, int new_size) {
  function ArrayResize (line 1021) | int ArrayResize (bool** array, int new_size) {
  function ArraySort (line 1024) | bool ArraySort (char* array, int count, int start, int direction) {
  function ArraySort (line 1036) | bool ArraySort (short* array, int count, int start, int direction) {
  function ArraySort (line 1048) | bool ArraySort (int* array, int count, int start, int direction) {
  function ArraySort (line 1060) | bool ArraySort (long* array, int count, int start, int direction) {
  function ArraySort (line 1072) | bool ArraySort (float* array, int count, int start, int direction) {
  function ArraySort (line 1084) | bool ArraySort (double* array, int count, int start, int direction) {
  function ArrayBsearch (line 1096) | int ArrayBsearch (const char* array, char value, int count, int start, i...
  function ArrayBsearch (line 1117) | int ArrayBsearch (const short* array, short value, int count, int start,...
  function ArrayBsearch (line 1138) | int ArrayBsearch (const int* array, int value, int count, int start, int...
  function ArrayBsearch (line 1159) | int ArrayBsearch (const long* array, long value, int count, int start, i...
  function ArrayBsearch (line 1180) | int ArrayBsearch (const float* array, float value, int count, int start,...
  function ArrayBsearch (line 1201) | int ArrayBsearch (const double* array, double value, int count, int star...
  type Parameter (line 1223) | struct Parameter {
  type DataInput (line 1231) | struct DataInput {
  type DataOutput (line 1236) | struct DataOutput {
  type GlobalVar (line 1241) | struct GlobalVar {
  type ParamInputOutputItem (line 1246) | struct ParamInputOutputItem {
  function setParam (line 1260) | void setParam (int uid, const struct Parameter & parameter) {
  function datetime (line 1270) | datetime setGlobalVar (int uid, const string name, double value) {
  function checkGlobalVar (line 1286) | bool checkGlobalVar (int uid, const string name) {
  function getGlobalVar (line 1294) | double getGlobalVar (int uid, const string name) {
  function delGlobalVar (line 1302) | bool delGlobalVar (int uid, const string name) {
  function EMSCRIPTEN_KEEPALIVE (line 1317) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1324) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1331) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1338) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1345) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1358) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1371) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1375) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1379) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1383) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1387) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1391) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1395) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1399) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1403) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1407) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1411) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1415) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1419) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1423) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1427) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1431) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1435) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1439) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1443) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1447) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1451) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1455) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1459) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1463) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1467) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1471) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1475) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1479) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1483) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1487) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1491) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1495) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1499) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1503) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1507) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1511) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1515) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1519) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1523) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1527) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1531) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1535) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1539) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1543) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1547) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1551) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1555) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1559) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1563) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1567) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1571) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1575) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1579) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1583) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1587) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1591) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1595) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1599) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1603) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1607) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1611) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1615) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1619) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1623) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1627) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1631) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1635) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1639) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1643) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1647) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1651) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1655) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1659) | EMSCRIPTEN_KEEPALIVE
  function EMSCRIPTEN_KEEPALIVE (line 1663) | EMSCRIPTEN_KEEPALIVE
  function PlaySound (line 1696) | bool PlaySound (const string name) {
  function SetIndexShift (line 1701) | void SetIndexShift (int index, int shift) {
  function ChartID (line 1705) | long ChartID () {
  function ENUM_TIMEFRAMES (line 1709) | ENUM_TIMEFRAMES ChartPeriod (long chart_id) {
  function ENUM_TIMEFRAMES (line 1712) | ENUM_TIMEFRAMES ChartPeriod () {
  function string (line 1716) | string ChartSymbol (long chart_id) {
  function string (line 1720) | string ChartSymbol () {
  function ENUM_TIMEFRAMES (line 1724) | ENUM_TIMEFRAMES Period () {
  function string (line 1728) | string Symbol () {
  function datetime (line 1733) | datetime iTime (const string symbol, int timeframe, int shift) {
  function datetime (line 1742) | datetime iTime (long symbol, int timeframe, int shift) {
  function iOpen (line 1745) | double iOpen (const string symbol, int timeframe, int shift) {
  function iOpen (line 1754) | double iOpen (long symbol, int timeframe, int shift) {
  function iHigh (line 1757) | double iHigh (const string symbol, int timeframe, int shift) {
  function iHigh (line 1766) | double iHigh (long symbol, int timeframe, int shift) {
  function iLow (line 1769) | double iLow (const string symbol, int timeframe, int shift) {
  function iLow (line 1778) | double iLow (long symbol, int timeframe, int shift) {
  function iClose (line 1781) | double iClose (const string symbol, int timeframe, int shift) {
  function iClose (line 1790) | double iClose (long symbol, int timeframe, int shift) {
  function iVolume (line 1793) | long iVolume (const string symbol, int timeframe, int shift) {
  function iVolume (line 1802) | long iVolume (long symbol, int timeframe, int shift) {
  function iHighest (line 1805) | int iHighest (const string symbol, int timeframe, int type, int count, i...
  function iHighest (line 1814) | int iHighest (long symbol, int timeframe, int type, int count, int start) {
  function Highest (line 1817) | int Highest (const string symbol, int timeframe, int type, int count, in...
  function Highest (line 1820) | int Highest (long symbol, int timeframe, int type, int count, int start) {
  function iLowest (line 1823) | int iLowest (const string symbol, int timeframe, int type, int count, in...
  function iLowest (line 1832) | int iLowest (long symbol, int timeframe, int type, int count, int start) {
  function Lowest (line 1835) | int Lowest (const string symbol, int timeframe, int type, int count, int...
  function Lowest (line 1838) | int Lowest (long symbol, int timeframe, int type, int count, int start) {
  function iAC (line 1842) | double iAC (const string symbol, int timeframe, int shift) {
  function iAC (line 1851) | double iAC (long symbol, int timeframe, int shift) {
  function iADX (line 1855) | double iADX (const string symbol, int timeframe, int period, int applied...
  function iADX (line 1864) | double iADX (long symbol, int timeframe, int period, int applied_price, ...
  function iAlligator (line 1868) | double iAlligator (
  function iAlligator (line 1881) | double iAlligator (
  function iAO (line 1887) | double iAO (const string symbol, int timeframe, int shift) {
  function iAO (line 1896) | double iAO (long symbol, int timeframe, int shift) {
  function iATR (line 1900) | double iATR (const string symbol, int timeframe, int period, int shift) {
  function iATR (line 1909) | double iATR (long symbol, int timeframe, int period, int shift) {
  function iBearsPower (line 1913) | double iBearsPower (const string symbol, int timeframe, int period, int ...
  function iBearsPower (line 1922) | double iBearsPower (long symbol, int timeframe, int period, int applied_...
  function iBands (line 1926) | double iBands (const string symbol, int timeframe, int period, double de...
  function iBands (line 1935) | double iBands (long symbol, int timeframe, int period, double deviation,...
  function iBandsOnArray (line 1938) | double iBandsOnArray (double* array, int total, int period, double devia...
  function iBullsPower (line 1942) | double iBullsPower (const string symbol, int timeframe, int period, int ...
  function iBullsPower (line 1951) | double iBullsPower (long symbol, int timeframe, int period, int applied_...
  function iCCI (line 1955) | double iCCI (const string symbol, int timeframe, int period, int applied...
  function iCCI (line 1964) | double iCCI (long symbol, int timeframe, int period, int applied_price, ...
  function iCCIOnArray (line 1967) | double iCCIOnArray (double* array, int total, int period, int shift) {
  function iDeMarker (line 2005) | double iDeMarker (const string symbol, int timeframe, int period, int sh...
  function iDeMarker (line 2014) | double iDeMarker (long symbol, int timeframe, int period, int shift) {
  function iEnvelopes (line 2018) | double iEnvelopes (const string symbol, int timeframe, int ma_period, in...
  function iEnvelopes (line 2027) | double iEnvelopes (long symbol, int timeframe, int ma_period, int ma_met...
  function iEnvelopesOnArray (line 2030) | double iEnvelopesOnArray (double* array, int total, int ma_period, int m...
  function iFractals (line 2034) | double iFractals (const string symbol, int timeframe, int mode, int shif...
  function iFractals (line 2043) | double iFractals (long symbol, int timeframe, int mode, int shift) {
  function iIchimoku (line 2047) | double iIchimoku (const string symbol, int timeframe, int tenkan_sen, in...
  function iIchimoku (line 2066) | double iIchimoku (long symbol, int timeframe, int tenkan_sen, int kijun_...
  function iMA (line 2070) | double iMA (const string symbol, int timeframe, int ma_period, int ma_sh...
  function iMA (line 2079) | double iMA (long symbol, int timeframe, int ma_period, int ma_shift, int...
  function iMAOnArray (line 2082) | double iMAOnArray (double* array, int total, int ma_period, int ma_shift...
  function iMACD (line 2086) | double iMACD (const string symbol, int timeframe, int fast_ema_period, i...
  function iMACD (line 2095) | double iMACD (long symbol, int timeframe, int fast_ema_period, int slow_...
  function iMFI (line 2099) | double iMFI (const string symbol, int timeframe, int period, int shift) {
  function iMFI (line 2108) | double iMFI (long symbol, int timeframe, int period, int shift) {
  function iMomentum (line 2112) | double iMomentum (const string symbol, int timeframe, int period, int ap...
  function iMomentum (line 2121) | double iMomentum (long symbol, int timeframe, int period, int applied_pr...
  function iMomentumOnArray (line 2124) | double iMomentumOnArray (double* array, int total, int period, int shift) {
  function iRSI (line 2128) | double iRSI (const string symbol, int timeframe, int period, int applied...
  function iRSI (line 2137) | double iRSI (long symbol, int timeframe, int period, int applied_price, ...
  function iRSIOnArray (line 2140) | double iRSIOnArray (double* array, int total, int period, int shift) {
  function iRVI (line 2144) | double iRVI (const string symbol, int timeframe, int period, int mode, i...
  function iRVI (line 2153) | double iRVI (long symbol, int timeframe, int period, int mode, int shift) {
  function iSAR (line 2157) | double iSAR (const string symbol, int timeframe, double step, double max...
  function iSAR (line 2166) | double iSAR (long symbol, int timeframe, double step, double maximum, in...
  function iStochastic (line 2170) | double iStochastic (const string symbol, int timeframe, int Kperiod, int...
  function iStochastic (line 2179) | double iStochastic (long symbol, int timeframe, int Kperiod, int Dperiod...
  function iWPR (line 2183) | double iWPR (const string symbol, int timeframe, int period, int shift) {
  function iWPR (line 2192) | double iWPR (long symbol, int timeframe, int period, int shift) {
  function datetime (line 2197) | datetime GlobalVariableSet (const string name, double value) {
  function GlobalVariableCheck (line 2201) | bool GlobalVariableCheck (const string name) {
  function GlobalVariableGet (line 2205) | double GlobalVariableGet (const string name) {
  function GlobalVariableDel (line 2209) | bool GlobalVariableDel (const string name) {
  function MarketInfo (line 2213) | double MarketInfo (const string symbol, int type) {
  function MarketInfo (line 2216) | double MarketInfo (long symbol, int type) {
  function SCompareL (line 2222) | bool SCompareL (const string str, long l) {
  function VeriSig (line 2227) | bool VeriSig (const string fintechee_data, const string fintechee_signat...

FILE: EA/Plugin-for-MQL/runtestcnn.cpp
  function getPosInfo (line 25) | void getPosInfo(datetime currTime) {
  function trade (line 75) | bool trade(int odrType, double volume, bool bOpen) {
  function OnInit (line 121) | int OnInit (void) {
  function OnTick (line 127) | void OnTick(void) {
  function OnDeinit (line 182) | void OnDeinit (const int) {

FILE: EA/Plugin-for-MQL/testcnn.cpp
  function OnInit (line 17) | int OnInit (void) {
  function OnTick (line 28) | void OnTick(void) {
  function OnDeinit (line 55) | void OnDeinit (const int) {

FILE: EA/Plugin-for-MQL/testverisig.cpp
  function OnInit (line 11) | int OnInit (void) {
  function OnTick (line 20) | void OnTick(void) {

FILE: EA/Plugin-for-XCoinCH/market_maker_bot.js
  function getDex (line 1315) | function getDex (state) {
  function getCryptocurrencies (line 1342) | function getCryptocurrencies (state) {

FILE: Indicators/Built-in/common.js
  function getHighestOnArray (line 1) | function getHighestOnArray (dataInput, dataOutput, calculatedLength, per...
  function getLowestOnArray (line 39) | function getLowestOnArray (dataInput, dataOutput, calculatedLength, peri...
  function sumOnArray (line 77) | function sumOnArray (dataInput, dataOutput, calculatedLength, period) {
  function sma (line 103) | function sma (dataInput, dataOutput, calculatedLength, period) {
  function ema (line 129) | function ema (dataInput, dataOutput, calculatedLength, period) {
  function smma (line 147) | function smma (dataInput, dataOutput, calculatedLength, period) {
  function lwma (line 173) | function lwma (dataInput, dataOutput, calculatedLength, period) {
Condensed preview — 143 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (948K chars).
[
  {
    "path": "AI/aitrader_12_eurusd.json",
    "chars": 1643,
    "preview": "{\"modelTopology\":{\"class_name\":\"Sequential\",\"config\":{\"name\":\"sequential_20\",\"layers\":[{\"class_name\":\"Conv1D\",\"config\":{"
  },
  {
    "path": "AI/aitrader_12_gbpusd.json",
    "chars": 1635,
    "preview": "{\"modelTopology\":{\"class_name\":\"Sequential\",\"config\":{\"name\":\"sequential_8\",\"layers\":[{\"class_name\":\"Conv1D\",\"config\":{\""
  },
  {
    "path": "AI/readme.md",
    "chars": 932,
    "preview": "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 "
  },
  {
    "path": "EA/Arbitrage/README.md",
    "chars": 58,
    "preview": "We will add more details to introduce how to use this EA.\n"
  },
  {
    "path": "EA/Arbitrage/fintechee_external_arbitrage.js",
    "chars": 19543,
    "preview": "registerEA(\n  \"fintechee_external_arbitrage\",\n  \"A test EA to trade arbitrage based on the price difference between Fint"
  },
  {
    "path": "EA/Arbitrage/guide_for_fintechee_external_arbitrage.txt",
    "chars": 938,
    "preview": "To utilize this EA and display the statistics panel regarding the frequencies of arbitrage opportunities, you must first"
  },
  {
    "path": "EA/Arbitrage/sample_trading_arbitrage.js",
    "chars": 4186,
    "preview": "registerEA(\n\t\t\"sample_trading_arbitrage\",\n\t\t\"Two accounts signed up on the different servers are required to trade arbit"
  },
  {
    "path": "EA/Built-in/README.md",
    "chars": 172,
    "preview": "The EAs in this folder will be updated automatically when you open the WEB trader.\n\nIf you customize the EAs in this fol"
  },
  {
    "path": "EA/Built-in/sample_using_rsi.js",
    "chars": 2326,
    "preview": "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,"
  },
  {
    "path": "EA/Built-in/sample_using_sma.js",
    "chars": 2507,
    "preview": "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,"
  },
  {
    "path": "EA/Chaos/chaos.js",
    "chars": 31905,
    "preview": "registerEA(\n  \"chaos\",\n  \"An EA based on Chaos theory(v1.0)\",\n  [{\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n    req"
  },
  {
    "path": "EA/Chaos/intro.txt",
    "chars": 182,
    "preview": "EA based on Trading Chaos(Bill Williams' book). All of the strategies described in the book have been implemented. Addit"
  },
  {
    "path": "EA/CopyTrading/README.md",
    "chars": 25,
    "preview": "This is just an example.\n"
  },
  {
    "path": "EA/CopyTrading/copy_trading_for_oanda.js",
    "chars": 1778,
    "preview": "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"
  },
  {
    "path": "EA/CopyTrading/copy_trading_for_oanda_guide.txt",
    "chars": 1477,
    "preview": "Use Case: A provides signals, B follows the signals from A to copy trade. A's account is a Fintechee-based account, B's "
  },
  {
    "path": "EA/CopyTrading/copy_trading_locally.js",
    "chars": 3101,
    "preview": "registerEA(\n\"copy_trading_locally\",\n\"A simple EA to copy trading locally(v1.01)\",\n[{\n\tname: \"fromAccountId\",\n\tvalue: \"XX"
  },
  {
    "path": "EA/CopyTrading/copy_trading_locally_guide.txt",
    "chars": 1137,
    "preview": "Use Case: A provides signals, B follows the signals from A to copy trade. Both accounts are Fintechee-based.\n\nHow to do?"
  },
  {
    "path": "EA/Martingale/improved_martingale.js",
    "chars": 7505,
    "preview": "registerEA(\n  \"improved_martingale\",\n  \"An EA based on an improved Martingale algorithm(v1.0)\",\n  [{\n    name: \"diffPric"
  },
  {
    "path": "EA/Martingale/improved_martingale.txt",
    "chars": 340,
    "preview": "Usually, Martingale strategy involves doubling the bet once a loss occurs and engaging in one-sided trading. In contrast"
  },
  {
    "path": "EA/Martingale/sample_martingale.js",
    "chars": 3368,
    "preview": "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: \"peri"
  },
  {
    "path": "EA/NeuralNetwork/nn_example.js",
    "chars": 2423,
    "preview": "// Please check this post to know how to use this EA: https://www.fintecher.org/daily-trading/added-genetic-algorithm-fo"
  },
  {
    "path": "EA/NeuralNetwork/sample_run_neuron_model.js",
    "chars": 3523,
    "preview": "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\","
  },
  {
    "path": "EA/NeuralNetwork/sample_training_neuron_model.js",
    "chars": 3452,
    "preview": "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: \"p"
  },
  {
    "path": "EA/NeuralNetwork/usage.txt",
    "chars": 645,
    "preview": "“sample_training_neuron_model” and “sample_run_neuron_model” are two neural network-based EAs that must be used together"
  },
  {
    "path": "EA/Oldie/README.md",
    "chars": 46,
    "preview": "This folder contains the deprecated programs.\n"
  },
  {
    "path": "EA/Oldie/README.txt",
    "chars": 42,
    "preview": "This folder contains deprecated programs.\n"
  },
  {
    "path": "EA/Oldie/fixapi_oanda_arbitrage.js",
    "chars": 18935,
    "preview": "// Deprecated. A new version has been released. Please refer to EA/fintechee_external_arbitrage.js.\nregisterEA(\n  \"fixap"
  },
  {
    "path": "EA/Plugin-for-Deribit/plugin_for_deribit.js",
    "chars": 18122,
    "preview": "registerEA(\n\"plugin_for_deribit\",\n\"A plugin to trade cryptocurrency options(v0.08)\",\n[{\n\tname: \"interval\",\n\tvalue: 30,\n\t"
  },
  {
    "path": "EA/Plugin-for-Deribit/usage.txt",
    "chars": 156,
    "preview": "You can use this EA to get crypto options' streaming quotes. Crypto options are much more complex than Forex or CFD. So,"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_approve.js",
    "chars": 1986,
    "preview": "registerEA(\n\t\t\"decentralized_exchange_eos_approve\",\n\t\t\"A decentralized exchange plugin to approve a proposal for exchang"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_cancel.js",
    "chars": 1926,
    "preview": "registerEA(\n\t\t\"decentralized_exchange_eos_cancel\",\n\t\t\"A decentralized exchange plugin to cancel a proposal for exchangin"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_exec.js",
    "chars": 1935,
    "preview": "registerEA(\n\t\t\"decentralized_exchange_eos_exec\",\n\t\t\"A decentralized exchange plugin to execute a transaction of exchangi"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_propose.js",
    "chars": 3931,
    "preview": "registerEA(\n\t\t\"decentralized_exchange_eos_propose\",\n\t\t\"A decentralized exchange plugin to propose for exchanging digital"
  },
  {
    "path": "EA/Plugin-for-EOS/decentralized_exchange_eos_unapprove.js",
    "chars": 1970,
    "preview": "registerEA(\n\t\t\"decentralized_exchange_eos_unapprove\",\n\t\t\"A decentralized exchange plugin to unapprove a proposal for exc"
  },
  {
    "path": "EA/Plugin-for-EOS/payment_gateway_eos.js",
    "chars": 2464,
    "preview": "registerEA(\n\t\t\"payment_gateway_eos\",\n\t\t\"A payment gateway plugin to make you fund(deposit or withdraw) via EOS platform("
  },
  {
    "path": "EA/Plugin-for-EOS/payment_gateway_eos_lib_loader.js",
    "chars": 2713,
    "preview": "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[{ // param"
  },
  {
    "path": "EA/Plugin-for-EOS/payment_gateway_eos_scatter.js",
    "chars": 4125,
    "preview": "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)\""
  },
  {
    "path": "EA/Plugin-for-EOS/usage.txt",
    "chars": 360,
    "preview": "This folder contains programs that are used for integrating with the EOS blockchain. These programs provide excellent ex"
  },
  {
    "path": "EA/Plugin-for-FXCM/README.md",
    "chars": 36,
    "preview": "## Developing. Will be coming soon.\n"
  },
  {
    "path": "EA/Plugin-for-MQL/README.md",
    "chars": 2397,
    "preview": "# Expert-Advisor-Cpp-Compiler\n\nThis is a Nodejs package to help Fintechee's users compile C/C++/MQL source codes(to make"
  },
  {
    "path": "EA/Plugin-for-MQL/mqlea2fintechee.h",
    "chars": 97946,
    "preview": "#include <stdio.h>\n#include <stdarg.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n#include <map>\n#include "
  },
  {
    "path": "EA/Plugin-for-MQL/mqlindi2fintechee.h",
    "chars": 74546,
    "preview": "#include <stdio.h>\n#include <stdarg.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n#include <map>\n#include "
  },
  {
    "path": "EA/Plugin-for-MQL/plugin_for_mql.js",
    "chars": 150843,
    "preview": "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"
  },
  {
    "path": "EA/Plugin-for-MQL/runtestcnn.cpp",
    "chars": 4195,
    "preview": "#define INPUT_NUM 10\n#define HIDDEN_NUM 10\n#define NN_NAME \"testcnn\"\n\ninput string ext_strSymbol = \"EUR/USD\";\ninput int "
  },
  {
    "path": "EA/Plugin-for-MQL/testcnn.cpp",
    "chars": 3109,
    "preview": "#define ARR_NUM 1001\n#define INPUT_NUM 10\n#define HIDDEN_NUM 10\n#define NN_NAME \"testcnn\"\n#define ITERATIONS 1000\n#defin"
  },
  {
    "path": "EA/Plugin-for-MQL/testverisig.cpp",
    "chars": 2027,
    "preview": "// This example is for the developers who want to sell EAs via Fintechee.io website.\n// If you use EA for yourself or yo"
  },
  {
    "path": "EA/Plugin-for-MQL/usage.txt",
    "chars": 669,
    "preview": "Our platform is compatible with any programming language based on WEB-Assembly. MQL, C++, and Python based programs can "
  },
  {
    "path": "EA/Plugin-for-Oanda/plugin_for_oanda.js",
    "chars": 16185,
    "preview": "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// Discl"
  },
  {
    "path": "EA/Plugin-for-Oanda/usage.txt",
    "chars": 653,
    "preview": "Oanda is a well-known broker that offers API trading. As a result, we have created a plugin that establishes both a data"
  },
  {
    "path": "EA/Plugin-for-SNS/plugin_for_sns.js",
    "chars": 7247,
    "preview": "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"
  },
  {
    "path": "EA/Plugin-for-SNS/usage.txt",
    "chars": 711,
    "preview": "This plugin is deprecated. We have a new plugin named \"Plugin for SNS with OpenAI\" instead.\n1, Launch an EA (Expert Advi"
  },
  {
    "path": "EA/Plugin-for-SNS-with-OpenAI/plugin_for_sns_with_openai.js",
    "chars": 9145,
    "preview": "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) { /"
  },
  {
    "path": "EA/Plugin-for-SNS-with-OpenAI/usage.txt",
    "chars": 651,
    "preview": "1, Launch an EA (Expert Advisor) named \"plugin_for_sns_with_openai\".\n2, If you are a publisher, input the topic name and"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/import_export_model.js",
    "chars": 3426,
    "preview": "registerEA(\n\"import_export_model\",\n\"An EA to import a model from files to localStorage or export a model from localStora"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/plugin_to_load_tensorflow.js",
    "chars": 8914,
    "preview": "registerEA(\n\t  \"plugin_to_load_tensorflow\",\n\t  \"A plugin to load Tensorflow(v1.13)\",\n\t  [{ // parameters\n\t    name: \"tfj"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/sample_running_cnn_model.js",
    "chars": 8555,
    "preview": "registerEA(\n\t  \"sample_running_cnn_model\",\n\t  \"An EA sample to run neuron model(v1.04)\",\n\t  [{ // parameters\n\t    name: "
  },
  {
    "path": "EA/Plugin-for-Tensorflow/sample_training_cnn_model.js",
    "chars": 13583,
    "preview": "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: "
  },
  {
    "path": "EA/Plugin-for-Tensorflow/test_loading_tensorflow.js",
    "chars": 992,
    "preview": "registerEA(\n  \"test_loading_tensorflow\",\n  \"A test EA to load Tensorflow2.0 (v1.0)\",\n  [{ // parameters\n    name: \"url\","
  },
  {
    "path": "EA/Plugin-for-Tensorflow/test_xor_powered_by_tensorflow.js",
    "chars": 4323,
    "preview": "registerEA(\n  \"test_xor_powered_by_tensorflow\",\n  \"A test EA to train XOR by using Tensorflow2.0 (v1.0)\",\n  [{ // parame"
  },
  {
    "path": "EA/Plugin-for-Tensorflow/usage.txt",
    "chars": 656,
    "preview": "This is the most interesting part that we would like to present to our users.\n\nTensorflow is an AI framework that was ut"
  },
  {
    "path": "EA/Plugin-for-TradingView/plugin_for_tradingview.js",
    "chars": 1568,
    "preview": "registerEA(\n  \"tradingview_widget\",\n  \"A plugin to embed the widget of TradingView(v1.0)\",\n  [],\n  function (context) { "
  },
  {
    "path": "EA/Plugin-for-TrailingStop/plugin_for_trailingstop.js",
    "chars": 2955,
    "preview": "registerEA(\n\"plugin_for_trailingstop\",\n\"A plugin to manage trailing stop(v1.02)\",\n[{\n\tname: \"symbolName\", // this parame"
  },
  {
    "path": "EA/Plugin-for-XCoinCH/market_maker_bot.js",
    "chars": 55103,
    "preview": "registerEA(\n  \"market_maker_bot\",\n  \"Automated market maker(v1.0)\",\n  [{\n  \tname: \"basePlatform\",\n  \tvalue: \"eth\",\n  \tre"
  },
  {
    "path": "EA/Plugin-for-XCoinCH/usage.txt",
    "chars": 367,
    "preview": "XCoinCH is another product developed by the Fintechee team, with X standing for cross and CH for clearing house. XCoinCH"
  },
  {
    "path": "EA/PriceAction/price_action.js",
    "chars": 11251,
    "preview": "// This EA has a built-in trailing stop management system, so, DO NOT use plugin_for_trailingstop at the same time.\nregi"
  },
  {
    "path": "EA/Sample-for-Workflow/callee.js",
    "chars": 681,
    "preview": "registerEA(\n  \"callee\",\n  \"A test EA playing the role as a step in the workflow(v1.0)\",\n  [{\n    name: \"symbolName\",\n   "
  },
  {
    "path": "EA/Sample-for-Workflow/caller.js",
    "chars": 727,
    "preview": "registerEA(\n  \"caller\",\n  \"A test EA to launch the callee EA(v1.0)\",\n  [{\n    name: \"symbolName\",\n    value: \"EUR/USD\",\n"
  },
  {
    "path": "EA/Tips/about_API_getData.txt",
    "chars": 1758,
    "preview": "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 "
  },
  {
    "path": "EA/Tips/how_to_rename.txt",
    "chars": 840,
    "preview": "Why rename the specific EA and indicator?\n\nThis is very important to know before you customize your own EA/indicator by "
  },
  {
    "path": "EA/Utility/historical_data_cleaner.js",
    "chars": 964,
    "preview": "registerEA(\n\t\t\"historical_data_cleaner\",\n\t\t\"An EA only used for clearing historical data stored on your local browser(v1"
  },
  {
    "path": "EA/Utility/historical_data_viewer.js",
    "chars": 910,
    "preview": "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"
  },
  {
    "path": "EA/Utility/usage.txt",
    "chars": 331,
    "preview": "The “historical_data_cleaner” is designed to clear the OHLC data within the IndexedDB stored on your browser.\n\nOn the ot"
  },
  {
    "path": "Indicators/Built-in/README.md",
    "chars": 186,
    "preview": "The indicators in this folder will be updated automatically when you open the WEB trader.\n\nIf you customize the indicato"
  },
  {
    "path": "Indicators/Built-in/ac.js",
    "chars": 1868,
    "preview": "registerIndicator(\n\"ac\",\n\"Accelerator Oscillator(v1.0)\",\nfunction (context) {\n\t\tvar dataInput = getDataInput(context, 0)"
  },
  {
    "path": "Indicators/Built-in/adx.js",
    "chars": 3056,
    "preview": "registerIndicator(\n    \"adx\", \"Average directional index(v1.0)\", function (context) {\n        var dataInputClose = getDa"
  },
  {
    "path": "Indicators/Built-in/alligator.js",
    "chars": 2915,
    "preview": "registerIndicator(\n    \"alligator\", \"A series of Bill Williams' indicators(v1.02)\", function (context) {\n\t\tvar dataInput"
  },
  {
    "path": "Indicators/Built-in/ao.js",
    "chars": 1304,
    "preview": "registerIndicator(\n\"ao\",\n\"Awesome Oscillator(v1.0)\",\nfunction (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tv"
  },
  {
    "path": "Indicators/Built-in/atr.js",
    "chars": 1277,
    "preview": "registerIndicator(\n    \"atr\", \"Average true range(v1.0)\", function (context) {\n\t\tvar dataInputClose = getDataInput(conte"
  },
  {
    "path": "Indicators/Built-in/bands.js",
    "chars": 2426,
    "preview": "registerIndicator(\n\"bands\",\n\"Bollinger Bands(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n"
  },
  {
    "path": "Indicators/Built-in/bears.js",
    "chars": 1108,
    "preview": "registerIndicator(\n\"bears\",\n\"Bears Power(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t   "
  },
  {
    "path": "Indicators/Built-in/bidask.js",
    "chars": 1147,
    "preview": "registerIndicator(\n\"bidask\", \"Bid and Ask(v1.01)\", function (context) {\n\tvar dataInput = getDataInput(context, 0)\n\tif (d"
  },
  {
    "path": "Indicators/Built-in/bulls.js",
    "chars": 1111,
    "preview": "registerIndicator(\n\"bulls\",\n\"Bulls Power(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t   "
  },
  {
    "path": "Indicators/Built-in/cci.js",
    "chars": 2081,
    "preview": "registerIndicator(\n\"cci\",\n\"Commodity Channel Index(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(contex"
  },
  {
    "path": "Indicators/Built-in/common.js",
    "chars": 3729,
    "preview": "function getHighestOnArray (dataInput, dataOutput, calculatedLength, period) {\n\tvar i = calculatedLength\n\n\tif (calculate"
  },
  {
    "path": "Indicators/Built-in/demarker.js",
    "chars": 2880,
    "preview": "registerIndicator(\n\"demarker\",\n\"DeMarker(v1.0)\",\nfunction (context) {\n\t    var dataInputHigh = getDataInput(context, 0)\n"
  },
  {
    "path": "Indicators/Built-in/ema.js",
    "chars": 871,
    "preview": "registerIndicator(\n    \"ema\", \"Exponential moving average(v1.0)\", function (context) {\n        var dataInput = getDataIn"
  },
  {
    "path": "Indicators/Built-in/envelopes.js",
    "chars": 2233,
    "preview": "registerIndicator(\n\"envelopes\",\n\"Envelopes(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t "
  },
  {
    "path": "Indicators/Built-in/fractals.js",
    "chars": 1874,
    "preview": "registerIndicator(\n\"fractals\",\n\"Fractals(v1.02)\",\nfunction (context) {\n\t    var dataInputHigh = getDataInput(context, 0)"
  },
  {
    "path": "Indicators/Built-in/heikin-ashi.js",
    "chars": 6135,
    "preview": "registerIndicator(\"heikin-ashi\", \"Heikin-Ashi(v1.01)\", function (context) {\n  var dataInputO = getDataInput(context, 0)\n"
  },
  {
    "path": "Indicators/Built-in/ichimoku.js",
    "chars": 3533,
    "preview": "registerIndicator(\n\"ichimoku\",\n\"Ichimoku Kinko Hyo(v1.0)\",\nfunction (context) {\n\t    var dataInputHigh = getDataInput(co"
  },
  {
    "path": "Indicators/Built-in/lwma.js",
    "chars": 880,
    "preview": "registerIndicator(\n    \"lwma\", \"Linear weighted moving average(v1.0)\", function (context) {\n        var dataInput = getD"
  },
  {
    "path": "Indicators/Built-in/macd.js",
    "chars": 1713,
    "preview": "registerIndicator(\n    \"macd\", \"MACD(v1.01)\", function (context) {\n        var dataInput = getDataInput(context, 0)\n\t\tva"
  },
  {
    "path": "Indicators/Built-in/mfi.js",
    "chars": 1519,
    "preview": "registerIndicator(\"mfi\", \"Market Facilitation Index(v1.01)\", function (context) {\n\t\tvar dataInputHigh = getDataInput(con"
  },
  {
    "path": "Indicators/Built-in/momentum.js",
    "chars": 854,
    "preview": "registerIndicator(\n\"momentum\",\n\"Momentum(v1.0)\",\nfunction (context) {\n\t    var dataInput = getDataInput(context, 0)\n\t   "
  },
  {
    "path": "Indicators/Built-in/rsi.js",
    "chars": 2816,
    "preview": "registerIndicator(\n    \"rsi\", \"Relative strength index(v1.01)\", function (context) {\n\t\tvar dataInput = getDataInput(cont"
  },
  {
    "path": "Indicators/Built-in/rvi.js",
    "chars": 2209,
    "preview": "registerIndicator(\n\"rvi\",\n\"Relative Vigor Index(v1.0)\",\nfunction (context) {\n\t    var dataInputOpen = getDataInput(conte"
  },
  {
    "path": "Indicators/Built-in/sar.js",
    "chars": 2971,
    "preview": "registerIndicator(\n\"sar\",\n\"Parabolic SAR(v1.01)\",\nfunction (context) {\n\t\tvar dataInputHigh = getDataInput(context, 0)\n\t\t"
  },
  {
    "path": "Indicators/Built-in/sma.js",
    "chars": 857,
    "preview": "registerIndicator(\n\t\"sma\", \"Simple moving average(v1.0)\", function (context) {\n\t\tvar dataInput = getDataInput(context, 0"
  },
  {
    "path": "Indicators/Built-in/smma.js",
    "chars": 873,
    "preview": "registerIndicator(\n    \"smma\", \"Smoothed moving average(v1.0)\", function (context) {\n        var dataInput = getDataInpu"
  },
  {
    "path": "Indicators/Built-in/stochastic.js",
    "chars": 3177,
    "preview": "registerIndicator(\n    \"stochastic\", \"Stochastic oscillator(v1.01)\", function (context) {\n\t\tvar dataInputClose = getData"
  },
  {
    "path": "Indicators/Built-in/volume.js",
    "chars": 544,
    "preview": "registerIndicator(\"volume\", \"Volume of OHLC(v1.0)\", function (context) {\n\t\tvar dataInput = getDataInput(context, 0)\n\t\tva"
  },
  {
    "path": "Indicators/Built-in/wpr.js",
    "chars": 2167,
    "preview": "registerIndicator(\n\"wpr\",\n\"Williams' Percent Range(v1.0)\",\nfunction (context) {\n\t    var dataInputClose = getDataInput(c"
  },
  {
    "path": "Indicators/Built-in/zigzag.js",
    "chars": 5962,
    "preview": "registerIndicator(\"zigzag\", \"ZigZag based on SAR(v1.03)\", function (context) {\n  var dataInputHigh = getDataInput(contex"
  },
  {
    "path": "Indicators/Oldie/README.md",
    "chars": 42,
    "preview": "This folder contains deprecated programs.\n"
  },
  {
    "path": "Indicators/Oldie/README.txt",
    "chars": 42,
    "preview": "This folder contains deprecated programs.\n"
  },
  {
    "path": "Indicators/Oldie/fintechee_oanda_loader.js",
    "chars": 13373,
    "preview": "registerIndicator(\"fintechee_oanda_loader\", \"A plugin to load Oanda's streaming quotes and transactions(v1.11)\", functio"
  },
  {
    "path": "Indicators/Oldie/line_segment_sample.js",
    "chars": 6264,
    "preview": "// This is just an example to implement chart elements by using custom indicator.\nregisterIndicator(\"line_segment_sample"
  },
  {
    "path": "Indicators/Plugin-for-Data-API/crypto_loader.js",
    "chars": 7834,
    "preview": "registerIndicator(\"fintechee_crypto_loader\", \"A plugin to load the specific cryptocurrency's streaming quotes(v1.02)\", f"
  },
  {
    "path": "Indicators/Plugin-for-Data-API/usage.txt",
    "chars": 490,
    "preview": "This folder includes programs used for integrating with data providers, specifically crypto data providers.\n\nWe plan to "
  },
  {
    "path": "Indicators/Plugin-for-Youtube/tutorial_videos.js",
    "chars": 809,
    "preview": "registerIndicator(\"tutorial_videos\", \"Embedded tutorial videos(v1.0)\", function (context) {\n\t},[{\n\t\tname: \"url\",\n\t\tvalue"
  },
  {
    "path": "Indicators/Plugin-for-Youtube/usage.txt",
    "chars": 474,
    "preview": "This plugin is designed to enable the display of YouTube videos, including live streams, within the chart layout. This a"
  },
  {
    "path": "Indicators/atr_comparison/README.md",
    "chars": 168,
    "preview": "![Fintechee ATR comparison indicator](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/atr_com"
  },
  {
    "path": "Indicators/atr_comparison/atr_comparison.js",
    "chars": 2646,
    "preview": "registerIndicator(\n    \"atr_comparison\", \"An improved Average True Range(v1.0)\", function (context) {\n    // Please add "
  },
  {
    "path": "Indicators/atr_comparison/atr_comparison_guide.txt",
    "chars": 1117,
    "preview": "We expand ATR to an improved version that helps us compare the volatilities of different symbols at the same time in one"
  },
  {
    "path": "Indicators/atr_comparison/atr_exporter.js",
    "chars": 1794,
    "preview": "registerIndicator(\n    \"atr_exporter\", \"A tool to export the data of Average True Range to the window object(v1.01)\", fu"
  },
  {
    "path": "Indicators/barrage/barrage.js",
    "chars": 11450,
    "preview": "registerIndicator(\"barrage\", \"A plugin to display barrages on the chart(v1.03)\", function(context) {},\n  [{\n    name: \"c"
  },
  {
    "path": "Indicators/chart_elements/README.md",
    "chars": 186,
    "preview": "chart_elements.js is a plugin to manage the chart elements implemented by API for indicators.\n\ntoggle_trading_signals.js"
  },
  {
    "path": "Indicators/chart_elements/chart_elements.js",
    "chars": 19105,
    "preview": "registerIndicator(\"chart_elements\", \"A manager for the chart elements implemented by using custom indicator(v1.04)\", fun"
  },
  {
    "path": "Indicators/chart_elements/chart_elements_intro.txt",
    "chars": 488,
    "preview": "One of the key features of Fintechee is its extensibility. The platform comes equipped with built-in chart elements such"
  },
  {
    "path": "Indicators/chart_elements/toggle_signals_intro.txt",
    "chars": 111,
    "preview": "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",
    "chars": 3436,
    "preview": "\tregisterIndicator(\"toggle_trading_signals\", \"Toggle the display of the trading signals(v1.03)\", function (context) {\n\t}"
  },
  {
    "path": "Indicators/cursor/cursor.js",
    "chars": 8616,
    "preview": "registerIndicator(\"cursor\", \"Cursor on hover(v1.0)\", function (context) {\n  // Please note, this indicator will make scr"
  },
  {
    "path": "Indicators/cursor/usage.txt",
    "chars": 212,
    "preview": "\"cursor\" is an implementation to show a cursor on the chart. The function to scroll the chart conflicts with this progra"
  },
  {
    "path": "Indicators/extra_fractals/README.md",
    "chars": 167,
    "preview": "![Fintechee extra fractals indicator](https://github.com/fintechees/Expert-Advisor-Studio/raw/master/Indicators/extra_fr"
  },
  {
    "path": "Indicators/extra_fractals/extra_fractals.js",
    "chars": 7781,
    "preview": "registerIndicator(\"extra_fractals\", \"An extended Fractals(v1.01)\", function (context) {\n  var dataInputHigh = getDataInp"
  },
  {
    "path": "Indicators/extra_fractals/usage.txt",
    "chars": 397,
    "preview": "\"Fractals\" is a very useful indicator to find breakout opportunities in an active market. However, the weakness of Fract"
  },
  {
    "path": "Indicators/extra_mfi/extra_mfi.js",
    "chars": 1641,
    "preview": "registerIndicator(\"extra_mfi\", \"Market Facilitation Index Extra Version(v1.0)\", function (context) {\n  var dataInputHigh"
  },
  {
    "path": "Indicators/extra_mfi/extra_mfi_guide.txt",
    "chars": 117,
    "preview": "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",
    "chars": 3359,
    "preview": "registerIndicator(\"extra_sar\", \"Parabolic SAR(v1.0)\", function (context) {\n  var dataInputHigh = getDataInput(context, 0"
  },
  {
    "path": "Indicators/fibonacci_retracements/README.md",
    "chars": 180,
    "preview": "![Fintechee Fibonacci retracement indicator](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/"
  },
  {
    "path": "Indicators/fibonacci_retracements/fibonacci_retracements.js",
    "chars": 7874,
    "preview": "registerIndicator(\"fibonacci_retracements\", \"Fibonacci retracements viewer based on ZigZag(v1.0)\", function (context) {\n"
  },
  {
    "path": "Indicators/fibonacci_retracements/usage.txt",
    "chars": 300,
    "preview": "Fibonacci retracements are always used to identify market reversal opportunities. Traditionally, we would check for Fibo"
  },
  {
    "path": "Indicators/order_buttons/README.md",
    "chars": 102,
    "preview": "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",
    "chars": 10714,
    "preview": "registerIndicator(\"order_buttons\", \"A chart widget with the buttons to send market orders(v1.0)\", function (context) {\n}"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/equity_curve.js",
    "chars": 2709,
    "preview": "registerIndicator(\"equity_curve\", \"An indicator to show the equity and the balance of an account(v1.02)\", function (cont"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/equity_curve_viewer.js",
    "chars": 2374,
    "preview": "registerEA(\n  \"equity_curve_viewer\",\n  \"An EA used for watching the information about the equity and the balance of an a"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/how_to_use_equity_curve_unrealized_pl.txt",
    "chars": 1402,
    "preview": "Almost all the indicators' charts are based on candlesticks or another indicator's output.\nWe can use almost all the ind"
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/unrealized_pl.js",
    "chars": 3241,
    "preview": "registerIndicator(\"unrealized_pl\", \"An indicator to show the unrealized PL of an account(v1.05)\", function (context) {\n "
  },
  {
    "path": "Indicators/unrealized_pl_and_equity_curve/unrealized_pl_viewer.js",
    "chars": 3316,
    "preview": "registerEA(\n  \"unrealized_pl_viewer\",\n  \"An EA used for watching the information about the unrealized PL of an account(v"
  },
  {
    "path": "LICENSE",
    "chars": 1201,
    "preview": "Fintechee License = MIT License + Restrictions for Racists\n\nCopyright (c) 2022 Fintechee\n\nPermission is hereby granted, "
  },
  {
    "path": "README.md",
    "chars": 21218,
    "preview": "> ## Anti-Racism Announcement!\n> ### WE ABSOLUTELY DISALLOW PROVIDING OUR SERVICE/PRODUCT/WHITE-LABEL TO ANY RACIST OR R"
  },
  {
    "path": "screenshot/README.md",
    "chars": 2,
    "preview": "\n\n"
  },
  {
    "path": "simple_manual.txt",
    "chars": 3737,
    "preview": "1. Supported Programming Languages\nFintechee supports JS/C/C++/MQL programming languages.\n\nJS codes can be run straightf"
  }
]

About this extraction

This page contains the full source code of the fintechees/Expert-Advisor-Studio GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 143 files (838.4 KB), approximately 238.2k tokens, and a symbol index with 662 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!