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 = '
' + '
' + '
' + // '
List
' + '
Load
' + '
Save
' + '
' + '
' + '
' + '' + '
' + '
' + '
' + '
' + '' + '
' + '
' + '
' var arbitragePricesPanel = '' $("#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 '

' + data + '

' } else { return '

' + data + '

' } } }, { title: "Ext-Fintechee", render: function (data, type, row) { if (data > 0) { return '

' + data + '

' } else { return '

' + data + '

' } } }, { 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: '' + '' + '' } ] }) 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 = '
' + '
' + '
' + // '
List
' + '
Load
' + '
Save
' + '
' + '
' + '
' + '' + '
' + '
' + '
' + '
' + '' + '
' + '
' + '
' var arbitragePricesPanel = '' $("#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 '

' + data + '

' } else { return '

' + data + '

' } } }, {title: "Oanda-FIX", render: function (data, type, row) { if (data > 0) { return '

' + data + '

' } else { return '

' + data + '

' } } }, {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: '' + '' + '' } ] }) 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 += '
' + expirations[i].optionName2 + '
' } $("#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 = '' $("#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 '

' + data + '

' } else if (row[5] > 0) { return '

' + data + '

' } else { return '

' + data + '

' } } }, {title: "Ask(C)", render: function (data, type, row) { if (row[6] == 0) { return '

' + data + '

' } else if (row[6] > 0) { return '

' + data + '

' } else { return '

' + data + '

' } } }, {title: "Strike Price"}, {title: "Bid(P)", render: function (data, type, row) { if (row[7] == 0) { return '

' + data + '

' } else if (row[7] > 0) { return '

' + data + '

' } else { return '

' + data + '

' } } }, {title: "Ask(P)", render: function (data, type, row) { if (row[8] == 0) { return '

' + data + '

' } else if (row[8] > 0) { return '

' + data + '

' } else { return '

' + data + '

' } } }, {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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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; } else { return -1; } } int ArrayResize (long** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (long)); long* newArr = (long*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (float** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (float)); float* newArr = (float*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (double** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (double)); double* newArr = (double*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (bool** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (bool)); bool* newArr = (bool*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (char** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (short** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (int** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (long** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (float** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (double** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (bool** array, int new_size) { return ArrayResize(array, new_size, 0); } bool ArraySort (char* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (short* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (int* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (long* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (float* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (double* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } int ArrayBsearch (const char* array, char value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const short* array, short value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const int* array, int value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const long* array, long value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const float* array, float value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const double* array, double value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } struct Parameter { char paramType; int paramInt; double paramDouble; bool paramBool; string paramString; }; struct GlobalVar { datetime time; double value; }; struct ParamHandleItem { bool bInit = true; vector paramList; map handleList; map globalVarList; }; map paramHandleList; int iFintecheeUID; int Bars; double Ask; double Bid; double Point; int Digits; int OnInit (void); void OnDeinit (const int); void OnTick (void); void setParam (int uid, const struct Parameter & parameter) { if (paramHandleList.find(uid) != paramHandleList.end()) { paramHandleList[uid].paramList.push_back(parameter); } else { struct ParamHandleItem item; item.paramList.push_back(parameter); paramHandleList[uid] = item; } } datetime setGlobalVar (int uid, const string name, double value) { struct GlobalVar globalVar; globalVar.time = TimeCurrent(); if (paramHandleList.find(uid) != paramHandleList.end()) { datetime time = paramHandleList[uid].globalVarList.count(name) > 0 ? paramHandleList[uid].globalVarList[name].time : globalVar.time; paramHandleList[uid].globalVarList[name] = globalVar; return time; } else { struct ParamHandleItem item; item.globalVarList[name] = globalVar; paramHandleList[uid] = item; return globalVar.time; } } bool checkGlobalVar (int uid, const string name) { if (paramHandleList.find(uid) != paramHandleList.end()) { return paramHandleList[uid].globalVarList.count(name) > 0; } else { return false; } } double getGlobalVar (int uid, const string name) { if (paramHandleList.find(uid) != paramHandleList.end()) { return paramHandleList[uid].globalVarList.count(name) > 0 ? paramHandleList[uid].globalVarList[name].value : 0; } else { return 0; } } bool delGlobalVar (int uid, const string name) { if (paramHandleList.find(uid) != paramHandleList.end()) { if (paramHandleList[uid].globalVarList.count(name) > 0) { paramHandleList[uid].globalVarList.erase(name); return true; } else { return false; } } else { return false; } } extern "C" { EMSCRIPTEN_KEEPALIVE void setParamInt (int uid, int param) { struct Parameter parameter; parameter.paramType = 'i'; parameter.paramInt = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setParamDouble (int uid, double param) { struct Parameter parameter; parameter.paramType = 'd'; parameter.paramDouble = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setParamBool (int uid, bool param) { struct Parameter parameter; parameter.paramType = 'b'; parameter.paramBool = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setParamString (int uid, const char* param) { struct Parameter parameter; parameter.paramType = 's'; parameter.paramString = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setjPrint (void (*f) (int, const char*)) { jPrint = f; } EMSCRIPTEN_KEEPALIVE void setjChartClose (long (*f) (int, long)) { jChartClose = f; } EMSCRIPTEN_KEEPALIVE void setjChartID (long (*f) (int)) { jChartID = f; } EMSCRIPTEN_KEEPALIVE void setjChartOpen (long (*f) (int, const char*, const char*)) { jChartOpen = f; } EMSCRIPTEN_KEEPALIVE void setjChartPeriod (int (*f) (int, long)) { jChartPeriod = f; } EMSCRIPTEN_KEEPALIVE void setjChartSymbol (const char* (*f) (int, long)) { jChartSymbol = f; } EMSCRIPTEN_KEEPALIVE void setjPeriod (int (*f) (int)) { jPeriod = f; } EMSCRIPTEN_KEEPALIVE void setjSymbol (const char* (*f) (int)) { jSymbol = f; } EMSCRIPTEN_KEEPALIVE void setjAccountBalance (double (*f) (int)) { jAccountBalance = f; } EMSCRIPTEN_KEEPALIVE void setjAccountCompany (const char* (*f) (int)) { jAccountCompany = f; } EMSCRIPTEN_KEEPALIVE void setjAccountCurrency (const char* (*f) (int)) { jAccountCurrency = f; } EMSCRIPTEN_KEEPALIVE void setjAccountEquity (double (*f) (int)) { jAccountEquity = f; } EMSCRIPTEN_KEEPALIVE void setjAccountFreeMargin (double (*f) (int)) { jAccountFreeMargin = f; } EMSCRIPTEN_KEEPALIVE void setjAccountMargin (double (*f) (int)) { jAccountMargin = f; } EMSCRIPTEN_KEEPALIVE void setjAccountProfit (double (*f) (int)) { jAccountProfit = f; } EMSCRIPTEN_KEEPALIVE void setjOrdersTotal (int (*f) (int)) { jOrdersTotal = f; } EMSCRIPTEN_KEEPALIVE void setjOrdersHistoryTotal (int (*f) (int)) { jOrdersHistoryTotal = f; } EMSCRIPTEN_KEEPALIVE void setjOrderSelect (int (*f) (int, int, int, int)) { jOrderSelect = f; } EMSCRIPTEN_KEEPALIVE void setjOrderOpenPrice (double (*f) (int)) { jOrderOpenPrice = f; } EMSCRIPTEN_KEEPALIVE void setjOrderType (int (*f) (int)) { jOrderType = f; } EMSCRIPTEN_KEEPALIVE void setjOrderTakeProfit (double (*f) (int)) { jOrderTakeProfit = f; } EMSCRIPTEN_KEEPALIVE void setjOrderStopLoss (double (*f) (int)) { jOrderStopLoss = f; } EMSCRIPTEN_KEEPALIVE void setjOrderLots (double (*f) (int)) { jOrderLots = f; } EMSCRIPTEN_KEEPALIVE void setjOrderProfit (double (*f) (int)) { jOrderProfit = f; } EMSCRIPTEN_KEEPALIVE void setjOrderSymbol (const char* (*f) (int)) { jOrderSymbol = f; } EMSCRIPTEN_KEEPALIVE void setjOrderTicket (int (*f) (int)) { jOrderTicket = f; } EMSCRIPTEN_KEEPALIVE void setjOrderMagicNumber (int (*f) (int)) { jOrderMagicNumber = f; } EMSCRIPTEN_KEEPALIVE void setjOrderOpenTime (datetime (*f) (int)) { jOrderOpenTime = f; } EMSCRIPTEN_KEEPALIVE void setjOrderComment (const char* (*f) (int)) { jOrderComment = f; } EMSCRIPTEN_KEEPALIVE void setjOrderExpiration (datetime (*f) (int)) { jOrderExpiration = f; } EMSCRIPTEN_KEEPALIVE void setjOrderPrint (void (*f) (int)) { jOrderPrint = f; } EMSCRIPTEN_KEEPALIVE void setjiTimeInit (int (*f) (int, const char*, const char*)) { jiTimeInit = f; } EMSCRIPTEN_KEEPALIVE void setjiTime (datetime (*f) (int, int, int)) { jiTime = f; } EMSCRIPTEN_KEEPALIVE void setjiOpenInit (int (*f) (int, const char*, const char*)) { jiOpenInit = f; } EMSCRIPTEN_KEEPALIVE void setjiOpen (double (*f) (int, int, int)) { jiOpen = f; } EMSCRIPTEN_KEEPALIVE void setjiHighInit (int (*f) (int, const char*, const char*)) { jiHighInit = f; } EMSCRIPTEN_KEEPALIVE void setjiHigh (double (*f) (int, int, int)) { jiHigh = f; } EMSCRIPTEN_KEEPALIVE void setjiLowInit (int (*f) (int, const char*, const char*)) { jiLowInit = f; } EMSCRIPTEN_KEEPALIVE void setjiLow (double (*f) (int, int, int)) { jiLow = f; } EMSCRIPTEN_KEEPALIVE void setjiCloseInit (int (*f) (int, const char*, const char*)) { jiCloseInit = f; } EMSCRIPTEN_KEEPALIVE void setjiClose (double (*f) (int, int, int)) { jiClose = f; } EMSCRIPTEN_KEEPALIVE void setjiVolumeInit (int (*f) (int, const char*, const char*)) { jiVolumeInit = f; } EMSCRIPTEN_KEEPALIVE void setjiVolume (long (*f) (int, int, int)) { jiVolume = f; } EMSCRIPTEN_KEEPALIVE void setjiHighest (int (*f) (int, int, const char*, int, int)) { jiHighest = f; } EMSCRIPTEN_KEEPALIVE void setjiLowest (int (*f) (int, int, const char*, int, int)) { jiLowest = f; } EMSCRIPTEN_KEEPALIVE void setjiACInit (int (*f) (int, const char*, const char*)) { jiACInit = f; } EMSCRIPTEN_KEEPALIVE void setjiAC (double (*f) (int, int, int)) { jiAC = f; } EMSCRIPTEN_KEEPALIVE void setjiADXInit (int (*f) (int, const char*, const char*, int, int)) { jiADXInit = f; } EMSCRIPTEN_KEEPALIVE void setjiADX (double (*f) (int, int, const char*, int)) { jiADX = f; } EMSCRIPTEN_KEEPALIVE void setjiAlligatorInit (int (*f) (int, const char*, const char*, int, int, int, int, int, int, const char*, int)) { jiAlligatorInit = f; } EMSCRIPTEN_KEEPALIVE void setjiAlligator (double (*f) (int, int, int, int, int, const char*, int)) { jiAlligator = f; } EMSCRIPTEN_KEEPALIVE void setjiAOInit (int (*f) (int, const char*, const char*)) { jiAOInit = f; } EMSCRIPTEN_KEEPALIVE void setjiAO (double (*f) (int, int, int)) { jiAO = f; } EMSCRIPTEN_KEEPALIVE void setjiATRInit (int (*f) (int, const char*, const char*, int)) { jiATRInit = f; } EMSCRIPTEN_KEEPALIVE void setjiATR (double (*f) (int, int, int)) { jiATR = f; } EMSCRIPTEN_KEEPALIVE void setjiBearsPowerInit (int (*f) (int, const char*, const char*, int, int)) { jiBearsPowerInit = f; } EMSCRIPTEN_KEEPALIVE void setjiBearsPower (double (*f) (int, int, int)) { jiBearsPower = f; } EMSCRIPTEN_KEEPALIVE void setjiBandsInit (int (*f) (int, const char*, const char*, int, double, int, int)) { jiBandsInit = f; } EMSCRIPTEN_KEEPALIVE void setjiBands (double (*f) (int, int, int, const char*, int)) { jiBands = f; } EMSCRIPTEN_KEEPALIVE void setjiBandsOnArray (double (*f) (int, double*, int, int, double, int, const char*, int)) { jiBandsOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiBullsPowerInit (int (*f) (int, const char*, const char*, int, int)) { jiBullsPowerInit = f; } EMSCRIPTEN_KEEPALIVE void setjiBullsPower (double (*f) (int, int, int)) { jiBullsPower = f; } EMSCRIPTEN_KEEPALIVE void setjiCCIInit (int (*f) (int, const char*, const char*, int, int)) { jiCCIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiCCI (double (*f) (int, int, int)) { jiCCI = f; } EMSCRIPTEN_KEEPALIVE void setjiCCIOnArray (double (*f) (int, double*, int, int, int)) { jiCCIOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiCustomInit (int (*f) (int, const char*, const char*, const char*, const char*)) { jiCustomInit = f; } EMSCRIPTEN_KEEPALIVE void setjiCustom (double (*f) (int, int, const char*, int)) { jiCustom = f; } EMSCRIPTEN_KEEPALIVE void setjiDeMarkerInit (int (*f) (int, const char*, const char*, int)) { jiDeMarkerInit = f; } EMSCRIPTEN_KEEPALIVE void setjiDeMarker (double (*f) (int, int, int)) { jiDeMarker = f; } EMSCRIPTEN_KEEPALIVE void setjiEnvelopesInit (int (*f) (int, const char*, const char*, int, const char*, int, int, double)) { jiEnvelopesInit = f; } EMSCRIPTEN_KEEPALIVE void setjiEnvelopes (double (*f) (int, int, int, const char*, int)) { jiEnvelopes = f; } EMSCRIPTEN_KEEPALIVE void setjiEnvelopesOnArray (double (*f) (int, double*, int, int, const char*, int, double, const char*, int)) { jiEnvelopesOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiFractalsInit (int (*f) (int, const char*, const char*)) { jiFractalsInit = f; } EMSCRIPTEN_KEEPALIVE void setjiFractals (double (*f) (int, int, const char*, int)) { jiFractals = f; } EMSCRIPTEN_KEEPALIVE void setjiIchimokuInit (int (*f) (int, const char*, const char*, int, int, int)) { jiIchimokuInit = f; } EMSCRIPTEN_KEEPALIVE void setjiIchimoku (double (*f) (int, int, int, const char*, int)) { jiIchimoku = f; } EMSCRIPTEN_KEEPALIVE void setjiMAInit (int (*f) (int, const char*, const char*, int, int, int, int)) { jiMAInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMA (double (*f) (int, int, int, const char*, int)) { jiMA = f; } EMSCRIPTEN_KEEPALIVE void setjiMAOnArray (double (*f) (int, double*, int, int, int, const char*, int)) { jiMAOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiMACDInit (int (*f) (int, const char*, const char*, int, int, int, int)) { jiMACDInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMACD (double (*f) (int, int, const char*, int)) { jiMACD = f; } EMSCRIPTEN_KEEPALIVE void setjiMFIInit (int (*f) (int, const char*, const char*, int)) { jiMFIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMFI (double (*f) (int, int, int)) { jiMFI = f; } EMSCRIPTEN_KEEPALIVE void setjiMomentumInit (int (*f) (int, const char*, const char*, int, int)) { jiMomentumInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMomentum (double (*f) (int, int, int)) { jiMomentum = f; } EMSCRIPTEN_KEEPALIVE void setjiMomentumOnArray (double (*f) (int, double*, int, int, int)) { jiMomentumOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiRSIInit (int (*f) (int, const char*, const char*, int, int)) { jiRSIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiRSI (double (*f) (int, int, int)) { jiRSI = f; } EMSCRIPTEN_KEEPALIVE void setjiRSIOnArray (double (*f) (int, double*, int, int, int)) { jiRSIOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiRVIInit (int (*f) (int, const char*, const char*, int)) { jiRVIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiRVI (double (*f) (int, int, const char*, int)) { jiRVI = f; } EMSCRIPTEN_KEEPALIVE void setjiSARInit (int (*f) (int, const char*, const char*, double, double)) { jiSARInit = f; } EMSCRIPTEN_KEEPALIVE void setjiSAR (double (*f) (int, int, int)) { jiSAR = f; } EMSCRIPTEN_KEEPALIVE void setjiStochasticInit (int (*f) (int, const char*, const char*, int, int, int, const char*)) { jiStochasticInit = f; } EMSCRIPTEN_KEEPALIVE void setjiStochastic (double (*f) (int, int, const char*, int)) { jiStochastic = f; } EMSCRIPTEN_KEEPALIVE void setjiWPRInit (int (*f) (int, const char*, const char*, int)) { jiWPRInit = f; } EMSCRIPTEN_KEEPALIVE void setjiWPR (double (*f) (int, int, int)) { jiWPR = f; } EMSCRIPTEN_KEEPALIVE void setjObjectCreate (int (*f) (int, long, const char*, int, datetime, double, datetime, double)) { jObjectCreate = f; } EMSCRIPTEN_KEEPALIVE void setjObjectDelete (int (*f) (int, const char*)) { jObjectDelete = f; } EMSCRIPTEN_KEEPALIVE void setjObjectGet (double (*f) (int, const char*, int)) { jObjectGet = f; } EMSCRIPTEN_KEEPALIVE void setjObjectSet (int (*f) (int, const char*, int, double)) { jObjectSet = f; } EMSCRIPTEN_KEEPALIVE void setjIsTesting (int (*f) ()) { jIsTesting = f; } EMSCRIPTEN_KEEPALIVE void setjMarketInfo (double (*f) (int, const char*, int)) { jMarketInfo = f; } EMSCRIPTEN_KEEPALIVE void setjCreateNeuralNetwork (int (*f) (int, const char*, const char*)) { jCreateNeuralNetwork = f; } EMSCRIPTEN_KEEPALIVE void setjActivateNeuralNetwork (double (*f) (int, const char*, double*, int)) { jActivateNeuralNetwork = f; } } bool ChartClose (long chart_id) { if (paramHandleList[iFintecheeUID].bInit) return false; long id = jChartClose(iFintecheeUID, chart_id); if (id != -1) { for (auto const& [key, val] : paramHandleList[iFintecheeUID].handleList) { if (val == id) { paramHandleList[iFintecheeUID].handleList.erase(key); return true; } } } return false; } bool ChartClose () { return ChartClose(0); } long ChartID () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jChartID(iFintecheeUID); } long ChartOpen (const string symbol, int timeframe) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jChartOpen(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return handle; } else { return 0; } } long ChartOpen (long symbol, int timeframe) { return ChartOpen("", timeframe); } ENUM_TIMEFRAMES ChartPeriod (long chart_id) { if (paramHandleList[iFintecheeUID].bInit) return PERIOD_CURRENT; return (ENUM_TIMEFRAMES)jChartPeriod(iFintecheeUID, chart_id); } ENUM_TIMEFRAMES ChartPeriod () { return ChartPeriod(0); } string ChartSymbol (long chart_id) { if (paramHandleList[iFintecheeUID].bInit) return ""; string symbol(jChartSymbol(iFintecheeUID, chart_id)); return symbol; } string ChartSymbol () { return ChartSymbol(0); } ENUM_TIMEFRAMES Period () { return (ENUM_TIMEFRAMES)jPeriod(iFintecheeUID); } string Symbol () { string symbol(jSymbol(iFintecheeUID)); return symbol; } double AccountBalance () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jAccountBalance(iFintecheeUID); } string AccountCompany () { if (paramHandleList[iFintecheeUID].bInit) return ""; string company(jAccountCompany(iFintecheeUID)); return company; } string AccountCurrency () { if (paramHandleList[iFintecheeUID].bInit) return ""; string currency(jAccountCurrency(iFintecheeUID)); return currency; } double AccountEquity () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jAccountEquity(iFintecheeUID); } double AccountFreeMargin () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jAccountFreeMargin(iFintecheeUID); } double AccountMargin () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jAccountMargin(iFintecheeUID); } double AccountProfit () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jAccountProfit(iFintecheeUID); } int OrdersTotal () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrdersTotal(iFintecheeUID); } int OrdersHistoryTotal () { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrdersHistoryTotal(iFintecheeUID); } int HistoryTotal () { return OrdersHistoryTotal(); } bool OrderSelect(int index, int select, int pool) { if (paramHandleList[iFintecheeUID].bInit) return false; return jOrderSelect(iFintecheeUID, index, select, pool) == 1; } bool OrderSelect(int index, int select) { return OrderSelect(index, select, MODE_TRADES) == 1; } double OrderOpenPrice() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderOpenPrice(iFintecheeUID); } int OrderType() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderType(iFintecheeUID); } double OrderTakeProfit() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderTakeProfit(iFintecheeUID); } double OrderStopLoss() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderStopLoss(iFintecheeUID); } double OrderLots() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderLots(iFintecheeUID); } double OrderProfit() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderProfit(iFintecheeUID); } string OrderSymbol() { if (paramHandleList[iFintecheeUID].bInit) return ""; string symbol(jOrderSymbol(iFintecheeUID)); return symbol; } int OrderTicket() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderTicket(iFintecheeUID); } int OrderMagicNumber() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderMagicNumber(iFintecheeUID); } datetime OrderOpenTime() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderOpenTime(iFintecheeUID); } string OrderComment() { if (paramHandleList[iFintecheeUID].bInit) return ""; string comment(jOrderComment(iFintecheeUID)); return comment; } datetime OrderExpiration() { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderExpiration(iFintecheeUID); } void OrderPrint() { if (paramHandleList[iFintecheeUID].bInit) return; jOrderPrint(iFintecheeUID); } template void Print (const Type & arg, const Types &... args) { stringstream s; s << arg; ((s << args), ..., (s << endl)); jPrint(iFintecheeUID, s.str().c_str()); } // todo template void Comment (const Type & arg, const Types &... args) { stringstream s; s << arg; ((s << args), ..., (s << endl)); jPrint(iFintecheeUID, s.str().c_str()); } // todo template void Alert (const Type & arg, const Types &... args) { stringstream s; s << arg; ((s << args), ..., (s << endl)); jPrint(iFintecheeUID, s.str().c_str()); } bool PlaySound (const string name) { Print("Playing: ", name); return true; } datetime iTime (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiTime(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } datetime iTime (long symbol, int timeframe, int shift) { return iTime("", timeframe, shift); } double iOpen (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiOpenInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiOpen(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iOpen (long symbol, int timeframe, int shift) { return iOpen("", timeframe, shift); } double iHigh (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiHighInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiHigh(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iHigh (long symbol, int timeframe, int shift) { return iHigh("", timeframe, shift); } double iLow (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiLowInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiLow(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iLow (long symbol, int timeframe, int shift) { return iLow("", timeframe, shift); } double iClose (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiCloseInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiClose(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iClose (long symbol, int timeframe, int shift) { return iClose("", timeframe, shift); } long iVolume (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiVolumeInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiVolume(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } long iVolume (long symbol, int timeframe, int shift) { return iVolume("", timeframe, shift); } int iHighest (const string symbol, int timeframe, int type, int count, int start) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiHighest(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start); } } int iHighest (long symbol, int timeframe, int type, int count, int start) { return iHighest("", timeframe, type, count, start); } int Highest (const string symbol, int timeframe, int type, int count, int start) { return iHighest (symbol, timeframe, type, count, start); } int Highest (long symbol, int timeframe, int type, int count, int start) { return iHighest("", timeframe, type, count, start); } int iLowest (const string symbol, int timeframe, int type, int count, int start) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiLowest(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start); } } int iLowest (long symbol, int timeframe, int type, int count, int start) { return iLowest("", timeframe, type, count, start); } int Lowest (const string symbol, int timeframe, int type, int count, int start) { return iLowest (symbol, timeframe, type, count, start); } int Lowest (long symbol, int timeframe, int type, int count, int start) { return iLowest("", timeframe, type, count, start); } double iAC (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iAC_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiACInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiAC(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iAC (long symbol, int timeframe, int shift) { return iAC("", timeframe, shift); } double iADX (const string symbol, int timeframe, int period, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iADX_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiADXInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiADX(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_ADX), shift); } } double iADX (long symbol, int timeframe, int period, int applied_price, int mode, int shift) { return iADX("", timeframe, period, applied_price, mode, shift); } double iAlligator ( const string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iAlligator_") + symbol + string("_") + string(tf) + string("_") + to_string(jaw_period) + string("_") + to_string(jaw_shift) + string("_") + to_string(teeth_period) + string("_") + to_string(teeth_shift) + string("_") + to_string(lips_period) + string("_") + to_string(lips_shift) + string("_") + to_string(ma_method) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiAlligatorInit(iFintecheeUID, symbol.c_str(), tf, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, convertMAMethod(ma_method), applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiAlligator(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], jaw_shift, teeth_shift, lips_shift, convertMode(mode, INDI_ALLIGATOR), shift); } } double iAlligator ( long symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price, int mode, int shift) { return iAlligator("", timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price, mode, shift); } double iAO (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iAO_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiAOInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiAO(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iAO (long symbol, int timeframe, int shift) { return iAO("", timeframe, shift); } double iATR (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iATR_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiATRInit(iFintecheeUID, symbol.c_str(), tf, period); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiATR(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iATR (long symbol, int timeframe, int period, int shift) { return iATR("", timeframe, period, shift); } double iBearsPower (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iBearsPower_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiBearsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiBearsPower(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iBearsPower (long symbol, int timeframe, int period, int applied_price, int shift) { return iBearsPower("", timeframe, period, applied_price, shift); } double iBands (const string symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iBands_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(deviation) + string("_") + to_string(bands_shift) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiBandsInit(iFintecheeUID, symbol.c_str(), tf, period, deviation, bands_shift, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiBands(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], bands_shift, convertMode(mode, INDI_BANDS), shift); } } double iBands (long symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) { return iBands("", timeframe, period, deviation, bands_shift, applied_price, mode, shift); } double iBandsOnArray (double* array, int total, int period, double deviation, int bands_shift, int mode, int shift) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jiBandsOnArray(iFintecheeUID, array, total, period, deviation, bands_shift, convertMode(mode, INDI_BANDS), shift); } double iBullsPower (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iBullsPower_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiBullsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiBullsPower(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iBullsPower (long symbol, int timeframe, int period, int applied_price, int shift) { return iBullsPower("", timeframe, period, applied_price, shift); } double iCCI (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iCCI_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiCCIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiCCI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iCCI (long symbol, int timeframe, int period, int applied_price, int shift) { return iCCI("", timeframe, period, applied_price, shift); } double iCCIOnArray (double* array, int total, int period, int shift) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jiCCIOnArray(iFintecheeUID, array, total, period, shift); } template double iCustom (const string symbol, int timeframe, const string name, Ts&&... args) { const char* tf = convertTimeFrame(timeframe); stringstream s; const char* mode; int shift; int length = sizeof...(args); int i = 0; auto loop = [&] (auto && input) { if (i >= 0 && i < length - 2) { s << input << "|||"; } else if (i == length - 2) { mode = (const char*)input; } else if (i == length - 1) { shift = (int)input; } i++; }; (loop(args), ...); string strID = string("iCustom_") + symbol + string("_") + string(tf) + string("_") + name + string("_") + s.str(); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiCustomInit(iFintecheeUID, symbol.c_str(), tf, name.c_str(), s.str().c_str()); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiCustom(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], mode, shift); } } template double iCustom (long symbol, int timeframe, const string name, Ts&&... args) { return iCustom("", timeframe, name, args...); } double iDeMarker (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iDeMarker_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiDeMarkerInit(iFintecheeUID, symbol.c_str(), tf, period); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiDeMarker(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iDeMarker (long symbol, int timeframe, int period, int shift) { return iDeMarker("", timeframe, period, shift); } double iEnvelopes (const string symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iEnvelopes_") + symbol + string("_") + string(tf) + string("_") + to_string(ma_period) + string("_") + to_string(ma_method) + string("_") + to_string(ma_shift) + string("_") + to_string(applied_price) + string("_") + to_string(deviation); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiEnvelopesInit(iFintecheeUID, symbol.c_str(), tf, ma_period, convertMAMethod(ma_method), ma_shift, applied_price, deviation); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiEnvelopes(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], ma_shift, convertMode(mode, INDI_ENVELOPES), shift); } } double iEnvelopes (long symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) { return iEnvelopes("", timeframe, ma_period, ma_method, ma_shift, applied_price, deviation, mode, shift); } double iEnvelopesOnArray (double* array, int total, int ma_period, int ma_method, int ma_shift, double deviation, int mode, int shift) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jiEnvelopesOnArray(iFintecheeUID, array, total, ma_period, convertMAMethod(ma_method), ma_shift, deviation, convertMode(mode, INDI_ENVELOPES), shift); } double iFractals (const string symbol, int timeframe, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iFractals_") + symbol + string("_") + string(tf); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiFractalsInit(iFintecheeUID, symbol.c_str(), tf); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiFractals(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_FRACTALS), shift); } } double iFractals (long symbol, int timeframe, int mode, int shift) { return iFractals("", timeframe, mode, shift); } double iIchimoku (const string symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iIchimoku_") + symbol + string("_") + string(tf) + string("_") + to_string(tenkan_sen) + string("_") + to_string(kijun_sen) + string("_") + to_string(senkou_span_b); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiIchimokuInit(iFintecheeUID, symbol.c_str(), tf, tenkan_sen, kijun_sen, senkou_span_b); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { if (mode == MODE_TENKANSEN) { return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift); } else if (mode == MODE_KIJUNSEN) { return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift); } else if (mode == MODE_SENKOUSPANA) { return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift); } else if (mode == MODE_SENKOUSPANB) { return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift); } else { return jiIchimoku(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], -kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift); } } } double iIchimoku (long symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) { return iIchimoku("", timeframe, tenkan_sen, kijun_sen, senkou_span_b, mode, shift); } double iMA (const string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMA_") + symbol + string("_") + string(tf) + string("_") + to_string(ma_period) + string("_") + to_string(ma_shift) + string("_") + to_string(ma_method) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiMAInit(iFintecheeUID, symbol.c_str(), tf, ma_period, ma_shift, ma_method, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiMA(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], ma_shift, convertMAMethod(ma_method), shift); } } double iMA (long symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) { return iMA("", timeframe, ma_period, ma_shift, ma_method, applied_price, shift); } double iMAOnArray (double* array, int total, int ma_period, int ma_shift, int ma_method, int shift) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jiMAOnArray(iFintecheeUID, array, total, ma_period, ma_shift, convertMAMethod(ma_method), shift); } double iMACD (const string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMACD_") + symbol + string("_") + string(tf) + string("_") + to_string(fast_ema_period) + string("_") + to_string(slow_ema_period) + string("_") + to_string(signal_period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiMACDInit(iFintecheeUID, symbol.c_str(), tf, fast_ema_period, slow_ema_period, signal_period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiMACD(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_MACD), shift); } } double iMACD (long symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) { return iMACD("", timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, mode, shift); } double iMFI (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMFI_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiMFIInit(iFintecheeUID, symbol.c_str(), tf, period); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiMFI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iMFI (long symbol, int timeframe, int period, int shift) { return iMFI("", timeframe, period, shift); } double iMomentum (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMomentum_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiMomentumInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiMomentum(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iMomentum (long symbol, int timeframe, int period, int applied_price, int shift) { return iMomentum("", timeframe, period, applied_price, shift); } double iMomentumOnArray (double* array, int total, int period, int shift) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jiMomentumOnArray(iFintecheeUID, array, total, period, shift); } double iRSI (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iRSI_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiRSIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiRSI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iRSI (long symbol, int timeframe, int period, int applied_price, int shift) { return iRSI("", timeframe, period, applied_price, shift); } double iRSIOnArray (double* array, int total, int period, int shift) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jiRSIOnArray(iFintecheeUID, array, total, period, shift); } double iRVI (const string symbol, int timeframe, int period, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iRVI_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiRVIInit(iFintecheeUID, symbol.c_str(), tf, period); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiRVI(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_RVI), shift); } } double iRVI (long symbol, int timeframe, int period, int mode, int shift) { return iRVI("", timeframe, period, mode, shift); } double iSAR (const string symbol, int timeframe, double step, double maximum, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iSAR_") + symbol + string("_") + string(tf) + string("_") + to_string(step) + string("_") + to_string(maximum); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiSARInit(iFintecheeUID, symbol.c_str(), tf, step, maximum); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiSAR(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iSAR (long symbol, int timeframe, double step, double maximum, int shift) { return iSAR("", timeframe, step, maximum, shift); } double iStochastic (const string symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iStochastic_") + symbol + string("_") + string(tf) + string("_") + to_string(Kperiod) + string("_") + to_string(Dperiod) + string("_") + to_string(slowing) + string("_") + to_string(method); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiStochasticInit(iFintecheeUID, symbol.c_str(), tf, Kperiod, Dperiod, slowing, convertMAMethod(method)); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiStochastic(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_STOCHASTIC), shift); } } double iStochastic (long symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) { return iStochastic("", timeframe, Kperiod, Dperiod, slowing, method, price_field, mode, shift); } double iWPR (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iWPR_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramHandleList[iFintecheeUID].bInit) { int handle = jiWPRInit(iFintecheeUID, symbol.c_str(), tf, period); paramHandleList[iFintecheeUID].handleList[strID] = handle; return 0; } else { return jiWPR(iFintecheeUID, paramHandleList[iFintecheeUID].handleList[strID], shift); } } double iWPR (long symbol, int timeframe, int period, int shift) { return iWPR("", timeframe, period, shift); } bool ObjectCreate (long chart_id, const string object_name, ENUM_OBJECT object_type, int sub_window, datetime time, double price, datetime time2 = 0, double price2 = 0) { if (paramHandleList[iFintecheeUID].bInit) return false; if (object_type == OBJ_ARROW_CHECK || object_type == OBJ_TREND) { return jObjectCreate(iFintecheeUID, chart_id, object_name.c_str(), object_type, time, price, time2, price2) == 1; } else { return false; } } bool ObjectDelete (const string object_name) { if (paramHandleList[iFintecheeUID].bInit) return false; return jObjectDelete(iFintecheeUID, object_name.c_str()) == 1; } bool ObjectDelete (long chart_id, const string object_name) { return ObjectDelete(object_name); } double ObjectGet (const string object_name, int property_index) { if (paramHandleList[iFintecheeUID].bInit) return 0; return jObjectGet(iFintecheeUID, object_name.c_str(), property_index); } bool ObjectSet (const string object_name, int property_index, double value) { if (paramHandleList[iFintecheeUID].bInit) return false; return jObjectSet(iFintecheeUID, object_name.c_str(), property_index, value) == 1; } int OrderSend (const string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, const string comment, int magic, datetime expiration, int arrow_color) { if (paramHandleList[iFintecheeUID].bInit) return -1; return jOrderSend(iFintecheeUID, symbol.c_str(), convertCmd(cmd), volume, price, slippage, stoploss, takeprofit, comment.c_str(), magic, expiration, arrow_color); } int OrderSend (long symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, const string comment, int magic, datetime expiration, int arrow_color) { if (paramHandleList[iFintecheeUID].bInit) return -1; return OrderSend("", cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color); } bool OrderModify (int ticket, double price, double stoploss, double takeprofit, datetime expiration, int arrow_color) { if (paramHandleList[iFintecheeUID].bInit) return false; return jOrderModify (iFintecheeUID, ticket, price, stoploss, takeprofit, expiration, arrow_color) == 1; } bool OrderClose(int ticket, double lots, double price, int slippage, int arrow_color) { if (paramHandleList[iFintecheeUID].bInit) return false; return jOrderClose(iFintecheeUID, ticket, lots, price, slippage, arrow_color) == 1; } bool OrderDelete(int ticket, int arrow_color) { if (paramHandleList[iFintecheeUID].bInit) return false; return jOrderDelete(iFintecheeUID, ticket, arrow_color) == 1; } bool OrderDelete(int ticket) { return OrderDelete(ticket, CLR_NONE); } // todo, check whether the logic about the return value is the same as MQL4 datetime GlobalVariableSet (const string name, double value) { return setGlobalVar(iFintecheeUID, name, value); } bool GlobalVariableCheck (const string name) { return checkGlobalVar(iFintecheeUID, name); } double GlobalVariableGet (const string name) { return getGlobalVar(iFintecheeUID, name); } bool GlobalVariableDel (const string name) { return delGlobalVar(iFintecheeUID, name); } bool IsTesting () { return jIsTesting() == 1; } double MarketInfo (const string symbol, int type) { if (symbol == "") { if (type == MODE_BID) { return Bid; } else if (type == MODE_ASK) { return Ask; } else if (type == MODE_POINT) { return Point; } else if (type == MODE_DIGITS) { return Digits; } else { return jMarketInfo(iFintecheeUID, symbol.c_str(), type); } } else { return jMarketInfo(iFintecheeUID, symbol.c_str(), type); } } double MarketInfo (long symbol, int type) { return MarketInfo("", type); } // Not compatible with MQL // Deprecated bool SCompareL (const string str, long l) { return jSCompareL(iFintecheeUID, str.c_str(), l); } // Not compatible with MQL bool VeriSig (const string fintechee_data, const string fintechee_signature, const string fintechee_public_key, const string application_public_key) { string data = fintechee_data; string signature = fintechee_signature; string publicKey = fintechee_public_key; string appPublicKey = application_public_key; data.erase(std::remove(data.begin(), data.end(), '\n'), data.end()); signature.erase(std::remove(signature.begin(), signature.end(), '\n'), signature.end()); publicKey.erase(std::remove(publicKey.begin(), publicKey.end(), '\n'), publicKey.end()); appPublicKey.erase(std::remove(appPublicKey.begin(), appPublicKey.end(), '\n'), appPublicKey.end()); data = StringTrimLeft(StringTrimRight(data)); signature = StringTrimLeft(StringTrimRight(signature)); publicKey = StringTrimLeft(StringTrimRight(publicKey)); appPublicKey = StringTrimLeft(StringTrimRight(appPublicKey)); int dataLen = StringLen(data); int signatureLen = StringLen(signature); int publicKeyLen = StringLen(publicKey); int appPublicKeyLen = StringLen(appPublicKey); if (dataLen == 0 || signatureLen == 0 || publicKeyLen == 0 || appPublicKeyLen == 0) return false; if (publicKeyLen != appPublicKeyLen) return false; if (StringCompare(publicKey, appPublicKey) != 0) return false; bool res = jVeriSig(iFintecheeUID, data.c_str(), signature.c_str(), publicKey.c_str()); if (res) { std::vector arr; std::stringstream ss(data); string s; while (std::getline(ss, s, ',')) { arr.push_back(s); } if (0 < arr.size()) { if (std::stoll(arr[0]) >= TimeCurrent()) { return true; } } } return false; } // Not compatible with MQL // Uses Synaptic bool CreateNeuralNetwork (const string nnName, const string nnJson) { return jCreateNeuralNetwork(iFintecheeUID, nnName.c_str(), nnJson.c_str()) == 1; } // Not compatible with MQL // Uses Synaptic double ActivateNeuralNetwork (const string nnName, double* input, int inputNum) { return jActivateNeuralNetwork(iFintecheeUID, nnName.c_str(), input, inputNum); } // Not compatible with MQL // If you use neural network(Synaptic or Tensorflow), please call PreventCleanUp at the beginning of OnInit void PreventCleanUp () { jPreventCleanUp(iFintecheeUID); } // Not compatible with MQL // Uses Tensorflow bool BuildCNN (const string nnName, int inputNum, int hiddenNum) { return jBuildCNN(iFintecheeUID, nnName.c_str(), inputNum, hiddenNum); } // Not compatible with MQL // Uses Tensorflow bool TrainCNN (const string nnName, double* dataInput, double* dataOutput, long trainingSetNum, int inputNum, long iterations, int batchSize, bool bMonitor) { return jTrainCNN(iFintecheeUID, nnName.c_str(), dataInput, dataOutput, trainingSetNum, inputNum, iterations, batchSize, bMonitor); } // Not compatible with MQL // Uses Tensorflow double RunCNN (const string nnName, double* dataInput, int inputNum) { return jRunCNN(iFintecheeUID, nnName.c_str(), dataInput, inputNum); } // Not compatible with MQL // Uses Tensorflow bool SaveCNN (const string nnName) { return jSaveCNN(iFintecheeUID, nnName.c_str()); } // Not compatible with MQL // Uses Tensorflow bool LoadCNN (const string nnName) { return jLoadCNN(iFintecheeUID, nnName.c_str()); } ================================================ FILE: EA/Plugin-for-MQL/mqlindi2fintechee.h ================================================ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 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; 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 }; 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"; } } void (*jPrint) (int, const char*); void (*jSetIndexShift) (int, int, int); long (*jChartID) (int); int (*jChartPeriod) (int, long); const char* (*jChartSymbol) (int, long); int (*jPeriod) (int); const char* (*jSymbol) (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); double (*jMarketInfo) (int, const char*, int); // Deprecated EM_JS(bool, jSCompareL, (int uid, const char* str, long l), { try { var obj = window.mqlIndicatorsBuffer[uid + ""]; var UTF8ToString = window.mqlIndicators[obj.name].module.UTF8ToString; var s = UTF8ToString(str); return parseInt(s) >= l; } catch (e) { return false; } }); 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.mqlIndicatorsBuffer[uid + ""]; var UTF8ToString = window.mqlIndicators[obj.name].module.UTF8ToString; const data = UTF8ToString(fintechee_data); const signature = UTF8ToString(fintechee_signature); const public_key = UTF8ToString(fintechee_public_key); veriSig(false, 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); }) }); }); void Sleep (int milliseconds) { sleep(milliseconds / 1000); } int GetLastError () { return 0; } string ErrorDescription (int code) { return ""; } bool IsStopped () { return false; } 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; } else { return -1; } } int ArrayResize (long** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (long)); long* newArr = (long*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (float** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (float)); float* newArr = (float*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (double** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (double)); double* newArr = (double*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (bool** array, int new_size, int reserve_size) { if (new_size > 0) { int size = new_size * (sizeof (bool)); bool* newArr = (bool*)malloc(size); if (*array != NULL) { memcpy(newArr, *array, size); free(*array); } *array = newArr; return new_size; } else { return -1; } } int ArrayResize (char** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (short** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (int** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (long** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (float** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (double** array, int new_size) { return ArrayResize(array, new_size, 0); } int ArrayResize (bool** array, int new_size) { return ArrayResize(array, new_size, 0); } bool ArraySort (char* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (short* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (int* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (long* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (float* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } bool ArraySort (double* array, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { sort(array, array + count, greater()); } else { sort(array, array + count); } return true; } else { return false; } } int ArrayBsearch (const char* array, char value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const short* array, short value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const int* array, int value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const long* array, long value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const float* array, float value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } int ArrayBsearch (const double* array, double value, int count, int start, int direction) { if (count > 0) { if (direction == MODE_DESCEND) { for (int i = count - 1; i >= 0; i--) { if (array[i] <= value) { return i; } } return 0; } else { for (int i = 0; i < count; i++) { if (array[i] >= value) { return i; } } return count - 1; } } else { return -1; } } struct Parameter { char paramType; int paramInt; double paramDouble; bool paramBool; string paramString; }; struct DataInput { int length; double* buffer; }; struct DataOutput { int length; double* buffer; }; struct GlobalVar { datetime time; double value; }; struct ParamInputOutputItem { vector paramList; vector dataInputList; vector dataOutputList; map handleList; map globalVarList; }; map paramInputOutputList; int iFintecheeUID; int Bars; double Point; int Digits; void setParam (int uid, const struct Parameter & parameter) { if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { paramInputOutputList[uid].paramList.push_back(parameter); } else { struct ParamInputOutputItem item; item.paramList.push_back(parameter); paramInputOutputList[uid] = item; } } datetime setGlobalVar (int uid, const string name, double value) { struct GlobalVar globalVar; globalVar.time = TimeCurrent(); if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { datetime time = paramInputOutputList[uid].globalVarList.count(name) > 0 ? paramInputOutputList[uid].globalVarList[name].time : globalVar.time; paramInputOutputList[uid].globalVarList[name] = globalVar; return time; } else { struct ParamInputOutputItem item; item.globalVarList[name] = globalVar; paramInputOutputList[uid] = item; return globalVar.time; } } bool checkGlobalVar (int uid, const string name) { if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { return paramInputOutputList[uid].globalVarList.count(name) > 0; } else { return false; } } double getGlobalVar (int uid, const string name) { if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { return paramInputOutputList[uid].globalVarList.count(name) > 0 ? paramInputOutputList[uid].globalVarList[name].value : 0; } else { return 0; } } bool delGlobalVar (int uid, const string name) { if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { if (paramInputOutputList[uid].globalVarList.count(name) > 0) { paramInputOutputList[uid].globalVarList.erase(name); return true; } else { return false; } } else { return false; } } extern "C" { EMSCRIPTEN_KEEPALIVE void setParamInt (int uid, int param) { struct Parameter parameter; parameter.paramType = 'i'; parameter.paramInt = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setParamDouble (int uid, double param) { struct Parameter parameter; parameter.paramType = 'd'; parameter.paramDouble = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setParamBool (int uid, bool param) { struct Parameter parameter; parameter.paramType = 'b'; parameter.paramBool = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setParamString (int uid, const char* param) { struct Parameter parameter; parameter.paramType = 's'; parameter.paramString = param; setParam(uid, parameter); } EMSCRIPTEN_KEEPALIVE void setDataInput (int uid, int length, double* buffer) { struct DataInput dataInput; dataInput.length = length; dataInput.buffer = buffer; if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { paramInputOutputList[uid].dataInputList.push_back(dataInput); } else { struct ParamInputOutputItem item; item.dataInputList.push_back(dataInput); paramInputOutputList[uid] = item; } } EMSCRIPTEN_KEEPALIVE void setDataOutput (int uid, int length, double* buffer) { struct DataOutput dataOutput; dataOutput.length = length; dataOutput.buffer = buffer; if (paramInputOutputList.find(uid) != paramInputOutputList.end()) { paramInputOutputList[uid].dataOutputList.push_back(dataOutput); } else { struct ParamInputOutputItem item; item.dataOutputList.push_back(dataOutput); paramInputOutputList[uid] = item; } } EMSCRIPTEN_KEEPALIVE void setjPrint (void (*f) (int, const char*)) { jPrint = f; } EMSCRIPTEN_KEEPALIVE void setjSetIndexShift (void (*f) (int, int, int)) { jSetIndexShift = f; } EMSCRIPTEN_KEEPALIVE void setjChartID (long (*f) (int)) { jChartID = f; } EMSCRIPTEN_KEEPALIVE void setjChartPeriod (int (*f) (int, long)) { jChartPeriod = f; } EMSCRIPTEN_KEEPALIVE void setjChartSymbol (const char* (*f) (int, long)) { jChartSymbol = f; } EMSCRIPTEN_KEEPALIVE void setjPeriod (int (*f) (int)) { jPeriod = f; } EMSCRIPTEN_KEEPALIVE void setjSymbol (const char* (*f) (int)) { jSymbol = f; } EMSCRIPTEN_KEEPALIVE void setjiTimeInit (int (*f) (int, const char*, const char*)) { jiTimeInit = f; } EMSCRIPTEN_KEEPALIVE void setjiTime (datetime (*f) (int, int, int)) { jiTime = f; } EMSCRIPTEN_KEEPALIVE void setjiOpenInit (int (*f) (int, const char*, const char*)) { jiOpenInit = f; } EMSCRIPTEN_KEEPALIVE void setjiOpen (double (*f) (int, int, int)) { jiOpen = f; } EMSCRIPTEN_KEEPALIVE void setjiHighInit (int (*f) (int, const char*, const char*)) { jiHighInit = f; } EMSCRIPTEN_KEEPALIVE void setjiHigh (double (*f) (int, int, int)) { jiHigh = f; } EMSCRIPTEN_KEEPALIVE void setjiLowInit (int (*f) (int, const char*, const char*)) { jiLowInit = f; } EMSCRIPTEN_KEEPALIVE void setjiLow (double (*f) (int, int, int)) { jiLow = f; } EMSCRIPTEN_KEEPALIVE void setjiCloseInit (int (*f) (int, const char*, const char*)) { jiCloseInit = f; } EMSCRIPTEN_KEEPALIVE void setjiClose (double (*f) (int, int, int)) { jiClose = f; } EMSCRIPTEN_KEEPALIVE void setjiVolumeInit (int (*f) (int, const char*, const char*)) { jiVolumeInit = f; } EMSCRIPTEN_KEEPALIVE void setjiVolume (long (*f) (int, int, int)) { jiVolume = f; } EMSCRIPTEN_KEEPALIVE void setjiHighest (int (*f) (int, int, const char*, int, int)) { jiHighest = f; } EMSCRIPTEN_KEEPALIVE void setjiLowest (int (*f) (int, int, const char*, int, int)) { jiLowest = f; } EMSCRIPTEN_KEEPALIVE void setjiACInit (int (*f) (int, const char*, const char*)) { jiACInit = f; } EMSCRIPTEN_KEEPALIVE void setjiAC (double (*f) (int, int, int)) { jiAC = f; } EMSCRIPTEN_KEEPALIVE void setjiADXInit (int (*f) (int, const char*, const char*, int, int)) { jiADXInit = f; } EMSCRIPTEN_KEEPALIVE void setjiADX (double (*f) (int, int, const char*, int)) { jiADX = f; } EMSCRIPTEN_KEEPALIVE void setjiAlligatorInit (int (*f) (int, const char*, const char*, int, int, int, int, int, int, const char*, int)) { jiAlligatorInit = f; } EMSCRIPTEN_KEEPALIVE void setjiAlligator (double (*f) (int, int, int, int, int, const char*, int)) { jiAlligator = f; } EMSCRIPTEN_KEEPALIVE void setjiAOInit (int (*f) (int, const char*, const char*)) { jiAOInit = f; } EMSCRIPTEN_KEEPALIVE void setjiAO (double (*f) (int, int, int)) { jiAO = f; } EMSCRIPTEN_KEEPALIVE void setjiATRInit (int (*f) (int, const char*, const char*, int)) { jiATRInit = f; } EMSCRIPTEN_KEEPALIVE void setjiATR (double (*f) (int, int, int)) { jiATR = f; } EMSCRIPTEN_KEEPALIVE void setjiBearsPowerInit (int (*f) (int, const char*, const char*, int, int)) { jiBearsPowerInit = f; } EMSCRIPTEN_KEEPALIVE void setjiBearsPower (double (*f) (int, int, int)) { jiBearsPower = f; } EMSCRIPTEN_KEEPALIVE void setjiBandsInit (int (*f) (int, const char*, const char*, int, double, int, int)) { jiBandsInit = f; } EMSCRIPTEN_KEEPALIVE void setjiBands (double (*f) (int, int, int, const char*, int)) { jiBands = f; } EMSCRIPTEN_KEEPALIVE void setjiBandsOnArray (double (*f) (int, double*, int, int, double, int, const char*, int)) { jiBandsOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiBullsPowerInit (int (*f) (int, const char*, const char*, int, int)) { jiBullsPowerInit = f; } EMSCRIPTEN_KEEPALIVE void setjiBullsPower (double (*f) (int, int, int)) { jiBullsPower = f; } EMSCRIPTEN_KEEPALIVE void setjiCCIInit (int (*f) (int, const char*, const char*, int, int)) { jiCCIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiCCI (double (*f) (int, int, int)) { jiCCI = f; } EMSCRIPTEN_KEEPALIVE void setjiCCIOnArray (double (*f) (int, double*, int, int, int)) { jiCCIOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiCustomInit (int (*f) (int, const char*, const char*, const char*, const char*)) { jiCustomInit = f; } EMSCRIPTEN_KEEPALIVE void setjiCustom (double (*f) (int, int, const char*, int)) { jiCustom = f; } EMSCRIPTEN_KEEPALIVE void setjiDeMarkerInit (int (*f) (int, const char*, const char*, int)) { jiDeMarkerInit = f; } EMSCRIPTEN_KEEPALIVE void setjiDeMarker (double (*f) (int, int, int)) { jiDeMarker = f; } EMSCRIPTEN_KEEPALIVE void setjiEnvelopesInit (int (*f) (int, const char*, const char*, int, const char*, int, int, double)) { jiEnvelopesInit = f; } EMSCRIPTEN_KEEPALIVE void setjiEnvelopes (double (*f) (int, int, int, const char*, int)) { jiEnvelopes = f; } EMSCRIPTEN_KEEPALIVE void setjiEnvelopesOnArray (double (*f) (int, double*, int, int, const char*, int, double, const char*, int)) { jiEnvelopesOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiFractalsInit (int (*f) (int, const char*, const char*)) { jiFractalsInit = f; } EMSCRIPTEN_KEEPALIVE void setjiFractals (double (*f) (int, int, const char*, int)) { jiFractals = f; } EMSCRIPTEN_KEEPALIVE void setjiIchimokuInit (int (*f) (int, const char*, const char*, int, int, int)) { jiIchimokuInit = f; } EMSCRIPTEN_KEEPALIVE void setjiIchimoku (double (*f) (int, int, int, const char*, int)) { jiIchimoku = f; } EMSCRIPTEN_KEEPALIVE void setjiMAInit (int (*f) (int, const char*, const char*, int, int, int, int)) { jiMAInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMA (double (*f) (int, int, int, const char*, int)) { jiMA = f; } EMSCRIPTEN_KEEPALIVE void setjiMAOnArray (double (*f) (int, double*, int, int, int, const char*, int)) { jiMAOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiMACDInit (int (*f) (int, const char*, const char*, int, int, int, int)) { jiMACDInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMACD (double (*f) (int, int, const char*, int)) { jiMACD = f; } EMSCRIPTEN_KEEPALIVE void setjiMFIInit (int (*f) (int, const char*, const char*, int)) { jiMFIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMFI (double (*f) (int, int, int)) { jiMFI = f; } EMSCRIPTEN_KEEPALIVE void setjiMomentumInit (int (*f) (int, const char*, const char*, int, int)) { jiMomentumInit = f; } EMSCRIPTEN_KEEPALIVE void setjiMomentum (double (*f) (int, int, int)) { jiMomentum = f; } EMSCRIPTEN_KEEPALIVE void setjiMomentumOnArray (double (*f) (int, double*, int, int, int)) { jiMomentumOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiRSIInit (int (*f) (int, const char*, const char*, int, int)) { jiRSIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiRSI (double (*f) (int, int, int)) { jiRSI = f; } EMSCRIPTEN_KEEPALIVE void setjiRSIOnArray (double (*f) (int, double*, int, int, int)) { jiRSIOnArray = f; } EMSCRIPTEN_KEEPALIVE void setjiRVIInit (int (*f) (int, const char*, const char*, int)) { jiRVIInit = f; } EMSCRIPTEN_KEEPALIVE void setjiRVI (double (*f) (int, int, const char*, int)) { jiRVI = f; } EMSCRIPTEN_KEEPALIVE void setjiSARInit (int (*f) (int, const char*, const char*, double, double)) { jiSARInit = f; } EMSCRIPTEN_KEEPALIVE void setjiSAR (double (*f) (int, int, int)) { jiSAR = f; } EMSCRIPTEN_KEEPALIVE void setjiStochasticInit (int (*f) (int, const char*, const char*, int, int, int, const char*)) { jiStochasticInit = f; } EMSCRIPTEN_KEEPALIVE void setjiStochastic (double (*f) (int, int, const char*, int)) { jiStochastic = f; } EMSCRIPTEN_KEEPALIVE void setjiWPRInit (int (*f) (int, const char*, const char*, int)) { jiWPRInit = f; } EMSCRIPTEN_KEEPALIVE void setjiWPR (double (*f) (int, int, int)) { jiWPR = f; } EMSCRIPTEN_KEEPALIVE void setjMarketInfo (double (*f) (int, const char*, int)) { jMarketInfo = f; } } template void Print (const Type & arg, const Types &... args) { stringstream s; s << arg; ((s << args), ..., (s << endl)); jPrint(iFintecheeUID, s.str().c_str()); } // todo template void Comment (const Type & arg, const Types &... args) { stringstream s; s << arg; ((s << args), ..., (s << endl)); jPrint(iFintecheeUID, s.str().c_str()); } // todo template void Alert (const Type & arg, const Types &... args) { stringstream s; s << arg; ((s << args), ..., (s << endl)); jPrint(iFintecheeUID, s.str().c_str()); } bool PlaySound (const string name) { Print("Playing: ", name); return true; } void SetIndexShift (int index, int shift) { jSetIndexShift(iFintecheeUID, index, shift); } long ChartID () { return jChartID(iFintecheeUID); } ENUM_TIMEFRAMES ChartPeriod (long chart_id) { return (ENUM_TIMEFRAMES)jChartPeriod(iFintecheeUID, chart_id); } ENUM_TIMEFRAMES ChartPeriod () { return ChartPeriod(0); } string ChartSymbol (long chart_id) { string symbol(jChartSymbol(iFintecheeUID, chart_id)); return symbol; } string ChartSymbol () { return ChartSymbol(0); } ENUM_TIMEFRAMES Period () { return (ENUM_TIMEFRAMES)jPeriod(iFintecheeUID); } string Symbol () { string symbol(jSymbol(iFintecheeUID)); return symbol; } datetime iTime (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiTime(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } datetime iTime (long symbol, int timeframe, int shift) { return iTime("", timeframe, shift); } double iOpen (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiOpenInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiOpen(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iOpen (long symbol, int timeframe, int shift) { return iOpen("", timeframe, shift); } double iHigh (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiHighInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiHigh(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iHigh (long symbol, int timeframe, int shift) { return iHigh("", timeframe, shift); } double iLow (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiLowInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiLow(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iLow (long symbol, int timeframe, int shift) { return iLow("", timeframe, shift); } double iClose (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiCloseInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiClose(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iClose (long symbol, int timeframe, int shift) { return iClose("", timeframe, shift); } long iVolume (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiVolumeInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiVolume(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } long iVolume (long symbol, int timeframe, int shift) { return iVolume("", timeframe, shift); } int iHighest (const string symbol, int timeframe, int type, int count, int start) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiHighest(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start); } int iHighest (long symbol, int timeframe, int type, int count, int start) { return iHighest("", timeframe, type, count, start); } int Highest (const string symbol, int timeframe, int type, int count, int start) { return iHighest (symbol, timeframe, type, count, start); } int Highest (long symbol, int timeframe, int type, int count, int start) { return iHighest("", timeframe, type, count, start); } int iLowest (const string symbol, int timeframe, int type, int count, int start) { const char* tf = convertTimeFrame(timeframe); string strID = string("Chart_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiTimeInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiLowest(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(type, INDI_OHLC), count, start); } int iLowest (long symbol, int timeframe, int type, int count, int start) { return iLowest("", timeframe, type, count, start); } int Lowest (const string symbol, int timeframe, int type, int count, int start) { return iLowest (symbol, timeframe, type, count, start); } int Lowest (long symbol, int timeframe, int type, int count, int start) { return iLowest("", timeframe, type, count, start); } double iAC (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iAC_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiACInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiAC(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iAC (long symbol, int timeframe, int shift) { return iAC("", timeframe, shift); } double iADX (const string symbol, int timeframe, int period, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iADX_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiADXInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiADX(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_ADX), shift); } double iADX (long symbol, int timeframe, int period, int applied_price, int mode, int shift) { return iADX("", timeframe, period, applied_price, mode, shift); } double iAlligator ( const string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iAlligator_") + symbol + string("_") + string(tf) + string("_") + to_string(jaw_period) + string("_") + to_string(jaw_shift) + string("_") + to_string(teeth_period) + string("_") + to_string(teeth_shift) + string("_") + to_string(lips_period) + string("_") + to_string(lips_shift) + string("_") + to_string(ma_method) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiAlligatorInit(iFintecheeUID, symbol.c_str(), tf, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, convertMAMethod(ma_method), applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiAlligator(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], jaw_shift, teeth_shift, lips_shift, convertMode(mode, INDI_ALLIGATOR), shift); } double iAlligator ( long symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period, int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price, int mode, int shift) { return iAlligator("", timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price, mode, shift); } double iAO (const string symbol, int timeframe, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iAO_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiAOInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiAO(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iAO (long symbol, int timeframe, int shift) { return iAO("", timeframe, shift); } double iATR (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iATR_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiATRInit(iFintecheeUID, symbol.c_str(), tf, period); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiATR(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iATR (long symbol, int timeframe, int period, int shift) { return iATR("", timeframe, period, shift); } double iBearsPower (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iBearsPower_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiBearsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiBearsPower(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iBearsPower (long symbol, int timeframe, int period, int applied_price, int shift) { return iBearsPower("", timeframe, period, applied_price, shift); } double iBands (const string symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iBands_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(deviation) + string("_") + to_string(bands_shift) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiBandsInit(iFintecheeUID, symbol.c_str(), tf, period, deviation, bands_shift, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiBands(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], bands_shift, convertMode(mode, INDI_BANDS), shift); } double iBands (long symbol, int timeframe, int period, double deviation, int bands_shift, int applied_price, int mode, int shift) { return iBands("", timeframe, period, deviation, bands_shift, applied_price, mode, shift); } double iBandsOnArray (double* array, int total, int period, double deviation, int bands_shift, int mode, int shift) { return jiBandsOnArray(iFintecheeUID, array, total, period, deviation, bands_shift, convertMode(mode, INDI_BANDS), shift); } double iBullsPower (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iBullsPower_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiBullsPowerInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiBullsPower(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iBullsPower (long symbol, int timeframe, int period, int applied_price, int shift) { return iBullsPower("", timeframe, period, applied_price, shift); } double iCCI (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iCCI_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiCCIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiCCI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iCCI (long symbol, int timeframe, int period, int applied_price, int shift) { return iCCI("", timeframe, period, applied_price, shift); } double iCCIOnArray (double* array, int total, int period, int shift) { return jiCCIOnArray(iFintecheeUID, array, total, period, shift); } template double iCustom (const string symbol, int timeframe, const string name, Ts&&... args) { const char* tf = convertTimeFrame(timeframe); stringstream s; const char* mode; int shift; int length = sizeof...(args); int i = 0; auto loop = [&] (auto && input) { if (i >= 0 && i < length - 2) { s << input << "|||"; } else if (i == length - 2) { mode = (const char*)input; } else if (i == length - 1) { shift = (int)input; } i++; }; (loop(args), ...); string strID = string("iCustom_") + symbol + string("_") + string(tf) + string("_") + string(name) + string("_") + s.str(); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiCustomInit(iFintecheeUID, symbol.c_str(), tf, name.c_str(), s.str().c_str()); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiCustom(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], mode, shift); } template double iCustom (long symbol, int timeframe, const string name, Ts&&... args) { return iCustom("", timeframe, name, args...); } double iDeMarker (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iDeMarker_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiDeMarkerInit(iFintecheeUID, symbol.c_str(), tf, period); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiDeMarker(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iDeMarker (long symbol, int timeframe, int period, int shift) { return iDeMarker("", timeframe, period, shift); } double iEnvelopes (const string symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iEnvelopes_") + symbol + string("_") + string(tf) + string("_") + to_string(ma_period) + string("_") + to_string(ma_method) + string("_") + to_string(ma_shift) + string("_") + to_string(applied_price) + string("_") + to_string(deviation); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiEnvelopesInit(iFintecheeUID, symbol.c_str(), tf, ma_period, convertMAMethod(ma_method), ma_shift, applied_price, deviation); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiEnvelopes(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], ma_shift, convertMode(mode, INDI_ENVELOPES), shift); } double iEnvelopes (long symbol, int timeframe, int ma_period, int ma_method, int ma_shift, int applied_price, double deviation, int mode, int shift) { return iEnvelopes("", timeframe, ma_period, ma_method, ma_shift, applied_price, deviation, mode, shift); } double iEnvelopesOnArray (double* array, int total, int ma_period, int ma_method, int ma_shift, double deviation, int mode, int shift) { return jiEnvelopesOnArray(iFintecheeUID, array, total, ma_period, convertMAMethod(ma_method), ma_shift, deviation, convertMode(mode, INDI_ENVELOPES), shift); } double iFractals (const string symbol, int timeframe, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iFractals_") + symbol + string("_") + string(tf); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiFractalsInit(iFintecheeUID, symbol.c_str(), tf); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiFractals(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_FRACTALS), shift); } double iFractals (long symbol, int timeframe, int mode, int shift) { return iFractals("", timeframe, mode, shift); } double iIchimoku (const string symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iIchimoku_") + symbol + string("_") + string(tf) + string("_") + to_string(tenkan_sen) + string("_") + to_string(kijun_sen) + string("_") + to_string(senkou_span_b); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiIchimokuInit(iFintecheeUID, symbol.c_str(), tf, tenkan_sen, kijun_sen, senkou_span_b); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } if (mode == MODE_TENKANSEN) { return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift); } else if (mode == MODE_KIJUNSEN) { return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], 0, convertMode(mode, INDI_ICHIMOKU), shift); } else if (mode == MODE_SENKOUSPANA) { return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift); } else if (mode == MODE_SENKOUSPANB) { return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift); } else { return jiIchimoku(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], -kijun_sen, convertMode(mode, INDI_ICHIMOKU), shift); } } double iIchimoku (long symbol, int timeframe, int tenkan_sen, int kijun_sen, int senkou_span_b, int mode, int shift) { return iIchimoku("", timeframe, tenkan_sen, kijun_sen, senkou_span_b, mode, shift); } double iMA (const string symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMA_") + symbol + string("_") + string(tf) + string("_") + to_string(ma_period) + string("_") + to_string(ma_shift) + string("_") + to_string(ma_method) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiMAInit(iFintecheeUID, symbol.c_str(), tf, ma_period, ma_shift, ma_method, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiMA(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], ma_shift, convertMAMethod(ma_method), shift); } double iMA (long symbol, int timeframe, int ma_period, int ma_shift, int ma_method, int applied_price, int shift) { return iMA("", timeframe, ma_period, ma_shift, ma_method, applied_price, shift); } double iMAOnArray (double* array, int total, int ma_period, int ma_shift, int ma_method, int shift) { return jiMAOnArray(iFintecheeUID, array, total, ma_period, ma_shift, convertMAMethod(ma_method), shift); } double iMACD (const string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMACD_") + symbol + string("_") + string(tf) + string("_") + to_string(fast_ema_period) + string("_") + to_string(slow_ema_period) + string("_") + to_string(signal_period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiMACDInit(iFintecheeUID, symbol.c_str(), tf, fast_ema_period, slow_ema_period, signal_period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiMACD(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_MACD), shift); } double iMACD (long symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) { return iMACD("", timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price, mode, shift); } double iMFI (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMFI_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiMFIInit(iFintecheeUID, symbol.c_str(), tf, period); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiMFI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iMFI (long symbol, int timeframe, int period, int shift) { return iMFI("", timeframe, period, shift); } double iMomentum (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iMomentum_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiMomentumInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiMomentum(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iMomentum (long symbol, int timeframe, int period, int applied_price, int shift) { return iMomentum("", timeframe, period, applied_price, shift); } double iMomentumOnArray (double* array, int total, int period, int shift) { return jiMomentumOnArray(iFintecheeUID, array, total, period, shift); } double iRSI (const string symbol, int timeframe, int period, int applied_price, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iRSI_") + symbol + string("_") + string(tf) + string("_") + to_string(period) + string("_") + to_string(applied_price); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiRSIInit(iFintecheeUID, symbol.c_str(), tf, period, applied_price); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiRSI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iRSI (long symbol, int timeframe, int period, int applied_price, int shift) { return iRSI("", timeframe, period, applied_price, shift); } double iRSIOnArray (double* array, int total, int period, int shift) { return jiRSIOnArray(iFintecheeUID, array, total, period, shift); } double iRVI (const string symbol, int timeframe, int period, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iRVI_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiRVIInit(iFintecheeUID, symbol.c_str(), tf, period); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiRVI(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_RVI), shift); } double iRVI (long symbol, int timeframe, int period, int mode, int shift) { return iRVI("", timeframe, period, mode, shift); } double iSAR (const string symbol, int timeframe, double step, double maximum, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iSAR_") + symbol + string("_") + string(tf) + string("_") + to_string(step) + string("_") + to_string(maximum); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiSARInit(iFintecheeUID, symbol.c_str(), tf, step, maximum); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiSAR(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iSAR (long symbol, int timeframe, double step, double maximum, int shift) { return iSAR("", timeframe, step, maximum, shift); } double iStochastic (const string symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iStochastic_") + symbol + string("_") + string(tf) + string("_") + to_string(Kperiod) + string("_") + to_string(Dperiod) + string("_") + to_string(slowing) + string("_") + to_string(method); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiStochasticInit(iFintecheeUID, symbol.c_str(), tf, Kperiod, Dperiod, slowing, convertMAMethod(method)); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiStochastic(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], convertMode(mode, INDI_STOCHASTIC), shift); } double iStochastic (long symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method, int price_field, int mode, int shift) { return iStochastic("", timeframe, Kperiod, Dperiod, slowing, method, price_field, mode, shift); } double iWPR (const string symbol, int timeframe, int period, int shift) { const char* tf = convertTimeFrame(timeframe); string strID = string("iWPR_") + symbol + string("_") + string(tf) + string("_") + to_string(period); if (paramInputOutputList[iFintecheeUID].handleList.count(strID) == 0) { int handle = jiWPRInit(iFintecheeUID, symbol.c_str(), tf, period); paramInputOutputList[iFintecheeUID].handleList[strID] = handle; } return jiWPR(iFintecheeUID, paramInputOutputList[iFintecheeUID].handleList[strID], shift); } double iWPR (long symbol, int timeframe, int period, int shift) { return iWPR("", timeframe, period, shift); } // todo, check whether the logic about the return value is the same as MQL4 datetime GlobalVariableSet (const string name, double value) { return setGlobalVar(iFintecheeUID, name, value); } bool GlobalVariableCheck (const string name) { return checkGlobalVar(iFintecheeUID, name); } double GlobalVariableGet (const string name) { return getGlobalVar(iFintecheeUID, name); } bool GlobalVariableDel (const string name) { return delGlobalVar(iFintecheeUID, name); } double MarketInfo (const string symbol, int type) { return jMarketInfo(iFintecheeUID, symbol.c_str(), type); } double MarketInfo (long symbol, int type) { return MarketInfo("", type); } // Not compatible with MQL // Deprecated bool SCompareL (const string str, long l) { return jSCompareL(iFintecheeUID, str.c_str(), l); } // Not compatible with MQL bool VeriSig (const string fintechee_data, const string fintechee_signature, const string fintechee_public_key, const string application_public_key) { string data = fintechee_data; string signature = fintechee_signature; string publicKey = fintechee_public_key; string appPublicKey = application_public_key; data.erase(std::remove(data.begin(), data.end(), '\n'), data.end()); signature.erase(std::remove(signature.begin(), signature.end(), '\n'), signature.end()); publicKey.erase(std::remove(publicKey.begin(), publicKey.end(), '\n'), publicKey.end()); appPublicKey.erase(std::remove(appPublicKey.begin(), appPublicKey.end(), '\n'), appPublicKey.end()); data = StringTrimLeft(StringTrimRight(data)); signature = StringTrimLeft(StringTrimRight(signature)); publicKey = StringTrimLeft(StringTrimRight(publicKey)); appPublicKey = StringTrimLeft(StringTrimRight(appPublicKey)); int dataLen = StringLen(data); int signatureLen = StringLen(signature); int publicKeyLen = StringLen(publicKey); int appPublicKeyLen = StringLen(appPublicKey); if (dataLen == 0 || signatureLen == 0 || publicKeyLen == 0 || appPublicKeyLen == 0) return false; if (publicKeyLen != appPublicKeyLen) return false; if (StringCompare(publicKey, appPublicKey) != 0) return false; bool res = jVeriSig(iFintecheeUID, data.c_str(), signature.c_str(), publicKey.c_str()); if (res) { std::vector arr; std::stringstream ss(data); string s; while (std::getline(ss, s, ',')) { arr.push_back(s); } if (0 < arr.size()) { if (std::stoll(arr[0]) >= TimeCurrent()) { return true; } } } return false; } ================================================ FILE: EA/Plugin-for-MQL/plugin_for_mql.js ================================================ registerEA( "plugin_for_mql", "mql_plugin to make MQL-based programs runnable on Fintechee(v1.06)", [], function (context) { // Init() if (typeof window.pluginForMql != "undefined") { window.pluginForMql.init() return } window.pluginForMql = { createMqlIndicator: function (definition) { importBuiltInIndicator( definition.name, definition.description, function (context) { var indiName = getIndiName(context) if (typeof window.mqlIndicators == "undefined" || typeof window.mqlIndicators[indiName] == "undefined") { return } var indiObj = window.mqlIndicators[indiName] var uid = null if (typeof context.uid == "undefined") { uid = window.mqlIndiUID++ context.uid = uid } else { uid = context.uid } var calculatedLength = 0 if (typeof window.mqlIndicatorsBuffer[uid + ""] != "undefined") { calculatedLength = getCalculatedLength(context) } var currDefinition = indiObj.definition var nByteDouble = 8 var nByteString = 1 var length = 1 var buffer = null if (calculatedLength == 0) { for (var i in currDefinition.parameters) { if (currDefinition.parameters[i].type == PARAMETER_TYPE.INTEGER) { indiObj.setParamInt(uid, getIndiParameter(context, currDefinition.parameters[i].name)) } else if (currDefinition.parameters[i].type == PARAMETER_TYPE.NUMBER) { indiObj.setParamDouble(uid, getIndiParameter(context, currDefinition.parameters[i].name)) } else if (currDefinition.parameters[i].type == PARAMETER_TYPE.BOOLEAN) { indiObj.setParamBool(uid, getIndiParameter(context, currDefinition.parameters[i].name)) } else if (currDefinition.parameters[i].type == PARAMETER_TYPE.STRING) { var indiStrParam = getIndiParameter(context, currDefinition.parameters[i].name) if (indiStrParam == null) { indiStrParam = "" } indiObj.setParamString(uid, indiStrParam) } } } var dataLen = getDataInput(context, 0).length var buffLen = dataLen * 2 var ratesTotal = dataLen var prevCalc = calculatedLength var buffObj = null if (typeof window.mqlIndicatorsBuffer[uid + ""] == "undefined") { var brokerName = getBrokerNameByContext(context) var accountId = getAccountIdByContext(context) var symbolName = getChartSymbolNameByContext(context) var timeFrame = getChartTimeFrameByContext(context) window.mqlIndicatorsBuffer[uid + ""] = { name: currDefinition.name, context: context, brokerName: brokerName, accountId: accountId, symbolName: symbolName, timeFrame: timeFrame, chartId: getChartHandleByContext(context), symbol: getSymbolInfo(brokerName, accountId, symbolName), bufferLen: buffLen, dataInput: [], dataOutput: [], time: new Date().getTime(), mTime: 0 } buffObj = window.mqlIndicatorsBuffer[uid + ""] for (var i in currDefinition.dataInput) { var dataInput = getDataInput(context, currDefinition.dataInput[i].index) buffer = indiObj.module._malloc(buffLen * nByteDouble) for (var j = 0; j < dataInput.length; j++) { indiObj.module.setValue(buffer + j * nByteDouble, dataInput[j], "double") } indiObj.setDataInput(uid, buffLen, buffer) buffObj.dataInput.push(buffer) } for (var i in currDefinition.dataOutput) { buffer = indiObj.module._malloc(buffLen * nByteDouble) indiObj.setDataOutput(uid, buffLen, buffer) buffObj.dataOutput.push(buffer) } indiObj.onCalc(uid, ratesTotal, prevCalc, 10000, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed)) for (var i in currDefinition.dataOutput) { var dataOutputMql = buffObj.dataOutput[i] var dataOutput = getDataOutput(context, currDefinition.dataOutput[i].name) for (var j = 0; j < dataOutput.length; j++) { dataOutput[j] = indiObj.module.getValue(dataOutputMql + j * nByteDouble, "double") } } } else if (dataLen == window.mqlIndicatorsBuffer[uid + ""].bufferLen) { buffObj = window.mqlIndicatorsBuffer[uid + ""] buffObj.time = new Date().getTime() buffObj.bufferLen = buffLen for (var i in currDefinition.dataInput) { var dataInput = getDataInput(context, currDefinition.dataInput[i].index) buffer = indiObj.module._malloc(buffLen * nByteDouble) for (var j = 0; j < dataInput.length; j++) { indiObj.module.setValue(buffer + j * nByteDouble, dataInput[j], "double") } indiObj.setDataInput(uid, buffLen, buffer) indiObj.module._free(buffObj.dataInput[i]) buffObj.dataInput.push(buffer) } for (var i in currDefinition.dataOutput) { buffer = indiObj.module._malloc(buffLen * nByteDouble) for (var j = 0; j < dataOutput.length; j++) { indiObj.module.setValue(buffer + j * nByteDouble, dataOutput[j], "double") } indiObj.setDataOutput(uid, buffLen, buffer) indiObj.module._free(buffObj.dataOutput[i]) buffObj.dataOutput.push(buffer) } var cData = getDataFromIndi(context, buffObj.chartId, DATA_NAME.CLOSE) indiObj.onCalc(uid, ratesTotal, prevCalc, cData.length, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed)) for (var i in currDefinition.dataOutput) { var dataOutputMql = buffObj.dataOutput[i] var dataOutput = getDataOutput(context, currDefinition.dataOutput[i].name) dataOutput[dataOutput.length - 1] = indiObj.module.getValue(dataOutputMql + (dataOutput.length - 1) * nByteDouble, "double") } } else { buffObj = window.mqlIndicatorsBuffer[uid + ""] buffObj.time = new Date().getTime() for (var i in currDefinition.dataInput) { var dataInputMql = buffObj.dataInput[i] var dataInput = getDataInput(context, currDefinition.dataInput[i].index) indiObj.module.setValue(dataInputMql + (dataInput.length - 1) * nByteDouble, dataInput[dataInput.length - 1], "double") } var cData = getDataFromIndi(context, buffObj.chartId, DATA_NAME.CLOSE) indiObj.onCalc(uid, ratesTotal, prevCalc, cData.length, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed)) for (var i in currDefinition.dataOutput) { var dataOutputMql = buffObj.dataOutput[i] var dataOutput = getDataOutput(context, currDefinition.dataOutput[i].name) dataOutput[dataOutput.length - 1] = indiObj.module.getValue(dataOutputMql + (dataOutput.length - 1) * nByteDouble, "double") } } for (var i in currDefinition.parameters) { if (currDefinition.parameters[i].name == "shift") { var shift = getIndiParameter(context, "shift") if (shift != null && calculatedLength == 0) { for (var j in currDefinition.dataOutput) { setIndiShift(context, currDefinition.dataOutput[j].name, shift) } } break } } }, definition.parameters, definition.dataInput, definition.dataOutput, definition.whereToRender ) // registerIndicator }, removeMqlIndicator: function (name) { unregisterIndicator(name) if (typeof window.mqlIndicators == "undefined" || typeof window.mqlIndicatorsBuffer == "undefined") return delete window.mqlIndicators[name] for (var i in window.mqlIndicatorsBuffer) { if (window.mqlIndicatorsBuffer[i].name == name) { delete window.mqlIndicatorsBuffer[i] break } } }, loadMqlIndicator: function (definition) { return new Promise(function (rs, rj) { 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") == definition.url) { tags[i].parentNode.removeChild(tags[i]) break } } var scriptPromise = new Promise(function (resolve, reject) { var script = document.createElement("script") document.body.appendChild(script) script.onload = resolve script.onerror = reject script.async = true script.src = definition.url }) scriptPromise.then(function () { IndiPlugIn().then(function (Module) { if (typeof window.mqlIndicators == "undefined") { window.mqlIndicators = [] window.mqlIndicatorsBuffer = [] window.mqlIndiUID = 0 } var jPrint = Module.addFunction(function (uid, s) { var obj = window.mqlIndicatorsBuffer[uid + ""] printMessage(window.mqlIndicators[obj.name].module.UTF8ToString(s)) }, "vii") var jSetIndexShift = Module.addFunction(function (uid, index, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] setIndiShift(obj.context, index, shift) }, "viii") var jChartID = Module.addFunction(function (uid) { return window.mqlIndicatorsBuffer[uid + ""].chartId }, "ii") var jChartPeriod = Module.addFunction(function (uid, chart_id) { var obj = window.mqlIndicatorsBuffer[uid + ""] if (chart_id == 0) { return obj.convertTimeFrame(obj.timeFrame) } else { return obj.convertTimeFrame(getChartTimeFrame(chart_id)) } }, "iii") var jChartSymbol = Module.addFunction(function (uid, chart_id) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = "" if (chart_id == 0) { symbolName = obj.symbolName } else { symbolName = getChartSymbolName(chart_id) } var lengthBytes = window.mqlIndicators[obj.name].module.lengthBytesUTF8(symbolName) + 1 var stringOnWasmHeap = window.mqlIndicators[obj.name].module._malloc(lengthBytes) window.mqlIndicators[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "iii") var jPeriod = Module.addFunction(function (uid) { var obj = window.mqlIndicatorsBuffer[uid + ""] return obj.convertTimeFrame(obj.timeFrame) }, "ii") var jSymbol = Module.addFunction(function (uid) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = obj.symbolName var lengthBytes = window.mqlIndicators[obj.name].module.lengthBytesUTF8(symbolName) + 1 var stringOnWasmHeap = window.mqlIndicators[obj.name].module._malloc(lengthBytes) window.mqlIndicators[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "ii") var jiTimeInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandleFromIndi(obj.context, symbolName, timeFrm) }, "iiii") var jiTime = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, chartHandle, "Time") return arr[arr.length - shift - 1] }, "iiii") var jiOpenInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandleFromIndi(obj.context, symbolName, timeFrm) }, "iiii") var jiOpen = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, chartHandle, "Open") return arr[arr.length - shift - 1] }, "diii") var jiHighInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandleFromIndi(obj.context, symbolName, timeFrm) }, "iiii") var jiHigh = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, chartHandle, "High") return arr[arr.length - shift - 1] }, "diii") var jiLowInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandleFromIndi(obj.context, symbolName, timeFrm) }, "iiii") var jiLow = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, chartHandle, "Low") return arr[arr.length - shift - 1] }, "diii") var jiCloseInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandleFromIndi(obj.context, symbolName, timeFrm) }, "iiii") var jiClose = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, chartHandle, "Close") return arr[arr.length - shift - 1] }, "diii") var jiVolumeInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandleFromIndi(obj.context, symbolName, timeFrm) }, "iiii") var jiVolume = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, chartHandle, "Volume") return arr[arr.length - shift - 1] }, "iiii") var jiHighest = Module.addFunction(function (uid, chartHandle, mode, count, start) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, chartHandle, md) var highest = -Number.MAX_VALUE var idx = -1 for (var i = start; i < start + count && i >= 0 && i < arr.length; i++) { if (arr[arr.length - i - 1] > highest) { highest = arr[arr.length - i - 1] idx = i } } return idx }, "iiiiii") var jiLowest = Module.addFunction(function (uid, chartHandle, mode, count, start) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, chartHandle, md) var lowest = Number.MAX_VALUE var idx = -1 for (var i = start; i < start + count && i >= 0 && i < arr.length; i++) { if (arr[arr.length - i - 1] < lowest) { lowest = arr[arr.length - i - 1] idx = i } } return idx }, "iiiiii") var jiACInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "ac", []) }, "iiii") var jiAC = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arrUp = getDataFromIndi(obj.context, indiHandle, "up") var arrDown = getDataFromIndi(obj.context, indiHandle, "down") return arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1] }, "diii") var jiADXInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "adx_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiADX = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiAlligatorInit = Module.addFunction(function (uid, symbol, timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) var method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "alligator_for_mql", [{ name: "jawsPeriod", value: jaw_period },{ name: "jawsShift", value: jaw_shift },{ name: "teethPeriod", value: teeth_period },{ name: "teethShift", value: teeth_shift },{ name: "lipsPeriod", value: lips_period },{ name: "lipsShift", value: lips_shift },{ name: "method", value: method },{ name: "appliedPrice", value: applied_price }]) }, "iiiiiiiiiiii") var jiAlligator = Module.addFunction(function (uid, indiHandle, jaw_shift, teeth_shift, lips_shift, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) if (md == "jaws") { return arr[arr.length - shift - 1] } else if (md == "teeth") { return arr[arr.length - shift - 1] } else { return arr[arr.length - shift - 1] } }, "diiiiiii") var jiAOInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "ao", []) }, "iiii") var jiAO = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arrUp = getDataFromIndi(obj.context, indiHandle, "up") var arrDown = getDataFromIndi(obj.context, indiHandle, "down") return arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1] }, "diii") var jiATRInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "atr", [{ name: "period", value: period }]) }, "iiiii") var jiATR = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "atr") return arr[arr.length - shift - 1] }, "diii") var jiBearsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "bears_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiBearsPower = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "bears") return arr[arr.length - shift - 1] }, "diii") var jiBandsInit = Module.addFunction(function (uid, symbol, timeframe, period, deviation, bands_shift, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "bands_for_mql", [{ name: "period", value: period, },{ name: "deviations", value: deviation, },{ name: "shift", value: bands_shift, },{ name: "method", value: "sma" },{ name: "appliedPrice", value: applied_price, }]) }, "iiiiidii") var jiBands = Module.addFunction(function (uid, indiHandle, bands_shift, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiiii") var jiBandsOnArray = Module.addFunction(function (uid, array, total, period, deviation, bands_shift, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("bands_for_mql", [{ name: "period", value: period, },{ name: "deviations", value: deviation, },{ name: "shift", value: bands_shift, },{ name: "method", value: "sma" },{ name: "appliedPrice", value: 0, }], dataInput, total) var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataOnArray(dataOutput, md) return arr[arr.length - shift - 1] }, "diiiidiii") var jiBullsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "bulls_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiBullsPower = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "bulls") return arr[arr.length - shift - 1] }, "diii") var jiCCIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "cci_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiCCI = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "cci") return arr[arr.length - shift - 1] }, "diii") var jiCCIOnArray = Module.addFunction(function (uid, array, total, period, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("cci_for_mql", [{ name: "period", value: period, },{ name: "appliedPrice", value: 0, }], dataInput, total) var arr = getDataOnArray(dataOutput, "cci") return arr[arr.length - shift - 1] }, "diiiii") var jiCustomInit = Module.addFunction(function (uid, symbol, timeframe, name, paramString) { var obj = window.mqlIndicatorsBuffer[uid + ""] var indiName = window.mqlIndicators[obj.name].module.UTF8ToString(name) if (typeof window.mqlIndicators == "undefined" || typeof window.mqlIndicators[indiName] == "undefined") { throw new Error("Please start MQL indicator loader plugin and load the specific indicator(" + indiName + ").") } var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) var params = window.mqlIndicators[obj.name].module.UTF8ToString(paramString).split("|||") symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm var parameters = JSON.parse(JSON.stringify(window.mqlIndicators[indiName].definition.parameters)) for (var i in parameters) { if (isInteger(params[i])) { parameters[i].value = parseInt(params[i]) } else if (isNumeric(params[i])) { parameters[i].value = parseFloat(params[i]) } else if (params[i] == "true") { parameters[i].value = true } else if (params[i] == "false") { parameters[i].value = false } else { parameters[i].value = params[i] } } return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, indiName, parameters) }, "iiiiii") var jiCustom = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiDeMarkerInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "demarker", [{ name: "period", value: period }]) }, "iiiii") var jiDeMarker = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "demarker") return arr[arr.length - shift - 1] }, "diii") var jiEnvelopesInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_method, ma_shift, applied_price, deviation) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) var method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "envelopes_for_mql", [{ name: "period", value: ma_period },{ name: "deviations", value: deviation },{ name: "shift", value: ma_shift },{ name: "method", value: method },{ name: "appliedPrice", value: applied_price }]) }, "iiiiiiiid") var jiEnvelopes = Module.addFunction(function (uid, indiHandle, ma_shift, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiiii") var jiEnvelopesOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_method, ma_shift, deviation, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method) var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("envelopes_for_mql", [{ name: "period", value: ma_period },{ name: "deviations", value: deviation },{ name: "shift", value: ma_shift },{ name: "method", value: method },{ name: "appliedPrice", value: 0 }], dataInput, total) var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataOnArray(dataOutput, md) return arr[arr.length - shift - 1] }, "diiiiiidii") var jiFractalsInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "fractals", []) }, "iiii") var jiFractals = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiIchimokuInit = Module.addFunction(function (uid, symbol, timeframe, tenkan_sen, kijun_sen, senkou_span_b) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "ichimoku", [{ name: "tenkan", value: tenkan_sen },{ name: "kijun", value: kijun_sen },{ name: "senkou", value: senkou_span_b }]) }, "iiiiiii") var jiIchimoku = Module.addFunction(function (uid, indiHandle, ichimoku_shift, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiiii") var jiMAInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_shift, ma_method, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm var params = [{ name: "period", value: ma_period },{ name: "shift", value: ma_shift },{ name: "appliedPrice", value: applied_price }] if (ma_method == 1) { return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "ema_for_mql", params) } else if (ma_method == 2) { return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "smma_for_mql", params) } else if (ma_method == 3) { return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "lwma_for_mql", params) } else { return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "sma_for_mql", params) } }, "iiiiiiii") var jiMA = Module.addFunction(function (uid, indiHandle, ma_shift, ma_method, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method) var arr = getDataFromIndi(obj.context, indiHandle, method) return arr[arr.length - shift - 1] }, "diiiii") var jiMAOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_shift, ma_method, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method) var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = null var params = [{ name: "period", value: ma_period },{ name: "shift", value: ma_shift },{ name: "appliedPrice", value: 0 }] if (method == "ema") { dataOutput = calcIndicatorOnArray("ema_for_mql", params, dataInput, total) } else if (method == "smma") { dataOutput = calcIndicatorOnArray("smma_for_mql", params, dataInput, total) } else if (method == "lwma") { dataOutput = calcIndicatorOnArray("lwma_for_mql", params, dataInput, total) } else { dataOutput = calcIndicatorOnArray("sma_for_mql", params, dataInput, total) } var arr = getDataOnArray(dataOutput, method) return arr[arr.length - shift - 1] }, "diiiiiii") var jiMACDInit = Module.addFunction(function (uid, symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "macd_for_mql", [{ name: "fastEMA", value: fast_ema_period },{ name: "slowEMA", value: slow_ema_period },{ name: "signalSMA", value: signal_period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiiiii") var jiMACD = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiMFIInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "mfi", [{ name: "period", value: period }]) }, "iiiiiiii") var jiMFI = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "mfi") return arr[arr.length - shift - 1] }, "diiii") var jiMomentumInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "momentum_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiMomentum = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "momentum") return arr[arr.length - shift - 1] }, "diii") var jiMomentumOnArray = Module.addFunction(function (uid, array, total, period, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("momentum_for_mql", [{ name: "period", value: period, },{ name: "appliedPrice", value: 0, }], dataInput, total) var arr = getDataOnArray(dataOutput, "momentum") return arr[arr.length - shift - 1] }, "diiiii") var jiRSIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "rsi_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiRSI = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "rsi") return arr[arr.length - shift - 1] }, "diii") var jiRSIOnArray = Module.addFunction(function (uid, array, total, period, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlIndicators[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("rsi_for_mql", [{ name: "period", value: period, },{ name: "appliedPrice", value: 0, }], dataInput, total) var arr = getDataOnArray(dataOutput, "rsi") return arr[arr.length - shift - 1] }, "diiiii") var jiRVIInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "rvi", [{ name: "period", value: period }]) }, "iiiii") var jiRVI = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiSARInit = Module.addFunction(function (uid, symbol, timeframe, step, maximum) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "sar", [{ name: "acceleration", value: step, },{ name: "afMax", value: maximum, }]) }, "iiiidd") var jiSAR = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "sar") return arr[arr.length - shift - 1] }, "diii") var jiStochasticInit = Module.addFunction(function (uid, symbol, timeframe, Kperiod, Dperiod, slowing, ma_method) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) var method = window.mqlIndicators[obj.name].module.UTF8ToString(ma_method) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "stochastic", [{ name: "KPeriod", value: Kperiod },{ name: "slowing", value: slowing },{ name: "DPeriod", value: Dperiod },{ name: "method", value: method }]) }, "iiiiiiii") var jiStochastic = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var md = window.mqlIndicators[obj.name].module.UTF8ToString(mode) var arr = getDataFromIndi(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiWPRInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlIndicators[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandleFromIndi(obj.context, symbolName, timeFrm, "wpr", [{ name: "period", value: period }]) }, "iiiii") var jiWPR = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlIndicatorsBuffer[uid + ""] var arr = getDataFromIndi(obj.context, indiHandle, "wpr") return arr[arr.length - shift - 1] }, "diii") var jMarketInfo = Module.addFunction(function (uid, symbol, type) { var obj = window.mqlIndicatorsBuffer[uid + ""] var symbolName = window.mqlIndicators[obj.name].module.UTF8ToString(symbol) var symbolObj = null if (symbolName == "") { symbolObj = obj.symbol } else { symbolObj = getSymbolInfo(obj.brokerName, obj.accountId, symbolName) } if (type == 11) { return 1.0 / symbolObj.toFixed } else if (type == 12) { return Math.log10(symbolObj.toFixed) } else if (type == 18) { return symbolObj.swapLong } else if (type == 19) { return symbolObj.swapShort } else if (type == 22) { return symbolObj.tradable } else if (type == 23) { return symbolObj.lotsMinLimit } else if (type == 24) { return symbolObj.lotsStep } else if (type == 25) { return symbolObj.lotsLimit } printErrorMessage("Not supported the specific market information currently!") return -1 }, "diii") window.mqlIndicators[definition.name] = { definition: definition, module: Module, setParamInt: Module.cwrap("setParamInt", null, ["number", "number"]), setParamDouble: Module.cwrap("setParamDouble", null, ["number", "number"]), setParamBool: Module.cwrap("setParamBool", null, ["number", "number"]), setParamString: Module.cwrap("setParamString", null, ["number", "string"]), setDataInput: Module.cwrap("setDataInput", null, ["number", "number", "number"]), setDataOutput: Module.cwrap("setDataOutput", null, ["number", "number", "number"]), onCalc: Module.cwrap("onCalc", null, ["number", "number", "number", "number", "number", "number"]), setjPrint: Module.cwrap("setjPrint", null, ["number"]), setjSetIndexShift: Module.cwrap("setjSetIndexShift", null, ["number"]), setjChartID: Module.cwrap("setjChartID", null, ["number"]), setjChartPeriod: Module.cwrap("setjChartPeriod", null, ["number"]), setjChartSymbol: Module.cwrap("setjChartSymbol", null, ["number"]), setjPeriod: Module.cwrap("setjPeriod", null, ["number"]), setjSymbol: Module.cwrap("setjSymbol", null, ["number"]), setjiTimeInit: Module.cwrap("setjiTimeInit", null, ["number"]), setjiTime: Module.cwrap("setjiTime", null, ["number"]), setjiOpenInit: Module.cwrap("setjiOpenInit", null, ["number"]), setjiOpen: Module.cwrap("setjiOpen", null, ["number"]), setjiHighInit: Module.cwrap("setjiHighInit", null, ["number"]), setjiHigh: Module.cwrap("setjiHigh", null, ["number"]), setjiLowInit: Module.cwrap("setjiLowInit", null, ["number"]), setjiLow: Module.cwrap("setjiLow", null, ["number"]), setjiCloseInit: Module.cwrap("setjiCloseInit", null, ["number"]), setjiClose: Module.cwrap("setjiClose", null, ["number"]), setjiVolumeInit: Module.cwrap("setjiVolumeInit", null, ["number"]), setjiVolume: Module.cwrap("setjiVolume", null, ["number"]), setjiHighest: Module.cwrap("setjiHighest", null, ["number"]), setjiLowest: Module.cwrap("setjiLowest", null, ["number"]), setjiACInit: Module.cwrap("setjiACInit", null, ["number"]), setjiAC: Module.cwrap("setjiAC", null, ["number"]), setjiADXInit: Module.cwrap("setjiADXInit", null, ["number"]), setjiADX: Module.cwrap("setjiADX", null, ["number"]), setjiAlligatorInit: Module.cwrap("setjiAlligatorInit", null, ["number"]), setjiAlligator: Module.cwrap("setjiAlligator", null, ["number"]), setjiAOInit: Module.cwrap("setjiAOInit", null, ["number"]), setjiAO: Module.cwrap("setjiAO", null, ["number"]), setjiATRInit: Module.cwrap("setjiATRInit", null, ["number"]), setjiATR: Module.cwrap("setjiATR", null, ["number"]), setjiBearsPowerInit: Module.cwrap("setjiBearsPowerInit", null, ["number"]), setjiBearsPower: Module.cwrap("setjiBearsPower", null, ["number"]), setjiBandsInit: Module.cwrap("setjiBandsInit", null, ["number"]), setjiBands: Module.cwrap("setjiBands", null, ["number"]), setjiBandsOnArray: Module.cwrap("setjiBandsOnArray", null, ["number"]), setjiBullsPowerInit: Module.cwrap("setjiBullsPowerInit", null, ["number"]), setjiBullsPower: Module.cwrap("setjiBullsPower", null, ["number"]), setjiCCIInit: Module.cwrap("setjiCCIInit", null, ["number"]), setjiCCI: Module.cwrap("setjiCCI", null, ["number"]), setjiCCIOnArray: Module.cwrap("setjiCCIOnArray", null, ["number"]), setjiCustomInit: Module.cwrap("setjiCustomInit", null, ["number"]), setjiCustom: Module.cwrap("setjiCustom", null, ["number"]), setjiDeMarkerInit: Module.cwrap("setjiDeMarkerInit", null, ["number"]), setjiDeMarker: Module.cwrap("setjiDeMarker", null, ["number"]), setjiEnvelopesInit: Module.cwrap("setjiEnvelopesInit", null, ["number"]), setjiEnvelopes: Module.cwrap("setjiEnvelopes", null, ["number"]), setjiEnvelopesOnArray: Module.cwrap("setjiEnvelopesOnArray", null, ["number"]), setjiFractalsInit: Module.cwrap("setjiFractalsInit", null, ["number"]), setjiFractals: Module.cwrap("setjiFractals", null, ["number"]), setjiIchimokuInit: Module.cwrap("setjiIchimokuInit", null, ["number"]), setjiIchimoku: Module.cwrap("setjiIchimoku", null, ["number"]), setjiMAInit: Module.cwrap("setjiMAInit", null, ["number"]), setjiMA: Module.cwrap("setjiMA", null, ["number"]), setjiMAOnArray: Module.cwrap("setjiMAOnArray", null, ["number"]), setjiMACDInit: Module.cwrap("setjiMACDInit", null, ["number"]), setjiMACD: Module.cwrap("setjiMACD", null, ["number"]), setjiMFIInit: Module.cwrap("setjiMFIInit", null, ["number"]), setjiMFI: Module.cwrap("setjiMFI", null, ["number"]), setjiMomentumInit: Module.cwrap("setjiMomentumInit", null, ["number"]), setjiMomentum: Module.cwrap("setjiMomentum", null, ["number"]), setjiMomentumOnArray: Module.cwrap("setjiMomentumOnArray", null, ["number"]), setjiRSIInit: Module.cwrap("setjiRSIInit", null, ["number"]), setjiRSI: Module.cwrap("setjiRSI", null, ["number"]), setjiRSIOnArray: Module.cwrap("setjiRSIOnArray", null, ["number"]), setjiRVIInit: Module.cwrap("setjiRVIInit", null, ["number"]), setjiRVI: Module.cwrap("setjiRVI", null, ["number"]), setjiSARInit: Module.cwrap("setjiSARInit", null, ["number"]), setjiSAR: Module.cwrap("setjiSAR", null, ["number"]), setjiStochasticInit: Module.cwrap("setjiStochasticInit", null, ["number"]), setjiStochastic: Module.cwrap("setjiStochastic", null, ["number"]), setjiWPRInit: Module.cwrap("setjiWPRInit", null, ["number"]), setjiWPR: Module.cwrap("setjiWPR", null, ["number"]), setjMarketInfo: Module.cwrap("setjMarketInfo", null, ["number"]) } window.mqlIndicators[definition.name].setjPrint(jPrint) window.mqlIndicators[definition.name].setjSetIndexShift(jSetIndexShift) window.mqlIndicators[definition.name].setjChartID(jChartID) window.mqlIndicators[definition.name].setjChartPeriod(jChartPeriod) window.mqlIndicators[definition.name].setjChartSymbol(jChartSymbol) window.mqlIndicators[definition.name].setjPeriod(jPeriod) window.mqlIndicators[definition.name].setjSymbol(jSymbol) window.mqlIndicators[definition.name].setjiTimeInit(jiTimeInit) window.mqlIndicators[definition.name].setjiTime(jiTime) window.mqlIndicators[definition.name].setjiOpenInit(jiOpenInit) window.mqlIndicators[definition.name].setjiOpen(jiOpen) window.mqlIndicators[definition.name].setjiHighInit(jiHighInit) window.mqlIndicators[definition.name].setjiHigh(jiHigh) window.mqlIndicators[definition.name].setjiLowInit(jiLowInit) window.mqlIndicators[definition.name].setjiLow(jiLow) window.mqlIndicators[definition.name].setjiCloseInit(jiCloseInit) window.mqlIndicators[definition.name].setjiClose(jiClose) window.mqlIndicators[definition.name].setjiVolumeInit(jiVolumeInit) window.mqlIndicators[definition.name].setjiVolume(jiVolume) window.mqlIndicators[definition.name].setjiHighest(jiHighest) window.mqlIndicators[definition.name].setjiLowest(jiLowest) window.mqlIndicators[definition.name].setjiACInit(jiACInit) window.mqlIndicators[definition.name].setjiAC(jiAC) window.mqlIndicators[definition.name].setjiADXInit(jiADXInit) window.mqlIndicators[definition.name].setjiADX(jiADX) window.mqlIndicators[definition.name].setjiAlligatorInit(jiAlligatorInit) window.mqlIndicators[definition.name].setjiAlligator(jiAlligator) window.mqlIndicators[definition.name].setjiAOInit(jiAOInit) window.mqlIndicators[definition.name].setjiAO(jiAO) window.mqlIndicators[definition.name].setjiATRInit(jiATRInit) window.mqlIndicators[definition.name].setjiATR(jiATR) window.mqlIndicators[definition.name].setjiBearsPowerInit(jiBearsPowerInit) window.mqlIndicators[definition.name].setjiBearsPower(jiBearsPower) window.mqlIndicators[definition.name].setjiBandsInit(jiBandsInit) window.mqlIndicators[definition.name].setjiBands(jiBands) window.mqlIndicators[definition.name].setjiBandsOnArray(jiBandsOnArray) window.mqlIndicators[definition.name].setjiBullsPowerInit(jiBullsPowerInit) window.mqlIndicators[definition.name].setjiBullsPower(jiBullsPower) window.mqlIndicators[definition.name].setjiCCIInit(jiCCIInit) window.mqlIndicators[definition.name].setjiCCI(jiCCI) window.mqlIndicators[definition.name].setjiCCIOnArray(jiCCIOnArray) window.mqlIndicators[definition.name].setjiCustomInit(jiCustomInit) window.mqlIndicators[definition.name].setjiCustom(jiCustom) window.mqlIndicators[definition.name].setjiDeMarkerInit(jiDeMarkerInit) window.mqlIndicators[definition.name].setjiDeMarker(jiDeMarker) window.mqlIndicators[definition.name].setjiEnvelopesInit(jiEnvelopesInit) window.mqlIndicators[definition.name].setjiEnvelopes(jiEnvelopes) window.mqlIndicators[definition.name].setjiEnvelopesOnArray(jiEnvelopesOnArray) window.mqlIndicators[definition.name].setjiFractalsInit(jiFractalsInit) window.mqlIndicators[definition.name].setjiFractals(jiFractals) window.mqlIndicators[definition.name].setjiIchimokuInit(jiIchimokuInit) window.mqlIndicators[definition.name].setjiIchimoku(jiIchimoku) window.mqlIndicators[definition.name].setjiMAInit(jiMAInit) window.mqlIndicators[definition.name].setjiMA(jiMA) window.mqlIndicators[definition.name].setjiMAOnArray(jiMAOnArray) window.mqlIndicators[definition.name].setjiMACDInit(jiMACDInit) window.mqlIndicators[definition.name].setjiMACD(jiMACD) window.mqlIndicators[definition.name].setjiMFIInit(jiMFIInit) window.mqlIndicators[definition.name].setjiMFI(jiMFI) window.mqlIndicators[definition.name].setjiMomentumInit(jiMomentumInit) window.mqlIndicators[definition.name].setjiMomentum(jiMomentum) window.mqlIndicators[definition.name].setjiMomentumOnArray(jiMomentumOnArray) window.mqlIndicators[definition.name].setjiRSIInit(jiRSIInit) window.mqlIndicators[definition.name].setjiRSI(jiRSI) window.mqlIndicators[definition.name].setjiRSIOnArray(jiRSIOnArray) window.mqlIndicators[definition.name].setjiRVIInit(jiRVIInit) window.mqlIndicators[definition.name].setjiRVI(jiRVI) window.mqlIndicators[definition.name].setjiSARInit(jiSARInit) window.mqlIndicators[definition.name].setjiSAR(jiSAR) window.mqlIndicators[definition.name].setjiStochasticInit(jiStochasticInit) window.mqlIndicators[definition.name].setjiStochastic(jiStochastic) window.mqlIndicators[definition.name].setjiWPRInit(jiWPRInit) window.mqlIndicators[definition.name].setjiWPR(jiWPR) window.mqlIndicators[definition.name].setjMarketInfo(jMarketInfo) var monitorMemory = function () { for (var i in window.mqlIndicatorsBuffer) { var obj = window.mqlIndicatorsBuffer[i] var module = window.mqlIndicators[obj.name].module if (obj.time == obj.mTime) { for (var j in obj.dataInput) { module._free(obj.dataInput[j]) } for (var j in obj.dataOutput) { module._free(obj.dataOutput[j]) } delete window.mqlIndicatorsBuffer[i] } else { obj.mTime = obj.time } } setTimeout(monitorMemory, 30000) } setTimeout(monitorMemory, 30000) rs(definition) }) // Module["onRuntimeInitialized"] }) .catch(function () { rj() }) }) }, saveMqlIndicator: function (definition, bAdd) { if (typeof localStorage.reservedZone == "undefined") { if (bAdd) { localStorage.reservedZone = JSON.stringify({allMqlIndis: [definition]}) } } else { var reservedZone = JSON.parse(localStorage.reservedZone) if (typeof reservedZone.allMqlIndis == "undefined") { if (bAdd) { reservedZone.allMqlIndis = [definition] } } else { for (var i in reservedZone.allMqlIndis) { if (reservedZone.allMqlIndis[i].name == definition.name) { reservedZone.allMqlIndis.splice(i, 1) break } } if (bAdd) { reservedZone.allMqlIndis.push(definition) } } localStorage.reservedZone = JSON.stringify(reservedZone) } }, createMqlEA: function (definition) { var parameters = [] parameters.push({ name: "symbol", value: "EUR/USD", required: true, type: PARAMETER_TYPE.STRING, range: null }) parameters.push({ name: "timeframe", value: TIME_FRAME.M1, required: true, type: PARAMETER_TYPE.STRING, range: null }) for (var i in definition.parameters) { parameters.push(definition.parameters[i]) } importBuiltInEA( definition.name, definition.description, parameters, function (context) { // Init() var eaName = getEAName(context) if (typeof window.mqlEAs == "undefined" || typeof window.mqlEAs[eaName] == "undefined") { throw new Error("Please start MQL EA loader plugin.") } var uid = null if (typeof context.uid == "undefined") { uid = window.mqlEAUID++ context.uid = uid } else { uid = context.uid } var eaObj = window.mqlEAs[eaName] var currDefinition = eaObj.definition var nByteDouble = 8 var nByteString = 1 var length = 1 var buffer = null for (var i in currDefinition.parameters) { if (currDefinition.parameters[i].type == PARAMETER_TYPE.INTEGER) { eaObj.setParamInt(uid, getEAParameter(context, currDefinition.parameters[i].name)) } else if (currDefinition.parameters[i].type == PARAMETER_TYPE.NUMBER) { eaObj.setParamDouble(uid, getEAParameter(context, currDefinition.parameters[i].name)) } else if (currDefinition.parameters[i].type == PARAMETER_TYPE.BOOLEAN) { eaObj.setParamBool(uid, getEAParameter(context, currDefinition.parameters[i].name)) } else if (currDefinition.parameters[i].type == PARAMETER_TYPE.STRING) { var eaStrParam = getEAParameter(context, currDefinition.parameters[i].name) if (eaStrParam == null) { eaStrParam = "" } eaObj.setParamString(uid, eaStrParam) } } if (typeof window.mqlEAsBuffer[uid + ""] == "undefined") { var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) var symbolName = getEAParameter(context, "symbol") var timeFrame = getEAParameter(context, "timeframe") window.mqlEAsBuffer[uid + ""] = { name: currDefinition.name, context: context, brokerName: brokerName, accountId: accountId, symbolName: symbolName, timeFrame: timeFrame, chartId: getChartHandle(context, brokerName, accountId, symbolName, timeFrame), symbol: getSymbolInfo(brokerName, accountId, symbolName), objs: (typeof localStorage.mqlObjs != "undefined" ? JSON.parse(localStorage.mqlObjs) : []), neuralNetworks: [], bPreventCleanUp: false, lock: false, convertTimeFrame: function () { if (TIME_FRAME.M1 == timeFrame) { return 1 } else if (TIME_FRAME.M5 == timeFrame) { return 5 } else if (TIME_FRAME.M15 == timeFrame) { return 15 } else if (TIME_FRAME.M30 == timeFrame) { return 30 } else if (TIME_FRAME.H1 == timeFrame) { return 60 } else if (TIME_FRAME.H4 == timeFrame) { return 240 } else if (TIME_FRAME.D == timeFrame) { return 1440 } else if (TIME_FRAME.W == timeFrame) { return 10080 } else if (TIME_FRAME.M == timeFrame) { return 43200 } else { return 0 } } } getQuotes (context, brokerName, accountId, symbolName) } eaObj.onTick(uid, 10000, 0, 0, 1.0 / window.mqlEAsBuffer[uid + ""].symbol.toFixed, Math.log10(window.mqlEAsBuffer[uid + ""].symbol.toFixed)) eaObj.onInit(uid) }, function (context) { // Deinit() var eaName = getEAName(context) var eaObj = window.mqlEAs[eaName] eaObj.onDeinit(context.uid, 0) if (!window.mqlEAsBuffer[context.uid + ""].bPreventCleanUp) { delete window.mqlEAsBuffer[context.uid + ""] } }, function (context) { // OnTick() var eaName = getEAName(context) if (typeof window.mqlEAs == "undefined" || typeof window.mqlEAs[eaName] == "undefined") { return } var uid = context.uid if (typeof window.mqlEAsBuffer[uid + ""] == "undefined" || window.mqlEAsBuffer[uid + ""].lock) { return } var buffObj = window.mqlEAsBuffer[uid + ""] buffObj.context = context var brokerName = buffObj.brokerName var accountId = buffObj.accountId var symbolName = buffObj.symbolName var tData = getData(context, buffObj.chartId, DATA_NAME.TIME) 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 } window.mqlEAs[eaName].onTick( uid, tData.length, ask, bid, 1.0 / buffObj.symbol.toFixed, Math.log10(buffObj.symbol.toFixed) ) } ) // registerEA }, removeMqlEA: function (name) { unregisterEA(name) if (typeof window.mqlEAs == "undefined" || typeof window.mqlEAsBuffer == "undefined") return delete window.mqlEAs[name] for (var i in window.mqlEAsBuffer) { if (window.mqlEAsBuffer[i].name == name) { delete window.mqlEAsBuffer[i] break } } }, loadMqlEA: function (definition) { return new Promise(function (rs, rj) { var scriptPromise = new Promise(function (resolve, reject) { 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") == definition.url) { tags[i].parentNode.removeChild(tags[i]) break } } var script = document.createElement("script") document.body.appendChild(script) script.onload = resolve script.onerror = reject script.async = true script.src = definition.url }) scriptPromise.then(function () { EAPlugIn().then(function (Module) { if (typeof window.mqlEAs == "undefined") { window.mqlEAs = [] window.mqlEAsBuffer = [] window.mqlEAUID = 0 } var jChartClose = Module.addFunction(function (uid, chart_id) { if (chart_id == 0) { return removeChart(window.mqlEAsBuffer[uid + ""].chartId) } else { return removeChart(chart_id) } }, "iii") var jChartID = Module.addFunction(function (uid) { return window.mqlEAsBuffer[uid + ""].chartId }, "ii") var jChartOpen = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jChartPeriod = Module.addFunction(function (uid, chart_id) { var obj = window.mqlEAsBuffer[uid + ""] if (chart_id == 0) { return obj.convertTimeFrame(obj.timeFrame) } else { return obj.convertTimeFrame(getChartTimeFrame(chart_id)) } }, "iii") var jChartSymbol = Module.addFunction(function (uid, chart_id) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = "" if (chart_id == 0) { symbolName = obj.symbolName } else { symbolName = getChartSymbolName(chart_id) } var lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(symbolName) + 1 var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes) window.mqlEAs[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "iii") var jPeriod = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return obj.convertTimeFrame(obj.timeFrame) }, "ii") var jSymbol = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = obj.symbolName var lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(symbolName) + 1 var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes) window.mqlEAs[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "ii") var jAccountBalance = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) return getBalanceOfAccount(account) }, "di") var jAccountCompany = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) var brokerName = getBrokerNameOfAccount(account) var lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(brokerName) + 1 var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes) window.mqlEAs[obj.name].module.stringToUTF8(brokerName, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "ii") var jAccountCurrency = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) var currency = getCurrencyOfAccount(account) var lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(currency) + 1 var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes) window.mqlEAs[obj.name].module.stringToUTF8(currency, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "ii") var jAccountEquity = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) return getEquityOfAccount(account) }, "di") var jAccountFreeMargin = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) return getMarginAvailableOfAccount(account) }, "di") var jAccountMargin = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) return getMarginUsedOfAccount(account) }, "di") var jAccountProfit = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var account = getAccount(obj.context, 0) return getUnrealizedPLOfAccount(account) }, "di") var jOrdersTotal = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getOrdersTradesListLength(obj.context) }, "ii") var jOrdersHistoryTotal = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getHistoryPoolLength(obj.context) }, "ii") var jOrderSelect = Module.addFunction(function (uid, index, select, pool) { var obj = window.mqlEAsBuffer[uid + ""] try { var orderOrTrade = null if (select == 1) { if (pool == 2) { orderOrTrade = getOrderOrTradeFromHistoryByIndex(obj.context, index) } else { orderOrTrade = getOrderOrTradeByIndex(obj.context, index) } } else { if (pool == 2) { orderOrTrade = getOrderOrTradeFromHistoryById(obj.context, index + "") } else { orderOrTrade = getOrderOrTradeById(obj.context, index + "") } } obj.orderOrTrade = orderOrTrade.orderOrTrade obj.type = orderOrTrade.type return 1 } catch(e) { return 0 } }, "iiiii") var jOrderOpenPrice = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getOrderTradePrice(obj.orderOrTrade) }, "di") var jOrderType = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var orderType = getOrderType(obj.orderOrTrade) if ("BUY" == orderType) { return 0; } else if ("SELL" == orderType) { return 1; } else if ("BUY LIMIT" == orderType) { return 2; } else if ("SELL LIMIT" == orderType) { return 3; } else if ("BUY STOP" == orderType) { return 4; } else { return 5; } }, "ii") var jOrderTakeProfit = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getTakeProfit(obj.orderOrTrade) }, "di") var jOrderStopLoss = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getStopLoss(obj.orderOrTrade) }, "di") var jOrderLots = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getOrderTradeLots(obj.orderOrTrade) }, "di") var jOrderProfit = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getPL(obj.orderOrTrade) }, "di") var jOrderSymbol = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = getSymbolName(obj.orderOrTrade) var lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(symbolName) + 1 var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes) window.mqlEAs[obj.name].module.stringToUTF8(symbolName, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "ii") var jOrderTicket = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return parseInt(getId(obj.orderOrTrade)) }, "ii") var jOrderMagicNumber = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getMagicNumber(obj.orderOrTrade) }, "ii") var jOrderOpenTime = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getOrderTradeTime(obj.orderOrTrade) }, "ii") var jOrderComment = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] var comment = getComment(obj.orderOrTrade) var lengthBytes = window.mqlEAs[obj.name].module.lengthBytesUTF8(comment) + 1 var stringOnWasmHeap = window.mqlEAs[obj.name].module._malloc(lengthBytes) window.mqlEAs[obj.name].module.stringToUTF8(comment, stringOnWasmHeap, lengthBytes) return stringOnWasmHeap }, "ii") var jOrderExpiration = Module.addFunction(function (uid) { var obj = window.mqlEAsBuffer[uid + ""] return getExpiration(obj.orderOrTrade) }, "ii") var jOrderPrint = Module.addFunction(function (uid) { var orderOrTrade = window.mqlEAsBuffer[uid + ""].orderOrTrade // todo add more information return printMessage(getId(orderOrTrade) + " " + getOrderTradeTime(orderOrTrade) + " " + getOrderType(orderOrTrade) + " " + getOrderTradeLots(orderOrTrade) + " " + getSymbolName(orderOrTrade) + " " + getOrderTradePrice(orderOrTrade) + " " + getStopLoss(orderOrTrade) + " " + getTakeProfit(orderOrTrade)) }, "vi") var jPrint = Module.addFunction(function (uid, s) { var obj = window.mqlEAsBuffer[uid + ""] printMessage(window.mqlEAs[obj.name].module.UTF8ToString(s)) }, "vii") var jiTimeInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jiTime = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, chartHandle, "Time") return arr[arr.length - shift - 1] }, "iiii") var jiOpenInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jiOpen = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, chartHandle, "Open") return arr[arr.length - shift - 1] }, "diii") var jiHighInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jiHigh = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, chartHandle, "High") return arr[arr.length - shift - 1] }, "diii") var jiLowInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jiLow = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, chartHandle, "Low") return arr[arr.length - shift - 1] }, "diii") var jiCloseInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jiClose = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, chartHandle, "Close") return arr[arr.length - shift - 1] }, "diii") var jiVolumeInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getChartHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm) }, "iiii") var jiVolume = Module.addFunction(function (uid, chartHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, chartHandle, "Volume") return arr[arr.length - shift - 1] }, "iiii") var jiHighest = Module.addFunction(function (uid, chartHandle, mode, count, start) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, chartHandle, md) var highest = -Number.MAX_VALUE var idx = -1 for (var i = start; i < start + count && i >= 0 && i < arr.length; i++) { if (arr[arr.length - i - 1] > highest) { highest = arr[arr.length - i - 1] idx = i } } return idx }, "iiiiii") var jiLowest = Module.addFunction(function (uid, chartHandle, mode, count, start) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, chartHandle, md) var lowest = Number.MAX_VALUE var idx = -1 for (var i = start; i < start + count && i >= 0 && i < arr.length; i++) { if (arr[arr.length - i - 1] < lowest) { lowest = arr[arr.length - i - 1] idx = i } } return idx }, "iiiiii") var jiACInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "ac", []) }, "iiii") var jiAC = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arrUp = getData(obj.context, indiHandle, "up") var arrDown = getData(obj.context, indiHandle, "down") return arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1] }, "diii") var jiADXInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "adx_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiADX = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiAlligatorInit = Module.addFunction(function (uid, symbol, timeframe, jaw_period, jaw_shift, teeth_period, teeth_shift, lips_period, lips_shift, ma_method, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) var method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "alligator_for_mql", [{ name: "jawsPeriod", value: jaw_period },{ name: "jawsShift", value: jaw_shift },{ name: "teethPeriod", value: teeth_period },{ name: "teethShift", value: teeth_shift },{ name: "lipsPeriod", value: lips_period },{ name: "lipsShift", value: lips_shift },{ name: "method", value: method },{ name: "appliedPrice", value: applied_price }]) }, "iiiiiiiiiiii") var jiAlligator = Module.addFunction(function (uid, indiHandle, jaw_shift, teeth_shift, lips_shift, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) if (md == "jaws") { return arr[arr.length - shift - 1] } else if (md == "teeth") { return arr[arr.length - shift - 1] } else { return arr[arr.length - shift - 1] } }, "diiiiiii") var jiAOInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "ao", []) }, "iiii") var jiAO = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arrUp = getData(obj.context, indiHandle, "up") var arrDown = getData(obj.context, indiHandle, "down") return arrUp[arrUp.length - shift - 1] > 0 ? arrUp[arrUp.length - shift - 1] : arrDown[arrDown.length - shift - 1] }, "diii") var jiATRInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "atr", [{ name: "period", value: period }]) }, "iiiii") var jiATR = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "atr") return arr[arr.length - shift - 1] }, "diii") var jiBearsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "bears_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiBearsPower = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "bears") return arr[arr.length - shift - 1] }, "diii") var jiBandsInit = Module.addFunction(function (uid, symbol, timeframe, period, deviation, bands_shift, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "bands_for_mql", [{ name: "period", value: period, },{ name: "deviations", value: deviation, },{ name: "shift", value: bands_shift, },{ name: "method", value: "sma" },{ name: "appliedPrice", value: applied_price, }]) }, "iiiiidii") var jiBands = Module.addFunction(function (uid, indiHandle, bands_shift, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiiii") var jiBandsOnArray = Module.addFunction(function (uid, array, total, period, deviation, bands_shift, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("bands_for_mql", [{ name: "period", value: period, },{ name: "deviations", value: deviation, },{ name: "shift", value: bands_shift, },{ name: "method", value: "sma" },{ name: "appliedPrice", value: 0, }], dataInput, total) var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getDataOnArray(dataOutput, md) return arr[arr.length - shift - 1] }, "diiiidiii") var jiBullsPowerInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "bulls_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiBullsPower = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "bulls") return arr[arr.length - shift - 1] }, "diii") var jiCCIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "cci_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiCCI = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "cci") return arr[arr.length - shift - 1] }, "diii") var jiCCIOnArray = Module.addFunction(function (uid, array, total, period, shift) { var obj = window.mqlEAsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("cci_for_mql", [{ name: "period", value: period, },{ name: "appliedPrice", value: 0, }], dataInput, total) var arr = getDataOnArray(dataOutput, "cci") return arr[arr.length - shift - 1] }, "diiiii") var jiCustomInit = Module.addFunction(function (uid, symbol, timeframe, name, paramString) { var obj = window.mqlEAsBuffer[uid + ""] var indiName = window.mqlEAs[obj.name].module.UTF8ToString(name) if (typeof window.mqlIndicators == "undefined" || typeof window.mqlIndicators[indiName] == "undefined") { throw new Error("Please start MQL indicator loader plugin and load the specific indicator(" + indiName + ").") } var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) var params = window.mqlEAs[obj.name].module.UTF8ToString(paramString).split("|||") symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm var parameters = JSON.parse(JSON.stringify(window.mqlIndicators[indiName].definition.parameters)) for (var i in parameters) { if (isInteger(params[i])) { parameters[i].value = parseInt(params[i]) } else if (isNumeric(params[i])) { parameters[i].value = parseFloat(params[i]) } else if (params[i] == "true") { parameters[i].value = true } else if (params[i] == "false") { parameters[i].value = false } else { parameters[i].value = params[i] } } return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, indiName, parameters) }, "iiiiii") var jiCustom = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiDeMarkerInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "demarker", [{ name: "period", value: period }]) }, "iiiii") var jiDeMarker = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "demarker") return arr[arr.length - shift - 1] }, "diii") var jiEnvelopesInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_method, ma_shift, applied_price, deviation) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) var method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "envelopes_for_mql", [{ name: "period", value: ma_period },{ name: "deviations", value: deviation },{ name: "shift", value: ma_shift },{ name: "method", value: method },{ name: "appliedPrice", value: applied_price }]) }, "iiiiiiiid") var jiEnvelopes = Module.addFunction(function (uid, indiHandle, ma_shift, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiiii") var jiEnvelopesOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_method, ma_shift, deviation, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method) var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("envelopes_for_mql", [{ name: "period", value: ma_period },{ name: "deviations", value: deviation },{ name: "shift", value: ma_shift },{ name: "method", value: method },{ name: "appliedPrice", value: 0 }], dataInput, total) var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getDataOnArray(dataOutput, md) return arr[arr.length - shift - 1] }, "diiiiiidii") var jiFractalsInit = Module.addFunction(function (uid, symbol, timeframe) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "fractals", []) }, "iiii") var jiFractals = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiIchimokuInit = Module.addFunction(function (uid, symbol, timeframe, tenkan_sen, kijun_sen, senkou_span_b) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "ichimoku", [{ name: "tenkan", value: tenkan_sen },{ name: "kijun", value: kijun_sen },{ name: "senkou", value: senkou_span_b }]) }, "iiiiiii") var jiIchimoku = Module.addFunction(function (uid, indiHandle, ichimoku_shift, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiiii") var jiMAInit = Module.addFunction(function (uid, symbol, timeframe, ma_period, ma_shift, ma_method, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm var params = [{ name: "period", value: ma_period },{ name: "shift", value: ma_shift },{ name: "appliedPrice", value: applied_price }] if (ma_method == 1) { return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "ema_for_mql", params) } else if (ma_method == 2) { return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "smma_for_mql", params) } else if (ma_method == 3) { return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "lwma_for_mql", params) } else { return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "sma_for_mql", params) } }, "iiiiiiii") var jiMA = Module.addFunction(function (uid, indiHandle, ma_shift, ma_method, shift) { var obj = window.mqlEAsBuffer[uid + ""] var method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method) var arr = getData(obj.context, indiHandle, method) return arr[arr.length - shift - 1] }, "diiiii") var jiMAOnArray = Module.addFunction(function (uid, array, total, ma_period, ma_shift, ma_method, shift) { var obj = window.mqlEAsBuffer[uid + ""] var method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method) var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = null var params = [{ name: "period", value: ma_period },{ name: "shift", value: ma_shift },{ name: "appliedPrice", value: 0 }] if (method == "ema") { dataOutput = calcIndicatorOnArray("ema_for_mql", params, dataInput, total) } else if (method == "smma") { dataOutput = calcIndicatorOnArray("smma_for_mql", params, dataInput, total) } else if (method == "lwma") { dataOutput = calcIndicatorOnArray("lwma_for_mql", params, dataInput, total) } else { dataOutput = calcIndicatorOnArray("sma_for_mql", params, dataInput, total) } var arr = getDataOnArray(dataOutput, method) return arr[arr.length - shift - 1] }, "diiiiiii") var jiMACDInit = Module.addFunction(function (uid, symbol, timeframe, fast_ema_period, slow_ema_period, signal_period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "macd_for_mql", [{ name: "fastEMA", value: fast_ema_period },{ name: "slowEMA", value: slow_ema_period },{ name: "signalSMA", value: signal_period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiiiii") var jiMACD = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiMFIInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "mfi", [{ name: "period", value: period }]) }, "iiiiiiii") var jiMFI = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "mfi") return arr[arr.length - shift - 1] }, "diiii") var jiMomentumInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "momentum_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiMomentum = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "momentum") return arr[arr.length - shift - 1] }, "diii") var jiMomentumOnArray = Module.addFunction(function (uid, array, total, period, shift) { var obj = window.mqlEAsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("momentum_for_mql", [{ name: "period", value: period, },{ name: "appliedPrice", value: 0, }], dataInput, total) var arr = getDataOnArray(dataOutput, "momentum") return arr[arr.length - shift - 1] }, "diiiii") var jiRSIInit = Module.addFunction(function (uid, symbol, timeframe, period, applied_price) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "rsi_for_mql", [{ name: "period", value: period },{ name: "appliedPrice", value: applied_price }]) }, "iiiiii") var jiRSI = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "rsi") return arr[arr.length - shift - 1] }, "diii") var jiRSIOnArray = Module.addFunction(function (uid, array, total, period, shift) { var obj = window.mqlEAsBuffer[uid + ""] var nByteDouble = 8 var data = new Array(total) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(array + i * nByteDouble, "double") } var dataInput = [] dataInput[0] = data var dataOutput = calcIndicatorOnArray("rsi_for_mql", [{ name: "period", value: period, },{ name: "appliedPrice", value: 0, }], dataInput, total) var arr = getDataOnArray(dataOutput, "rsi") return arr[arr.length - shift - 1] }, "diiiii") var jiRVIInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "rvi", [{ name: "period", value: period }]) }, "iiiii") var jiRVI = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiSARInit = Module.addFunction(function (uid, symbol, timeframe, step, maximum) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "sar", [{ name: "acceleration", value: step, },{ name: "afMax", value: maximum, }]) }, "iiiidd") var jiSAR = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "sar") return arr[arr.length - shift - 1] }, "diii") var jiStochasticInit = Module.addFunction(function (uid, symbol, timeframe, Kperiod, Dperiod, slowing, ma_method) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) var method = window.mqlEAs[obj.name].module.UTF8ToString(ma_method) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "stochastic", [{ name: "KPeriod", value: Kperiod },{ name: "slowing", value: slowing },{ name: "DPeriod", value: Dperiod },{ name: "method", value: method }]) }, "iiiiiiii") var jiStochastic = Module.addFunction(function (uid, indiHandle, mode, shift) { var obj = window.mqlEAsBuffer[uid + ""] var md = window.mqlEAs[obj.name].module.UTF8ToString(mode) var arr = getData(obj.context, indiHandle, md) return arr[arr.length - shift - 1] }, "diiii") var jiWPRInit = Module.addFunction(function (uid, symbol, timeframe, period) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var timeFrm = window.mqlEAs[obj.name].module.UTF8ToString(timeframe) symbolName = symbolName == "" ? obj.symbolName : symbolName timeFrm = timeFrm == "0" ? obj.timeFrame : timeFrm return getIndicatorHandle(obj.context, obj.brokerName, obj.accountId, symbolName, timeFrm, "wpr", [{ name: "period", value: period }]) }, "iiiii") var jiWPR = Module.addFunction(function (uid, indiHandle, shift) { var obj = window.mqlEAsBuffer[uid + ""] var arr = getData(obj.context, indiHandle, "wpr") return arr[arr.length - shift - 1] }, "diii") var jObjectCreate = Module.addFunction(function (uid, chart_id, object_name, object_type, time, price, time2, price2) { var obj = window.mqlEAsBuffer[uid + ""] var name = window.mqlEAs[obj.name].module.UTF8ToString(object_name) if (object_type == 1) { // OBJ_ARROW_CHECK var objId = addSignal(chart_id, name, time, price) if (objId != -1) { obj.objs.push({id: objId, chartId: chart_id, name: name}) localStorage.mqlObjs = JSON.stringify(obj.objs) return 1 } else { return 0 } } else if (object_type == 2) { // OBJ_TREND var objId = addTrendLine(chart_id, name, time, price, time2, price2) if (objId != -1) { obj.objs.push({id: objId, chartId: chart_id, name: name}) localStorage.mqlObjs = JSON.stringify(obj.objs) return 1 } else { return 0 } } else { return 0 } }, "iiiiiidid") var jObjectDelete = Module.addFunction(function (uid, object_name) { var obj = window.mqlEAsBuffer[uid + ""] var name = window.mqlEAs[obj.name].module.UTF8ToString(object_name) var success = false for (var i = obj.objs.length - 1; i >= 0; i--) { if (obj.objs[i].name == name) { if (removeObject(obj.objs[i].chartId, obj.objs[i].id)) { success = true obj.objs.splice(i, 1) } break } } if (success) { localStorage.mqlObjs = JSON.stringify(obj.objs) return 1 } else { return 0 } }, "iii") var jObjectGet = Module.addFunction(function (uid, object_name, property_index) { var obj = window.mqlEAsBuffer[uid + ""] var name = window.mqlEAs[obj.name].module.UTF8ToString(object_name) for (var i = obj.objs.length - 1; i >= 0; i--) { if (obj.objs[i].name == name) { if (property_index == 0) { // OBJPROP_TIME1 return getObjectPropTime1(obj.objs[i].chartId, obj.objs[i].id) } else if (property_index == 1) { // OBJPROP_PRICE1 return getObjectPropPrice1(obj.objs[i].chartId, obj.objs[i].id) } else if (property_index == 2) { // OBJPROP_TIME2 return getObjectPropTime2(obj.objs[i].chartId, obj.objs[i].id) } else if (property_index == 3) { // OBJPROP_PRICE2 return getObjectPropPrice2(obj.objs[i].chartId, obj.objs[i].id) } } } return -1 }, "diii") var jObjectSet = Module.addFunction(function (uid, object_name, property_index, property_value) { var obj = window.mqlEAsBuffer[uid + ""] var name = window.mqlEAs[obj.name].module.UTF8ToString(object_name) for (var i = obj.objs.length - 1; i >= 0; i--) { if (obj.objs[i].name == name) { if (property_index == 0) { // OBJPROP_TIME1 if (setObjectPropTime1(obj.objs[i].chartId, obj.objs[i].id, property_value)) { return 1 } } else if (property_index == 1) { // OBJPROP_PRICE1 if (setObjectPropPrice1(obj.objs[i].chartId, obj.objs[i].id, property_value)) { return 1 } } else if (property_index == 2) { // OBJPROP_TIME2 if (setObjectPropTime2(obj.objs[i].chartId, obj.objs[i].id, property_value)) { return 1 } } else if (property_index == 3) { // OBJPROP_PRICE2 if (setObjectPropPrice2(obj.objs[i].chartId, obj.objs[i].id, property_value)) { return 1 } } } } return 0 }, "iiiid") var jIsTesting = Module.addFunction(function () { return isTesting() ? 1 : 0 }, "i") var jMarketInfo = Module.addFunction(function (uid, symbol, type) { var obj = window.mqlEAsBuffer[uid + ""] var symbolName = window.mqlEAs[obj.name].module.UTF8ToString(symbol) var symbolObj = null if (symbolName == "") { symbolObj = obj.symbol } else { symbolObj = getSymbolInfo(obj.brokerName, obj.accountId, symbolName) } if (type == 11) { return 1.0 / symbolObj.toFixed } else if (type == 12) { return Math.log10(symbolObj.toFixed) } else if (type == 18) { return symbolObj.swapLong } else if (type == 19) { return symbolObj.swapShort } else if (type == 22) { return symbolObj.tradable } else if (type == 23) { return symbolObj.lotsMinLimit } else if (type == 24) { return symbolObj.lotsStep } else if (type == 25) { return symbolObj.lotsLimit } printErrorMessage("Not supported the specific market information currently!") return -1 }, "diii") var jCreateNeuralNetwork = Module.addFunction(function (uid, name, nnJson) { var obj = window.mqlEAsBuffer[uid + ""] var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name) var neuralNetworkJson = window.mqlEAs[obj.name].module.UTF8ToString(nnJson) if (nnName != "" && neuralNetworkJson != "" && typeof obj.neuralNetworks[nnName] == "undefined") { obj.neuralNetworks[nnName] = { perceptron: synaptic.Network.fromJSON(JSON.parse(neuralNetworkJson)) } return 1 } else { return 0 } }, "iiii") var jActivateNeuralNetwork = Module.addFunction(function (uid, name, input, inputNum) { var obj = window.mqlEAsBuffer[uid + ""] var nnName = window.mqlEAs[obj.name].module.UTF8ToString(name) var nByteDouble = 8 var data = new Array(inputNum) for (var i = 0; i < data.length; i++) { data[i] = window.mqlEAs[obj.name].module.getValue(input + i * nByteDouble, "double") } if (typeof obj.neuralNetworks[nnName] != "undefined" && typeof obj.neuralNetworks[nnName].perceptron != "undefined") { return obj.neuralNetworks[nnName].perceptron.activate(data)[0] } else { return 0.5 } }, "diiii") window.mqlEAs[definition.name] = { definition: definition, module: Module, setParamInt: Module.cwrap("setParamInt", null, ["number", "number"]), setParamDouble: Module.cwrap("setParamDouble", null, ["number", "number"]), setParamBool: Module.cwrap("setParamBool", null, ["number", "number"]), setParamString: Module.cwrap("setParamString", null, ["number", "string"]), onInit: Module.cwrap("onInit", null, ["number"]), onDeinit: Module.cwrap("onDeinit", null, ["number", "number"]), onTick: Module.cwrap("onTick", null, ["number", "number", "number", "number", "number", "number"]), setjPrint: Module.cwrap("setjPrint", null, ["number"]), setjChartClose: Module.cwrap("setjChartClose", null, ["number"]), setjChartID: Module.cwrap("setjChartID", null, ["number"]), setjChartOpen: Module.cwrap("setjChartOpen", null, ["number"]), setjChartPeriod: Module.cwrap("setjChartPeriod", null, ["number"]), setjChartSymbol: Module.cwrap("setjChartSymbol", null, ["number"]), setjPeriod: Module.cwrap("setjPeriod", null, ["number"]), setjSymbol: Module.cwrap("setjSymbol", null, ["number"]), setjAccountBalance: Module.cwrap("setjAccountBalance", null, ["number"]), setjAccountCompany: Module.cwrap("setjAccountCompany", null, ["number"]), setjAccountCurrency: Module.cwrap("setjAccountCurrency", null, ["number"]), setjAccountEquity: Module.cwrap("setjAccountEquity", null, ["number"]), setjAccountFreeMargin: Module.cwrap("setjAccountFreeMargin", null, ["number"]), setjAccountMargin: Module.cwrap("setjAccountMargin", null, ["number"]), setjAccountProfit: Module.cwrap("setjAccountProfit", null, ["number"]), setjOrdersTotal: Module.cwrap("setjOrdersTotal", null, ["number"]), setjOrdersHistoryTotal: Module.cwrap("setjOrdersHistoryTotal", null, ["number"]), setjOrderSelect: Module.cwrap("setjOrderSelect", null, ["number"]), setjOrderOpenPrice: Module.cwrap("setjOrderOpenPrice", null, ["number"]), setjOrderType: Module.cwrap("setjOrderType", null, ["number"]), setjOrderTakeProfit: Module.cwrap("setjOrderTakeProfit", null, ["number"]), setjOrderStopLoss: Module.cwrap("setjOrderStopLoss", null, ["number"]), setjOrderLots: Module.cwrap("setjOrderLots", null, ["number"]), setjOrderProfit: Module.cwrap("setjOrderProfit", null, ["number"]), setjOrderSymbol: Module.cwrap("setjOrderSymbol", null, ["number"]), setjOrderTicket: Module.cwrap("setjOrderTicket", null, ["number"]), setjOrderMagicNumber: Module.cwrap("setjOrderMagicNumber", null, ["number"]), setjOrderOpenTime: Module.cwrap("setjOrderOpenTime", null, ["number"]), setjOrderComment: Module.cwrap("setjOrderComment", null, ["number"]), setjOrderExpiration: Module.cwrap("setjOrderExpiration", null, ["number"]), setjOrderPrint: Module.cwrap("setjOrderPrint", null, ["number"]), setjiTimeInit: Module.cwrap("setjiTimeInit", null, ["number"]), setjiTime: Module.cwrap("setjiTime", null, ["number"]), setjiOpenInit: Module.cwrap("setjiOpenInit", null, ["number"]), setjiOpen: Module.cwrap("setjiOpen", null, ["number"]), setjiHighInit: Module.cwrap("setjiHighInit", null, ["number"]), setjiHigh: Module.cwrap("setjiHigh", null, ["number"]), setjiLowInit: Module.cwrap("setjiLowInit", null, ["number"]), setjiLow: Module.cwrap("setjiLow", null, ["number"]), setjiCloseInit: Module.cwrap("setjiCloseInit", null, ["number"]), setjiClose: Module.cwrap("setjiClose", null, ["number"]), setjiVolumeInit: Module.cwrap("setjiVolumeInit", null, ["number"]), setjiVolume: Module.cwrap("setjiVolume", null, ["number"]), setjiHighest: Module.cwrap("setjiHighest", null, ["number"]), setjiLowest: Module.cwrap("setjiLowest", null, ["number"]), setjiACInit: Module.cwrap("setjiACInit", null, ["number"]), setjiAC: Module.cwrap("setjiAC", null, ["number"]), setjiADXInit: Module.cwrap("setjiADXInit", null, ["number"]), setjiADX: Module.cwrap("setjiADX", null, ["number"]), setjiAlligatorInit: Module.cwrap("setjiAlligatorInit", null, ["number"]), setjiAlligator: Module.cwrap("setjiAlligator", null, ["number"]), setjiAOInit: Module.cwrap("setjiAOInit", null, ["number"]), setjiAO: Module.cwrap("setjiAO", null, ["number"]), setjiATRInit: Module.cwrap("setjiATRInit", null, ["number"]), setjiATR: Module.cwrap("setjiATR", null, ["number"]), setjiBearsPowerInit: Module.cwrap("setjiBearsPowerInit", null, ["number"]), setjiBearsPower: Module.cwrap("setjiBearsPower", null, ["number"]), setjiBandsInit: Module.cwrap("setjiBandsInit", null, ["number"]), setjiBands: Module.cwrap("setjiBands", null, ["number"]), setjiBandsOnArray: Module.cwrap("setjiBandsOnArray", null, ["number"]), setjiBullsPowerInit: Module.cwrap("setjiBullsPowerInit", null, ["number"]), setjiBullsPower: Module.cwrap("setjiBullsPower", null, ["number"]), setjiCCIInit: Module.cwrap("setjiCCIInit", null, ["number"]), setjiCCI: Module.cwrap("setjiCCI", null, ["number"]), setjiCCIOnArray: Module.cwrap("setjiCCIOnArray", null, ["number"]), setjiCustomInit: Module.cwrap("setjiCustomInit", null, ["number"]), setjiCustom: Module.cwrap("setjiCustom", null, ["number"]), setjiDeMarkerInit: Module.cwrap("setjiDeMarkerInit", null, ["number"]), setjiDeMarker: Module.cwrap("setjiDeMarker", null, ["number"]), setjiEnvelopesInit: Module.cwrap("setjiEnvelopesInit", null, ["number"]), setjiEnvelopes: Module.cwrap("setjiEnvelopes", null, ["number"]), setjiEnvelopesOnArray: Module.cwrap("setjiEnvelopesOnArray", null, ["number"]), setjiFractalsInit: Module.cwrap("setjiFractalsInit", null, ["number"]), setjiFractals: Module.cwrap("setjiFractals", null, ["number"]), setjiIchimokuInit: Module.cwrap("setjiIchimokuInit", null, ["number"]), setjiIchimoku: Module.cwrap("setjiIchimoku", null, ["number"]), setjiMAInit: Module.cwrap("setjiMAInit", null, ["number"]), setjiMA: Module.cwrap("setjiMA", null, ["number"]), setjiMAOnArray: Module.cwrap("setjiMAOnArray", null, ["number"]), setjiMACDInit: Module.cwrap("setjiMACDInit", null, ["number"]), setjiMACD: Module.cwrap("setjiMACD", null, ["number"]), setjiMFIInit: Module.cwrap("setjiMFIInit", null, ["number"]), setjiMFI: Module.cwrap("setjiMFI", null, ["number"]), setjiMomentumInit: Module.cwrap("setjiMomentumInit", null, ["number"]), setjiMomentum: Module.cwrap("setjiMomentum", null, ["number"]), setjiMomentumOnArray: Module.cwrap("setjiMomentumOnArray", null, ["number"]), setjiRSIInit: Module.cwrap("setjiRSIInit", null, ["number"]), setjiRSI: Module.cwrap("setjiRSI", null, ["number"]), setjiRSIOnArray: Module.cwrap("setjiRSIOnArray", null, ["number"]), setjiRVIInit: Module.cwrap("setjiRVIInit", null, ["number"]), setjiRVI: Module.cwrap("setjiRVI", null, ["number"]), setjiSARInit: Module.cwrap("setjiSARInit", null, ["number"]), setjiSAR: Module.cwrap("setjiSAR", null, ["number"]), setjiStochasticInit: Module.cwrap("setjiStochasticInit", null, ["number"]), setjiStochastic: Module.cwrap("setjiStochastic", null, ["number"]), setjiWPRInit: Module.cwrap("setjiWPRInit", null, ["number"]), setjiWPR: Module.cwrap("setjiWPR", null, ["number"]), setjObjectCreate: Module.cwrap("setjObjectCreate", null, ["number"]), setjObjectDelete: Module.cwrap("setjObjectDelete", null, ["number"]), setjObjectGet: Module.cwrap("setjObjectGet", null, ["number"]), setjObjectSet: Module.cwrap("setjObjectSet", null, ["number"]), setjIsTesting: Module.cwrap("setjIsTesting", null, ["number"]), setjMarketInfo: Module.cwrap("setjMarketInfo", null, ["number"]), setjCreateNeuralNetwork: Module.cwrap("setjCreateNeuralNetwork", null, ["number"]), setjActivateNeuralNetwork: Module.cwrap("setjActivateNeuralNetwork", null, ["number"]) } window.mqlEAs[definition.name].setjPrint(jPrint) window.mqlEAs[definition.name].setjChartClose(jChartClose) window.mqlEAs[definition.name].setjChartID(jChartID) window.mqlEAs[definition.name].setjChartOpen(jChartOpen) window.mqlEAs[definition.name].setjChartPeriod(jChartPeriod) window.mqlEAs[definition.name].setjChartSymbol(jChartSymbol) window.mqlEAs[definition.name].setjPeriod(jPeriod) window.mqlEAs[definition.name].setjSymbol(jSymbol) window.mqlEAs[definition.name].setjAccountBalance(jAccountBalance) window.mqlEAs[definition.name].setjAccountCompany(jAccountCompany) window.mqlEAs[definition.name].setjAccountCurrency(jAccountCurrency) window.mqlEAs[definition.name].setjAccountEquity(jAccountEquity) window.mqlEAs[definition.name].setjAccountFreeMargin(jAccountFreeMargin) window.mqlEAs[definition.name].setjAccountMargin(jAccountMargin) window.mqlEAs[definition.name].setjAccountProfit(jAccountProfit) window.mqlEAs[definition.name].setjOrdersTotal(jOrdersTotal) window.mqlEAs[definition.name].setjOrdersHistoryTotal(jOrdersHistoryTotal) window.mqlEAs[definition.name].setjOrderSelect(jOrderSelect) window.mqlEAs[definition.name].setjOrderOpenPrice(jOrderOpenPrice) window.mqlEAs[definition.name].setjOrderType(jOrderType) window.mqlEAs[definition.name].setjOrderTakeProfit(jOrderTakeProfit) window.mqlEAs[definition.name].setjOrderStopLoss(jOrderStopLoss) window.mqlEAs[definition.name].setjOrderLots(jOrderLots) window.mqlEAs[definition.name].setjOrderProfit(jOrderProfit) window.mqlEAs[definition.name].setjOrderSymbol(jOrderSymbol) window.mqlEAs[definition.name].setjOrderTicket(jOrderTicket) window.mqlEAs[definition.name].setjOrderMagicNumber(jOrderMagicNumber) window.mqlEAs[definition.name].setjOrderOpenTime(jOrderOpenTime) window.mqlEAs[definition.name].setjOrderComment(jOrderComment) window.mqlEAs[definition.name].setjOrderExpiration(jOrderExpiration) window.mqlEAs[definition.name].setjOrderPrint(jOrderPrint) window.mqlEAs[definition.name].setjiTimeInit(jiTimeInit) window.mqlEAs[definition.name].setjiTime(jiTime) window.mqlEAs[definition.name].setjiOpenInit(jiOpenInit) window.mqlEAs[definition.name].setjiOpen(jiOpen) window.mqlEAs[definition.name].setjiHighInit(jiHighInit) window.mqlEAs[definition.name].setjiHigh(jiHigh) window.mqlEAs[definition.name].setjiLowInit(jiLowInit) window.mqlEAs[definition.name].setjiLow(jiLow) window.mqlEAs[definition.name].setjiCloseInit(jiCloseInit) window.mqlEAs[definition.name].setjiClose(jiClose) window.mqlEAs[definition.name].setjiVolumeInit(jiVolumeInit) window.mqlEAs[definition.name].setjiVolume(jiVolume) window.mqlEAs[definition.name].setjiHighest(jiHighest) window.mqlEAs[definition.name].setjiLowest(jiLowest) window.mqlEAs[definition.name].setjiACInit(jiACInit) window.mqlEAs[definition.name].setjiAC(jiAC) window.mqlEAs[definition.name].setjiADXInit(jiADXInit) window.mqlEAs[definition.name].setjiADX(jiADX) window.mqlEAs[definition.name].setjiAlligatorInit(jiAlligatorInit) window.mqlEAs[definition.name].setjiAlligator(jiAlligator) window.mqlEAs[definition.name].setjiAOInit(jiAOInit) window.mqlEAs[definition.name].setjiAO(jiAO) window.mqlEAs[definition.name].setjiATRInit(jiATRInit) window.mqlEAs[definition.name].setjiATR(jiATR) window.mqlEAs[definition.name].setjiBearsPowerInit(jiBearsPowerInit) window.mqlEAs[definition.name].setjiBearsPower(jiBearsPower) window.mqlEAs[definition.name].setjiBandsInit(jiBandsInit) window.mqlEAs[definition.name].setjiBands(jiBands) window.mqlEAs[definition.name].setjiBandsOnArray(jiBandsOnArray) window.mqlEAs[definition.name].setjiBullsPowerInit(jiBullsPowerInit) window.mqlEAs[definition.name].setjiBullsPower(jiBullsPower) window.mqlEAs[definition.name].setjiCCIInit(jiCCIInit) window.mqlEAs[definition.name].setjiCCI(jiCCI) window.mqlEAs[definition.name].setjiCCIOnArray(jiCCIOnArray) window.mqlEAs[definition.name].setjiCustomInit(jiCustomInit) window.mqlEAs[definition.name].setjiCustom(jiCustom) window.mqlEAs[definition.name].setjiDeMarkerInit(jiDeMarkerInit) window.mqlEAs[definition.name].setjiDeMarker(jiDeMarker) window.mqlEAs[definition.name].setjiEnvelopesInit(jiEnvelopesInit) window.mqlEAs[definition.name].setjiEnvelopes(jiEnvelopes) window.mqlEAs[definition.name].setjiEnvelopesOnArray(jiEnvelopesOnArray) window.mqlEAs[definition.name].setjiFractalsInit(jiFractalsInit) window.mqlEAs[definition.name].setjiFractals(jiFractals) window.mqlEAs[definition.name].setjiIchimokuInit(jiIchimokuInit) window.mqlEAs[definition.name].setjiIchimoku(jiIchimoku) window.mqlEAs[definition.name].setjiMAInit(jiMAInit) window.mqlEAs[definition.name].setjiMA(jiMA) window.mqlEAs[definition.name].setjiMAOnArray(jiMAOnArray) window.mqlEAs[definition.name].setjiMACDInit(jiMACDInit) window.mqlEAs[definition.name].setjiMACD(jiMACD) window.mqlEAs[definition.name].setjiMFIInit(jiMFIInit) window.mqlEAs[definition.name].setjiMFI(jiMFI) window.mqlEAs[definition.name].setjiMomentumInit(jiMomentumInit) window.mqlEAs[definition.name].setjiMomentum(jiMomentum) window.mqlEAs[definition.name].setjiMomentumOnArray(jiMomentumOnArray) window.mqlEAs[definition.name].setjiRSIInit(jiRSIInit) window.mqlEAs[definition.name].setjiRSI(jiRSI) window.mqlEAs[definition.name].setjiRSIOnArray(jiRSIOnArray) window.mqlEAs[definition.name].setjiRVIInit(jiRVIInit) window.mqlEAs[definition.name].setjiRVI(jiRVI) window.mqlEAs[definition.name].setjiSARInit(jiSARInit) window.mqlEAs[definition.name].setjiSAR(jiSAR) window.mqlEAs[definition.name].setjiStochasticInit(jiStochasticInit) window.mqlEAs[definition.name].setjiStochastic(jiStochastic) window.mqlEAs[definition.name].setjiWPRInit(jiWPRInit) window.mqlEAs[definition.name].setjiWPR(jiWPR) window.mqlEAs[definition.name].setjObjectCreate(jObjectCreate) window.mqlEAs[definition.name].setjObjectDelete(jObjectDelete) window.mqlEAs[definition.name].setjObjectGet(jObjectGet) window.mqlEAs[definition.name].setjObjectSet(jObjectSet) window.mqlEAs[definition.name].setjIsTesting(jIsTesting) window.mqlEAs[definition.name].setjMarketInfo(jMarketInfo) window.mqlEAs[definition.name].setjCreateNeuralNetwork(jCreateNeuralNetwork) window.mqlEAs[definition.name].setjActivateNeuralNetwork(jActivateNeuralNetwork) rs(definition) }) // Module["onRuntimeInitialized"] }) .catch(function () { rj() }) }) }, saveMqlEA: function (definition, bAdd) { if (typeof localStorage.reservedZone == "undefined") { if (bAdd) { localStorage.reservedZone = JSON.stringify({allMqlEAs: [definition]}) } } else { var reservedZone = JSON.parse(localStorage.reservedZone) if (typeof reservedZone.allMqlEAs == "undefined") { if (bAdd) { reservedZone.allMqlEAs = [definition] } } else { for (var i in reservedZone.allMqlEAs) { if (reservedZone.allMqlEAs[i].name == definition.name) { reservedZone.allMqlEAs.splice(i, 1) break } } if (bAdd) { reservedZone.allMqlEAs.push(definition) } } localStorage.reservedZone = JSON.stringify(reservedZone) } }, removeScript: function (url) { 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") == url) { tags[i].parentNode.removeChild(tags[i]) break } } }, loadMqlPrograms: function () { var mqlPrograms = [] if (typeof localStorage.reservedZone != "undefined") { var reservedZone = JSON.parse(localStorage.reservedZone) if (typeof reservedZone.allMqlIndis != "undefined") { var mqlIndicatorsLoaded = (typeof window.mqlIndicators != "undefined" ? true : false) var allMqlIndis = reservedZone.allMqlIndis for (var i in allMqlIndis) { var mqlIndi = allMqlIndis[i] mqlPrograms.push({ name: mqlIndi.name, description: mqlIndi.description, type: "Indicator", loaded: ((mqlIndicatorsLoaded && typeof window.mqlIndicators[mqlIndi.name] != "undefined") ? true : false) }) } } if (typeof reservedZone.allMqlEAs != "undefined") { var mqlEAsLoaded = (typeof window.mqlEAs != "undefined" ? true : false) var allMqlEAs = reservedZone.allMqlEAs for (var i in allMqlEAs) { var mqlEA = allMqlEAs[i] mqlPrograms.push({ name: mqlEA.name, description: mqlEA.description, type: "EA", loaded: ((mqlEAsLoaded && typeof window.mqlEAs[mqlEA.name] != "undefined") ? true : false) }) } } } return mqlPrograms }, showMqlPrograms: function (mqlPrograms) { $("#mql_based_programs_list").DataTable().clear().draw() for (var i in mqlPrograms) { var mqlProgram = mqlPrograms[i] var row = $("#mql_based_programs_list").DataTable().row.add([ mqlProgram.name, mqlProgram.description, mqlProgram.type, mqlProgram.loaded ? "Loaded" : "" ]).draw(false) } }, showAddedMqlProgram: function (mqlProgram, type) { var data = $("#mql_based_programs_list").DataTable().rows().data() var rowId = -1 for (var i in data) { if (data[i][0] == mqlProgram.name && data[i][2] == type) { rowId = parseInt(i) break } } if (rowId != -1) { $("#mql_based_programs_list").dataTable().fnUpdate("Loaded", rowId, 3, false, false) } else { $("#mql_based_programs_list").DataTable().row.add([ mqlProgram.name, mqlProgram.description, type, "Loaded" ]).draw(false) } }, showMqlProgramNewState: function (name, type, state) { var data = $("#mql_based_programs_list").DataTable().rows().data() var rowId = -1 for (var i in data) { if (data[i][0] == name && data[i][2] == type) { rowId = parseInt(i) break } } if (rowId != -1) { $("#mql_based_programs_list").dataTable().fnUpdate(state, rowId, 3, false, false) } }, removeMqlProgram: function (name, type) { var data = $("#mql_based_programs_list").DataTable().rows().data() var rowId = -1 for (var i in data) { if (data[i][0] == name && data[i][2] == type) { rowId = parseInt(i) break } } if (rowId != -1) { $("#mql_based_programs_list").dataTable().fnDeleteRow(rowId) } }, getSelected: function () { var selected = [] var mqlPrograms = $("#mql_based_programs_list").DataTable().rows(".selected").data().toArray() for (var i in mqlPrograms) { selected.push({ name: mqlPrograms[i][0], type: mqlPrograms[i][2] }) } return selected }, loadSelected: function (selected) { var allMqlIndis = [] var allMqlEAs = [] if (typeof localStorage.reservedZone != "undefined") { var reservedZone = JSON.parse(localStorage.reservedZone) if (typeof reservedZone.allMqlIndis != "undefined") { allMqlIndis = reservedZone.allMqlIndis } if (typeof reservedZone.allMqlEAs != "undefined") { allMqlEAs = reservedZone.allMqlEAs } } else { return } var that = this for (var i in selected) { var sel = selected[i] if (sel.type == "Indicator") { for (var j in allMqlIndis) { var mqlIndi = allMqlIndis[j] if (sel.name == mqlIndi.name) { this.loadMqlIndicator(mqlIndi) .then(function (definition) { that.showMqlProgramNewState(definition.name, "Indicator", "Loaded") }) .catch(function () {}) } } } else if (sel.type == "EA") { for (var j in allMqlEAs) { var mqlEA = allMqlEAs[j] if (sel.name == mqlEA.name) { this.loadMqlEA(mqlEA) .then(function (definition) { that.showMqlProgramNewState(definition.name, "EA", "Loaded") }) .catch(function () {}) } } } } }, removeSelected: function (selected) { var allMqlIndis = [] var allMqlEAs = [] if (typeof localStorage.reservedZone != "undefined") { var reservedZone = JSON.parse(localStorage.reservedZone) if (typeof reservedZone.allMqlIndis != "undefined") { allMqlIndis = reservedZone.allMqlIndis } if (typeof reservedZone.allMqlEAs != "undefined") { allMqlEAs = reservedZone.allMqlEAs } } else { return } var that = this for (var i in selected) { var sel = selected[i] if (sel.type == "Indicator") { for (var j in allMqlIndis) { var mqlIndi = allMqlIndis[j] if (sel.name == mqlIndi.name) { that.removeMqlIndicator(mqlIndi.name) that.removeMqlProgram(mqlIndi.name, "Indicator") that.saveMqlIndicator(mqlIndi, false) that.removeScript(mqlIndi.url) } } } else if (sel.type == "EA") { for (var j in allMqlEAs) { var mqlEA = allMqlEAs[j] if (sel.name == mqlEA.name) { that.removeMqlEA(mqlEA.name) that.removeMqlProgram(mqlEA.name, "EA") that.saveMqlEA(mqlEA, false) that.removeScript(mqlEA.url) } } } } }, init: function () { var that = this if (typeof $("#mql_based_programs_dashboard").html() == "undefined") { var panel = '' $("#reserved_zone").append(panel) $("#add_mql_indicator").on("click", function () { var def = $("#mqlIndiDefinition").val().trim() if (def != "") { try { that.loadMqlIndicator(JSON.parse(def)) .then(function (definition) { that.createMqlIndicator(definition) that.showAddedMqlProgram(definition, "Indicator") that.saveMqlIndicator(definition, true) }) .catch(function () {}) } catch (e) { popupErrorMessage(e.message) printErrorMessage(e.message) } } }) $("#add_mql_ea").on("click", function () { var def = $("#mqlEADefinition").val().trim() if (def != "") { try { that.loadMqlEA(JSON.parse(def)) .then(function (definition) { that.createMqlEA(definition) that.showAddedMqlProgram(definition, "EA") that.saveMqlEA(definition, true) }) .catch(function () {}) } catch (e) { popupErrorMessage(e.message) printErrorMessage(e.message) } } }) $("#load_mql_programs").on("click", function () { that.loadSelected(that.getSelected()) }) $("#remove_mql_programs").on("click", function () { that.removeSelected(that.getSelected()) }) $("#close_mql_dashboard").on("click", function () { $("#mql_based_programs_dashboard").modal("hide") }) } if (!$.fn.dataTable.isDataTable("#mql_based_programs_list")) { $("#mql_based_programs_list").DataTable({ data: [], columns: [ {title: "Name"}, {title: "Description"}, {title: "Type"}, {title: "State"} ], 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-left"}, {width: "50%", targets: 1, className: "dt-body-left"}, {width: "15%", targets: 2, className: "dt-body-left"}, {width: "15%", targets: 2, className: "dt-body-left"}, {targets: [0, 1, 2, 3], className: "dt-head-left"} ] }) $("#mql_based_programs_list tbody").on("click", "tr", function () { $(this).toggleClass("selected") }) } this.showMqlPrograms(this.loadMqlPrograms()) $("#mql_based_programs_dashboard").modal({autofocus:false}).modal("show") } } window.pluginForMql.init() }, function (context) { // Deinit() }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-MQL/runtestcnn.cpp ================================================ #define INPUT_NUM 10 #define HIDDEN_NUM 10 #define NN_NAME "testcnn" input string ext_strSymbol = "EUR/USD"; input int ext_iPeriod = 60; input double ext_dblVolume = 0.01; datetime currTime = 0; int cntL = 0; int cntS = 0; double totalPlL = 0; double totalPlS = 0; double highestPriceL = -DBL_MAX; double lowestPriceL = DBL_MAX; double highestPriceS = -DBL_MAX; double lowestPriceS = DBL_MAX; datetime upTime = 0; datetime downTime = 0; datetime prevClsUpTime = 0; datetime prevClsDownTime = 0; void getPosInfo(datetime currTime) { cntL = 0; cntS = 0; totalPlL = 0; totalPlS = 0; highestPriceL = -DBL_MAX; lowestPriceL = DBL_MAX; highestPriceS = -DBL_MAX; lowestPriceS = DBL_MAX; int cnt = OrdersTotal(); for (int i = cnt - 1; i >= 0; i--) { if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) return; if (StringCompare(Symbol(), OrderSymbol()) == 0) { double openPrice = OrderOpenPrice(); datetime openTime = OrderOpenTime(); if (OrderType() == OP_BUY) { cntL++; totalPlL += OrderProfit(); if (openPrice > highestPriceL) { highestPriceL = openPrice; } if (openPrice < lowestPriceL) { lowestPriceL = openPrice; } if (openTime > currTime) { upTime = currTime; } } if (OrderType() == OP_SELL) { cntS++; totalPlS += OrderProfit(); if (openPrice > highestPriceS) { highestPriceS = openPrice; } if (openPrice < lowestPriceS) { lowestPriceS = openPrice; } if (openTime > currTime) { downTime = currTime; } } } } } bool trade(int odrType, double volume, bool bOpen) { bool res = false; if (bOpen) { if (odrType == OP_BUY) { OrderSend(ext_strSymbol, OP_BUY, volume, 0, 0, 0, 0, "", 0, 0, Green); res = true; } else if (odrType == OP_SELL) { OrderSend(ext_strSymbol, OP_SELL, volume, 0, 0, 0, 0, "", 0, 0, Red); res = true; } } else { bool bClosed = false; if (odrType == OP_BUY) { int cnt = OrdersTotal(); for (int i = cnt - 1; i >= 0; i--) { if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) return false; if (StringCompare(Symbol(), OrderSymbol()) == 0 && OrderType() == OP_BUY) { OrderClose(OrderTicket(), volume, 0, 0, Green); bClosed = true; } } } else if (odrType == OP_SELL) { int cnt = OrdersTotal(); for (int i = cnt - 1; i >= 0; i--) { if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) return false; if (StringCompare(Symbol(), OrderSymbol()) == 0 && OrderType() == OP_SELL) { OrderClose(OrderTicket(), volume, 0, 0, Red); bClosed = true; } } } if (bClosed) { res = true; } } return res; } int OnInit (void) { PreventCleanUp(); LoadCNN(NN_NAME); return 0; } void OnTick(void) { if (currTime == iTime(ext_strSymbol, ext_iPeriod, 0)) return; currTime = iTime(ext_strSymbol, ext_iPeriod, 0); double arr[INPUT_NUM]; double highest = -DBL_MAX; double lowest = DBL_MAX; for (int i = 1; i <= INPUT_NUM; i++) { arr[i - 1] = iMACD(ext_strSymbol, ext_iPeriod, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, i); if (arr[i - 1] > highest) { highest = arr[i - 1]; } if (arr[i - 1] < lowest) { lowest = arr[i - 1]; } } double height = highest - lowest; if (height <= 0) return; double input[INPUT_NUM]; for (int i = 0; i < INPUT_NUM; i++) { input[i] = (arr[i] - lowest) / height; } double result = RunCNN(NN_NAME, input, INPUT_NUM); int signal = result >= 0.5 ? 1 : 0; getPosInfo(currTime); if (upTime > 0 || downTime > 0) { if (signal == 1) { if (trade(OP_SELL, ext_dblVolume, false)) { downTime = 0; } } else { if (trade(OP_BUY, ext_dblVolume, false)) { upTime = 0; } } return; } if (signal == 1) { if (trade(OP_BUY, ext_dblVolume, true)) { upTime = currTime; } } else { if (trade(OP_SELL, ext_dblVolume, true)) { downTime = currTime; } } } void OnDeinit (const int) { } ================================================ FILE: EA/Plugin-for-MQL/testcnn.cpp ================================================ #define ARR_NUM 1001 #define INPUT_NUM 10 #define HIDDEN_NUM 10 #define NN_NAME "testcnn" #define ITERATIONS 1000 #define BATCH_SIZE 512 input string ext_strSymbol = "EUR/USD"; input int ext_iPeriod = 60; input bool ext_bTrain = true; // if testing, set false to it double macdArr[ARR_NUM * INPUT_NUM]; double oArr[ARR_NUM]; int cursor = 0; datetime currTime = 0; int OnInit (void) { PreventCleanUp(); for (int i = 0; i < ARR_NUM * INPUT_NUM; i++) { macdArr[i] = 0; } for (int i = 0; i < ARR_NUM; i++) { oArr[i] = 0; } return 0; } void OnTick(void) { if (cursor >= ARR_NUM) return; if (currTime == iTime(ext_strSymbol, ext_iPeriod, 0)) return; currTime = iTime(ext_strSymbol, ext_iPeriod, 0); double arr[INPUT_NUM]; double highest = -DBL_MAX; double lowest = DBL_MAX; for (int i = 1; i <= INPUT_NUM; i++) { arr[i - 1] = iMACD(ext_strSymbol, ext_iPeriod, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, i); if (arr[i - 1] > highest) { highest = arr[i - 1]; } if (arr[i - 1] < lowest) { lowest = arr[i - 1]; } } double height = highest - lowest; if (height <= 0) return; for (int i = 0; i < INPUT_NUM; i++) { macdArr[cursor * INPUT_NUM + i] = (arr[i] - lowest) / height; } oArr[cursor] = iOpen(ext_strSymbol, ext_iPeriod, 0); cursor++; } void OnDeinit (const int) { double trainingSetI[(cursor - 1) * INPUT_NUM]; double trainingSetO[(cursor - 1) * 2]; if (ext_bTrain) { if (BuildCNN(NN_NAME, INPUT_NUM, HIDDEN_NUM)) { for (int i = 0; i < cursor - 1; i++) { for (int j = 0; j < INPUT_NUM; j++) { trainingSetI[i * INPUT_NUM + j] = macdArr[i * INPUT_NUM + j]; } if (oArr[i] <= oArr[i + 1]) { trainingSetO[i * 2] = 1.0; trainingSetO[i * 2 + 1] = 0.0; } else { trainingSetO[i * 2] = 0.0; trainingSetO[i * 2 + 1] = 1.0; } } Print("Please be patient with the training progress."); if (TrainCNN(NN_NAME, trainingSetI, trainingSetO, cursor - 1, INPUT_NUM, ITERATIONS, BATCH_SIZE, false)) { SaveCNN(NN_NAME); } else { return; } } else { return; } } else { if (!LoadCNN(NN_NAME)) { return; } } int longWinCnt = 0; int shortWinCnt = 0; int longCnt = 0; int shortCnt = 0; for (int i = 0; i < cursor - 1; i++) { double input[INPUT_NUM]; double output = trainingSetO[i * 2]; for (int j = 0; j < INPUT_NUM; j++) { input[j] = trainingSetI[i * INPUT_NUM + j]; } double result = RunCNN(NN_NAME, input, INPUT_NUM); bool resWin = ((result >= 0.5 ? 1.0 : 0.0) == output ? true : false); if (resWin) { if (output == 1.0) { longCnt++; longWinCnt++; } else { shortCnt++; shortWinCnt++; } } else { if (output == 1.0) { longCnt++; } else { shortCnt++; } } } int lsCount = longCnt + shortCnt; Print("Long: ", longCnt, ", ", (longWinCnt * 1.0 / lsCount)); Print("Short: ", shortCnt, ", ", (shortWinCnt * 1.0 / lsCount)); } ================================================ FILE: EA/Plugin-for-MQL/testverisig.cpp ================================================ // This example is for the developers who want to sell EAs via Fintechee.io website. // If you use EA for yourself or you don't care copyright infringement, then you don't need to add the codes below to your source files. input string FINTECHEE_DATA = ""; // Keep this variable empty and DO NOT change the name of this variable. input string FINTECHEE_SIGNATURE = ""; // Keep this variable empty and DO NOT change the name of this variable. input string FINTECHEE_PUBLIC_KEY = ""; // Keep this variable empty and DO NOT change the name of this variable. // string APPLICATION_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwGzur7MO/CJPHvr2+r3lwxmjAL2d6nH2iyTwhL/CJZ8OGKm/+aikyluxoxF9Nq9aVLhCW5D1q9vAJCVYke7aquA/uuRE7a7frcWnKYOKNS2Pwvx88bJJBpfXfVh2K46i/2EfqdsghR+B1kSojS4lZggDB70uwIpeT2Q32X/5jEHl3p/9ZpFUwhStE2VMaEx/YOcdhAuS5BomDCe9g4KSI7faH3R0mA4dF1Tru6sAQarkAybI0RNlV52CpWfP2MfpeXm/P6WSXolM++DqFw8OsdrdqfyKM31zKyDOxzNib/DZbk72q6hzRtzGB4y3dTiyOVh3iP7nGOC/R0qPZCjRNQIDAQAB-----END PUBLIC KEY-----"; string APPLICATION_PUBLIC_KEY = ""; // Replace this string with your public key. The public key above is an example. DO NOT change the name of this variable. You can get your public key on Fintechee.io's inventory page. Please choose "Seller" to create an inventory item first, then a key pair will be generated. bool bVerified = false; // This global variable is used to check whether your license is available. You can set an assert condition such as "if(!bVerified) return;" anywhere that you want to block abuse. int OnInit (void) { // Please code the lines below anywhere that you want to verify the license. But note that calling VeriSig takes time, so we recommend you set an interval to check the license in the OnTick function or call VeriSig in OnInit. if (VeriSig(FINTECHEE_DATA, FINTECHEE_SIGNATURE, FINTECHEE_PUBLIC_KEY, APPLICATION_PUBLIC_KEY)) { bVerified = true; Print("Verification is done!"); } return 0; } void OnTick(void) { if (!bVerified) return; } ================================================ FILE: EA/Plugin-for-MQL/usage.txt ================================================ Our platform is compatible with any programming language based on WEB-Assembly. MQL, C++, and Python based programs can be used on our platform. This plugin allows MQL and C++ based programs to be imported into our system and run directly in the browser. Visit our website, https://fintechee.io, to explore our EA marketplace, which is supported by multiple vendors. If you have an EA that is based on MQL or C++, you can utilize our compiler, https://github.com/fintechees/Expert-Advisor-Cpp-Compiler, to compile and sell it on our marketplace. Your algo trading strategies can be experienced by clients who can utilize this plugin to import it into our WEB-trader. ================================================ FILE: EA/Plugin-for-Oanda/plugin_for_oanda.js ================================================ registerEA( "plugin_for_oanda", "An EA to integrate with Oanda(v1.0)", [], function (context) { // Init() // Disclaimer: we are not affiliated with Oanda. if (typeof window.pluginForOanda == "undefined") { window.pluginForOanda = { oandaDemo: true, oandaAccountId: "", oandaTradeKey: "", wrapperLibUrl: "https://www.fintechee.com/js/oanda/oanda_wrapper.js", interval: 120000, latestHBTime: 0, bLibLoaded: false, bMonitoring: false, currenciesList: [], openPositions: [], clearTable: function () { var posTable = null if ($.fn.dataTable.isDataTable("#oanda_pos_list")) { posTable = $("#oanda_pos_list").DataTable(); posTable.clear().draw(); posTable.destroy(); $("#oanda_pos_list").empty(); } $("#oanda_pos_list").DataTable({ data: [], columns: [ {title: "Instrument"}, {title: "Units"}, {title: "Type"} ], ordering: false, searching: false, bPaginate: false, bLengthChange: false, bFilter: false, bInfo: false, scrollY: '50vh', scrollCollapse: true, paging: false, columnDefs: [ {width: "40%", targets: 0, className: "dt-body-left"}, {width: "30%", targets: 1, className: "dt-body-left"}, {width: "30%", targets: 2, className: "dt-body-left"}, {targets: [0, 1, 2], className: "dt-head-left"} ] }) }, updatePositions: function (trade) { var rowId = -1 var instrument = trade.instrument.replace("_", "/") var currentUnits = parseFloat(trade.currentUnits) var units = 0 for (var i in this.openPositions) { var openPos = this.openPositions[i] if (openPos[0] == instrument) { rowId = parseInt(i) if (openPos[2] == "Long") { units = openPos[1] } else { units = -openPos[1] } units += currentUnits break } } if (rowId != -1) { if (units == 0) { this.openPositions.splice(rowId, 1) this.removePosFromTable(rowId) } else { if (units > 0) { this.openPositions[rowId][2] = "Long" this.openPositions[rowId][1] = units this.updatePosOnTable(rowId, "Long", units) } else { this.openPositions[rowId][2] = "Short" this.openPositions[rowId][1] = -units this.updatePosOnTable(rowId, "Short", -units) } } } else { var pos = [ trade.instrument.replace("_", "/"), Math.abs(currentUnits), currentUnits > 0 ? "Long" : "Short" ] this.openPositions.push(pos) this.addPosToTable(pos) } }, addPosToTable: function (pos) { $("#oanda_pos_list").DataTable().row.add(pos).draw(false) }, updatePosOnTable: function (rowId, orderType, units) { $("#oanda_pos_list").dataTable().fnUpdate(units, rowId, 1, false, false) $("#oanda_pos_list").dataTable().fnUpdate(orderType, rowId, 2, false, false) }, removePosFromTable: function (rowId) { $("#oanda_pos_list").dataTable().postable.fnDeleteRow(rowId) }, loadTrades: function () { var that = this if (typeof window.oandaOrderAPI != "undefined") { window.oandaOrderAPI.trades.listOpen(this.oandaAccountId) .then(function (res) { that.clearTable() for (var i in res.trades) { that.updatePositions(res.trades[i]) } }) .catch(function () {}) } }, sendOrder: function (symbolName, orderType, volume) { if (typeof window.oandaOrderAPI != "undefined") { window.oandaOrderAPI.orders.openOrder(this.oandaAccountId, { units: (orderType == ORDER_TYPE.OP_BUY ? (volume * 100000 + "") : (-volume * 100000 + "")), instrument: symbolName.replace("/", "_"), timeInForce: "FOK", type: "MARKET", positionFill: "DEFAULT" }) } }, loadLib: 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.wrapperLibUrl) { this.bLibLoaded = true break } } var that = this if (!this.bLibLoaded) { var script = document.createElement("script") script.id = "oanda_wrapper_lib" document.body.appendChild(script) script.onload = function () { that.bLibLoaded = true popupMessage("The wrapper lib for Oanda has been loaded successfully!") } script.onerror = function () { that.bLibLoaded = false popupErrorMessage("Failed to load the wrapper lib for Oanda.") } script.async = true script.src = this.wrapperLibUrl } }, monitorConnection: function () { if (this.latestHBTime != 0 && new Date().getTime() - this.latestHBTime >= this.interval) { this.bMonitoring = false this.reconnect() } var that = this setTimeout(function () {that.monitorConnection()}, this.interval) }, dataSubscribers: [], orderSubscribers: [], subscribeToDataChannel: function (subscriberName, subscriberCallback) { this.dataSubscribers[subscriberName] = subscriberCallback }, subscribeToOrderChannel: function (subscriberName, subscriberCallback) { this.orderSubscribers[subscriberName] = subscriberCallback }, unsubscribeFromDataChannel: function (subscriberName) { delete this.dataSubscribers[subscriberName] }, unsubscribeFromOrderChannel: function (subscriberName) { delete this.orderSubscribers[subscriberName] }, oandaDataCallback: function (res) { if (!this.bMonitoring) { popupMessage("Oanda has been connected successfully!") this.monitorConnection() this.bMonitoring = true } for (var i in this.dataSubscribers) { this.dataSubscribers[i](res) } }, oandaOrderCallback: function (res) { if (typeof res.type != "undefined") { if (res.type == "ORDER_FILL") { res.currentUnits = res.units this.updatePositions(res) } else if (res.type == "HEARTBEAT") { this.latestHBTime = new Date().getTime() } } for (var i in this.orderSubscribers) { this.orderSubscribers[i](res) } }, reconnect: function () { var that = this if (typeof window.oandaDataAPI != "undefined") { var symbolsList = [] for (var i in this.currenciesList) { symbolsList.push(this.currenciesList[i].symbolName) } window.oandaDataAPI.addToken(this.oandaDemo, this.oandaAccountId, this.oandaTradeKey) window.oandaDataAPI.pricing.stream(this.oandaAccountId, {instruments: symbolsList.join(","), snapshot: false}, function (res) { that.oandaDataCallback(res) }) } if (typeof window.oandaOrderAPI != "undefined") { window.oandaOrderAPI.addToken(this.oandaDemo, this.oandaAccountId, this.oandaTradeKey) window.oandaOrderAPI.transactions.stream(this.oandaAccountId, function (res) { that.oandaOrderCallback(res) }) } }, charts: [], chartChangeCallback: function (ctx) { // This callback function will be called once the chart switches from the normal mode to the takeover mode or the symbol of the chart under the takeover mode changes. var symbolName = getExtraSymbolName(ctx) if (typeof this.currenciesList[symbolName] != "undefined") { var chartId = getChartHandleByContext(ctx) setTakeoverMode(chartId) var timeFrame = getTimeFrame(ctx) if (typeof this.charts[chartId + ""] == "undefined") { this.charts[chartId + ""] = { chartId: chartId, symbolName: null, timeFrame: null } } var chart = this.charts[chartId + ""] chart.symbolName = this.currenciesList[symbolName].symbolName chart.timeFrame = timeFrame var that = this window.oandaDataAPI.instruments.candles(this.oandaAccountId, chart.symbolName, { granularity: timeFrame.toUpperCase() }) .then(function (res) { var data = [] if (Array.isArray(res.candles)) { for (var i in res.candles) { var ohlc = res.candles[i].mid data.push({ time: Math.floor(new Date(res.candles[i].time).getTime() / 1000), volume: res.candles[i].volume, open: parseFloat(ohlc.o), high: parseFloat(ohlc.h), low: parseFloat(ohlc.l), close: parseFloat(ohlc.c) }) } takeoverLoad(chartId, data) } }) } else { var chartId = getChartHandleByContext(ctx) unsetTakeoverMode(chartId) takeoverLoad(chartId, []) delete this.charts[chartId + ""] } }, chartRemoveCallback: function (ctx) { // This callback function will be called once the chart switches from the takeover mode to the normal mode or the chart is removed. var chartId = getChartHandleByContext(ctx) unsetTakeoverMode(chartId) takeoverLoad(chartId, []) delete this.charts[chartId + ""] }, quotes: [], onTick: function (res) { if (typeof res.instrument != "undefined") { var ask = null var bid = null var price = null if (Array.isArray(res.asks)) { ask = parseFloat(res.asks[0].price) price = ask } if (Array.isArray(res.bids)) { bid = parseFloat(res.bids[0].price) price = bid } if (ask == null) { ask = price } if (bid == null) { bid = price } if (ask == null || bid == null) { return } for (var i in this.charts) { var chart = this.charts[i] if (chart.symbolName == res.instrument) { var tick = { time: Math.floor(new Date().getTime() / 1000), volume: 0, price: Math.round((bid + ask) / 2 * 100000) / 100000 } if (chart.timeFrame == "M1") { takeoverUpdate(chart.chartId, 60, tick) } else if (chart.timeFrame == "M5") { takeoverUpdate(chart.chartId, 300, tick) } else if (chart.timeFrame == "M15") { takeoverUpdate(chart.chartId, 900, tick) } else if (chart.timeFrame == "M30") { takeoverUpdate(chart.chartId, 1800, tick) } else if (chart.timeFrame == "H1") { takeoverUpdate(chart.chartId, 3600, tick) } else if (chart.timeFrame == "H4") { takeoverUpdate(chart.chartId, 14400, tick) } else if (chart.timeFrame == "D") { takeoverUpdate(chart.chartId, 86400, tick) } else { takeoverUpdate(chart.chartId, 86400, tick) } } } this.quotes[res.instrument.replace("_", "/")] = { ask: ask, bid: bid } } }, initDashboard: function () { if (typeof $("#oanda_dashboard").html() == "undefined") { var panel = '' $("#reserved_zone").append(panel) $("#dropdownOandaDemo").dropdown() var that = this $("#connect_to_oanda").on("click", function () { that.oandaDemo = $("#oandaDemo").val() == "" || $("#oandaDemo").val() == "true" that.oandaAccountId = $("#oandaAccountId").val().trim() that.oandaTradeKey = $("#oandaTradeKey").val().trim() if (that.oandaAccountId != "" && that.oandaTradeKey != "" && that.bLibLoaded) { that.reconnect() that.subscribeToDataChannel("oanda_data", function (res) { that.onTick(res) }) that.loadTrades() } }) $("#close_oanda_dashboard").on("click", function () { $("#oanda_dashboard").modal("hide") }) var currenciesList = [{ symbolName: "AUD_CAD", displayName: "AUD/CAD (Oanda)" }, { symbolName: "AUD_CHF", displayName: "AUD/CHF (Oanda)" }, { symbolName: "AUD_JPY", displayName: "AUD/JPY (Oanda)" }, { symbolName: "AUD_USD", displayName: "AUD/USD (Oanda)" }, { symbolName: "EUR_GBP", displayName: "EUR/GBP (Oanda)" }, { symbolName: "EUR_JPY", displayName: "EUR/JPY (Oanda)" }, { symbolName: "EUR_USD", displayName: "EUR/USD (Oanda)" }, { symbolName: "GBP_AUD", displayName: "GBP/AUD (Oanda)" }, { symbolName: "GBP_CHF", displayName: "GBP/CHF (Oanda)" }, { symbolName: "GBP_JPY", displayName: "GBP/JPY (Oanda)" }, { symbolName: "GBP_USD", displayName: "GBP/USD (Oanda)" }, { symbolName: "USD_CAD", displayName: "USD/CAD (Oanda)" }, { symbolName: "USD_CHF", displayName: "USD/CHF (Oanda)" }, { symbolName: "USD_JPY", displayName: "USD/JPY (Oanda)" }] for (var i in currenciesList) { this.currenciesList[currenciesList[i].displayName] = currenciesList[i] this.quotes[currenciesList[i].symbolName.replace("_", "/")] = null } var chartIds = getLayout(1).concat(getLayout(2)).concat(getLayout(3)).concat(getLayout(4)) for (var i in chartIds) { if (typeof this.charts[chartIds[i] + ""] == "undefined") { this.charts[chartIds[i] + ""] = { chartId: chartIds[i], symbolName: null, timeFrame: null } createTakeover(chartIds[i], function (ctx) { that.chartChangeCallback(ctx) }, function (ctx) { that.chartRemoveCallback(ctx) } ) } } addExtraSymbols(this.currenciesList) } $("#oanda_dashboard").modal({autofocus:false}).modal("show") this.clearTable() for (var i in this.openPositions) { this.addPosToTable(this.openPositions[i]) } } } } window.pluginForOanda.initDashboard() window.pluginForOanda.loadLib() }, function (context) { // Deinit() if (!window.pluginForOanda.bLibLoaded) { var script = document.getElementById("oanda_wrapper_lib") script.remove() } }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-Oanda/usage.txt ================================================ Oanda is a well-known broker that offers API trading. As a result, we have created a plugin that establishes both a data channel for retrieving real-time quotes from Oanda and a trade channel for sending orders via Oanda’s REST API. Due to the substantial variance in prices between FIX API, which is utilized by institutions, and retail brokers, there can be arbitrage opportunities. However, arbitrage trading is not easy and requires considerable expenditures to develop appropriate tools. This plugin now allows traders to track market movements between two data sources and trade for arbitrage on their local machines without additional expenses. ================================================ FILE: EA/Plugin-for-SNS/plugin_for_sns.js ================================================ registerEA( "plugin_for_sns", "An EA to integrate with Fintechee SNS(v1.0)", [], function (context) { // Init() if (typeof window.pluginForSns == "undefined") { window.pluginForSns = { data: [], defaultTopic: "FintecheeEcoCal", topics: [], createTopic: function (topic, publishToken) { $.ajax({ type: "POST", url: "https://ciq1ir66d3.execute-api.eu-central-1.amazonaws.com/v1/register", contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ topic: topic, publishToken: publishToken }), success: function (data) { if (typeof data.res == "string") { $("#publishToken").val(data.res) } }, error: function (request, status, error) { popupErrorMessage(request.responseText) } }) }, postToTopic: function (topic, publishToken, content) { this.websocket.send(JSON.stringify({ action: "post", topic: topic, publishToken: publishToken, content: content })) }, subscribeToTopic: function (topic) { this.websocket.send(JSON.stringify({ action: "subscribe", topic: topic })) this.topics[topic] = true if (typeof this.data[topic] == "undefined") { this.data[topic] = [] } }, subscribers: [], subscribe: function (name, callback, ctx) { if (typeof name == "string" && typeof callback == "function" && typeof ctx == "object") { this.subscribers[name] = { callback: callback, context: ctx } } }, unsubscribe: function (name) { if (typeof name == "string") { delete this.subscribers[name] } }, updateData: function (data) { if (data.bFull) { this.data[data.topic] = data.data } else { if (data.topic == this.defaultTopic) { var oldData = this.data[data.topic] for (var i in data.data) { var iFound = -1 var updItem = data.data[i] for (var j in oldData) { var oldItem = oldData[j] if (updItem.data == oldItem.data) { iFound = parseInt(j) break } } if (iFound != -1) { this.data[data.topic][iFound] = data.data[i] } else { this.data[data.topic].push(data.data[i]) } } } else { for (var i in data.data) { this.data[data.topic].push(data.data[i]) } } } for (var i in this.subscribers) { this.subscribers[i].callback(this.subscribers[i].context) } }, bConnected: false, websocket: null, reconnect: function () { var socket = new WebSocket("wss://5k4mgf59ce.execute-api.eu-central-1.amazonaws.com/production") var that = this socket.onopen = function (e) { that.bConnected = true console.log("[open] Connection established") console.log("Sending to server") var subscriptionCnt = 0 for (var i in that.topics) { if (that.topics[i] && that.bConnected) { that.subscribeToTopic(i) subscriptionCnt++ } } if (subscriptionCnt == 0) { that.subscribeToTopic(that.defaultTopic) } } socket.onmessage = function (event) { console.log('[message] Data received from server') try { that.updateData(JSON.parse(event.data)) } catch (e) {} } socket.onclose = function (event) { that.bConnected = false if (event.wasClean) { console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`) } else { console.log('[close] Connection down') setTimeout(function () { that.reconnect() }, 1000) } } socket.onerror = function (error) { console.log(`[error] ${error}`) } this.websocket = socket }, initDashboard: function () { if (typeof $("#sns_dashboard").html() == "undefined") { var panel = '' $("#reserved_zone").append(panel) var that = this $("#btnCreateTopic").on("click", function () { var topic = $("#topicName").val().trim() var publishToken = $("#publishToken").val().trim() if (topic != "") { that.createTopic(topic, publishToken) } }) $("#btnPostToTopic").on("click", function () { var topic = $("#topicName").val().trim() var publishToken = $("#publishToken").val().trim() var content = $("#topicContent").val().trim() if (topic != "" && publishToken != "" && content != "" && that.bConnected) { that.postToTopic(topic, publishToken, content) } }) $("#btnSubscribeToTopic").on("click", function () { var topic = $("#topicToSubscribeTo").val().trim() if (topic != "" && that.bConnected) { that.subscribeToTopic(topic) } }) $("#btnCloseSnsDashboard").on("click", function () { $("#sns_dashboard").modal("hide") }) $("#tokenToggle").on("click", function() { var tokenInput = $("#publishToken") var icon = $(this) if (tokenInput.attr("type") == "password") { tokenInput.attr("type", "text") } else { tokenInput.attr("type", "password") } }) } $("#sns_dashboard").modal({autofocus:false}).modal("show") this.reconnect() } } } window.pluginForSns.initDashboard() if (typeof window.fintecheeBarrage != "undefined") { for (var i in window.fintecheeBarrage.context) { window.pluginForSns.subscribe("barrage-" + i, window.fintecheeBarrage.callback, window.fintecheeBarrage.context[i]) } } }, function (context) { // Deinit() }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-SNS/usage.txt ================================================ This plugin is deprecated. We have a new plugin named "Plugin for SNS with OpenAI" instead. 1, Launch an EA (Expert Advisor) named "plugin_for_sns". 2, If you are a publisher, input the topic name and click the "Create" button. The backend system will create a topic for you (if the topic already exists, the creation will fail) and generate a publish token. You can then begin posting your content. 3, If you are a subscriber, input the topic you wish to subscribe to. Afterward, please add an indicator called "barrage" to the chart. Whenever the publisher posts content, you will see a triangle on the chart. Hover your mouse over the triangle to view the content from the publisher in your social network. ================================================ FILE: EA/Plugin-for-SNS-with-OpenAI/plugin_for_sns_with_openai.js ================================================ registerEA( "plugin_for_sns_with_openai", "An EA to integrate with SNS and OpenAI(v1.0)", [], function (context) { // Init() if (typeof window.pluginForSns == "undefined") { window.pluginForSns = { data: [], defaultTopic: "FintecheeEcoCal", topics: [], createTopic: function (topic, publishToken) { $.ajax({ type: "POST", url: "https://ciq1ir66d3.execute-api.eu-central-1.amazonaws.com/v1/register", contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ topic: topic, publishToken: publishToken }), success: function (data) { if (typeof data.res == "string") { $("#publishToken").val(data.res) } }, error: function (request, status, error) { popupErrorMessage(request.responseText) } }) }, postToTopic: function (topic, publishToken, content) { this.websocket.send(JSON.stringify({ action: "post", topic: topic, publishToken: publishToken, content: content })) }, chatWithOpenAI: function (topic, publishToken, content) { this.websocket.send(JSON.stringify({ action: "openai", topic: topic, publishToken: publishToken, content: content })) }, subscribeToTopic: function (topic) { this.websocket.send(JSON.stringify({ action: "subscribe", topic: topic })) this.topics[topic] = true if (typeof this.data[topic] == "undefined") { this.data[topic] = [] } }, subscribers: [], subscribe: function (name, callback, ctx) { if (typeof name == "string" && typeof callback == "function" && typeof ctx == "object") { this.subscribers[name] = { callback: callback, context: ctx } } }, unsubscribe: function (name) { if (typeof name == "string") { delete this.subscribers[name] } }, updateData: function (data) { if (data.bFull) { this.data[data.topic] = data.data } else { if (data.topic == this.defaultTopic) { var oldData = this.data[data.topic] for (var i in data.data) { var iFound = -1 var updItem = data.data[i] for (var j in oldData) { var oldItem = oldData[j] if (updItem.data == oldItem.data) { iFound = parseInt(j) break } } if (iFound != -1) { this.data[data.topic][iFound] = data.data[i] } else { this.data[data.topic].push(data.data[i]) } } } else { for (var i in data.data) { this.data[data.topic].push(data.data[i]) } } } for (var i in this.subscribers) { this.subscribers[i].callback(this.subscribers[i].context) } }, respond: function (data) { if (data.bError) { $("#openAIResponse").val(data.errMsg) } else { if (data.type == "OpenAI") { var response = JSON.parse(data.data) $("#openAIResponse").val(response.choices[0].message.content) } else if (data.type == "PostToSns") { $("#openAIResponse").val(data.data[0].name) } } }, bConnected: false, websocket: null, reconnect: function () { var socket = new WebSocket("wss://5k4mgf59ce.execute-api.eu-central-1.amazonaws.com/production") var that = this socket.onopen = function (e) { that.bConnected = true console.log("[open] Connection established") console.log("Sending to server") var subscriptionCnt = 0 for (var i in that.topics) { if (that.topics[i] && that.bConnected) { that.subscribeToTopic(i) subscriptionCnt++ } } if (subscriptionCnt == 0) { that.subscribeToTopic(that.defaultTopic) } } socket.onmessage = function (event) { console.log('[message] Data received from server') try { var data = JSON.parse(event.data) if (data.bResponse) { that.respond(data) } else { that.updateData(data) } } catch (e) {} } socket.onclose = function (event) { that.bConnected = false if (event.wasClean) { console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`) } else { console.log('[close] Connection down') setTimeout(function () { that.reconnect() }, 1000) } } socket.onerror = function (error) { console.log(`[error] ${error}`) } this.websocket = socket }, initDashboard: function () { if (typeof $("#sns_dashboard").html() == "undefined") { var panel = '' $("#reserved_zone").append(panel) var that = this $("#btnCreateTopic").on("click", function () { var topic = $("#topicName").val().trim() var publishToken = $("#publishToken").val().trim() if (topic != "") { that.createTopic(topic, publishToken) } }) $("#btnPostToTopic").on("click", function () { var topic = $("#topicName").val().trim() var publishToken = $("#publishToken").val().trim() var content = $("#topicContent").val().trim() if (topic != "" && publishToken != "" && content != "" && that.bConnected) { that.postToTopic(topic, publishToken, content) } }) $("#btnChatWithOpenAI").on("click", function () { $("#btnChatWithOpenAI").prop("disabled", true) setTimeout(function () { $("#btnChatWithOpenAI").prop("disabled", false) }, 15000) var topic = $("#topicName").val().trim() var publishToken = $("#publishToken").val().trim() var content = $("#openAIContent").val().trim() if (topic != "" && publishToken != "" && content != "" && that.bConnected) { that.chatWithOpenAI(topic, publishToken, content) } }) $("#btnSubscribeToTopic").on("click", function () { var topic = $("#topicToSubscribeTo").val().trim() if (topic != "" && that.bConnected) { that.subscribeToTopic(topic) } }) $("#btnCloseSnsDashboard").on("click", function () { $("#sns_dashboard").modal("hide") }) $("#tokenToggle").on("click", function() { var tokenInput = $("#publishToken") var icon = $(this) if (tokenInput.attr("type") == "password") { tokenInput.attr("type", "text") } else { tokenInput.attr("type", "password") } }) } $("#sns_dashboard").modal({autofocus:false}).modal("show") this.reconnect() } } } window.pluginForSns.initDashboard() if (typeof window.fintecheeBarrage != "undefined") { for (var i in window.fintecheeBarrage.context) { window.pluginForSns.subscribe("barrage-" + i, window.fintecheeBarrage.callback, window.fintecheeBarrage.context[i]) } } }, function (context) { // Deinit() }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-SNS-with-OpenAI/usage.txt ================================================ 1, Launch an EA (Expert Advisor) named "plugin_for_sns_with_openai". 2, If you are a publisher, input the topic name and click the "Create" button. The backend system will create a topic for you (if the topic already exists, the creation will fail) and generate a publish token. You can then begin posting your content or chat with OpenAI. 3, If you are a subscriber, input the topic you wish to subscribe to. Afterward, please add an indicator called "barrage" to the chart. Whenever the publisher posts content, you will see a triangle on the chart. Hover your mouse over the triangle to view the content from the publisher in your social network. ================================================ FILE: EA/Plugin-for-Tensorflow/import_export_model.js ================================================ registerEA( "import_export_model", "An EA to import a model from files to localStorage or export a model from localStorage to files(v1.0)", [{ name: "tfModelName", value: "testcnn", required: true, type: "String", range: null, step: null }, { name: "import", value: true, // If true, then this EA imports the specific model from files to localStorage. If false, then this EA exports the specific model from localStorage to files. required: true, type: "Boolean", range: null, step: null }], function (context) { // Init() if (typeof window.tf == "undefined") { printErrorMessage("Please run the plugin to load Tensorflow first.") return } var tfModelName = getEAParameter(context, "tfModelName") var bImport = getEAParameter(context, "import") context.cnn = { initDashboard: function () { if (typeof $("#import_cnn_model").html() == "undefined") { var panel = '' $("#reserved_zone").append(panel) var that = this $("#btnImportModel").on("click", function () { context.cnn.importModel() }) } $("#import_cnn_model").modal({autofocus:false}).modal("show") }, importModel: function () { var jsonFile = document.getElementById("jsonFile") var weightsFile = document.getElementById("weightsFile") if (jsonFile.files.length == 0 || weightsFile.files[0] == 0) { setTimeout(function () { context.cnn.importModel() }, 1000) } else { $("#import_cnn_model").modal("hide") window.loadCnn(tfModelName, true, jsonFile.files[0], weightsFile.files[0]) .then(function (tfModel) { window.saveCnn(tfModel, tfModelName, false) popupMessage("Successfully imported the CNN model.") }) .catch(function (e) { popupErrorMessage("Failed to import the CNN model.") }) } } } if (bImport) { context.cnn.initDashboard() } else { window.loadCnn(tfModelName) .then(function (tfModel) { window.saveCnn(tfModel, tfModelName, true) popupMessage("Successfully exported the CNN model.") }) .catch(function (e) { popupErrorMessage("Failed to load the CNN model.") }) } }, function (context) { // Deinit() }, function (context) { // OnTick() }, function (context) { // OnTransaction() } ) ================================================ FILE: EA/Plugin-for-Tensorflow/plugin_to_load_tensorflow.js ================================================ registerEA( "plugin_to_load_tensorflow", "A plugin to load Tensorflow(v1.13)", [{ // parameters name: "tfjs", value: "https://www.fintechee.com/js/tf/tf.min.js", required: false, type: PARAMETER_TYPE.STRING, range: null },{ name: "tfvisjs", value: "https://www.fintechee.com/js/tf/tfjs-vis.js", required: false, type: PARAMETER_TYPE.STRING, range: null }], function (context) { // Init() if (typeof tf == "undefined") { var tfjs = getEAParameter(context, "tfjs") var tfvisjs = getEAParameter(context, "tfvisjs") 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") == tfjs || tags[i].getAttribute("src") == tfvisjs)) { 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 () { // Deprecated. It will be retained for compatibility with existing source codes. window.buildCnn = function (featuresNum, kernelSize, filters, strides) { return new Promise(function (resolve, reject) { var tfModel = window.tf.sequential() tfModel.add(window.tf.layers.conv1d({ inputShape: [featuresNum, 1], kernelSize: kernelSize, filters: filters, strides: strides, use_bias: true, activation: "relu", kernelInitializer: "VarianceScaling" })) tfModel.add(window.tf.layers.flatten({ })) tfModel.add(window.tf.layers.dense({ units: 2, kernelInitializer: "VarianceScaling", activation: "softmax" })) return resolve(tfModel) }) } // substitution for buildCnn window.buildExtraCnn = function (featuresNum, kernelSize, filters, strides, units) { return new Promise(function (resolve, reject) { var tfModel = window.tf.sequential() tfModel.add(window.tf.layers.conv1d({ inputShape: [featuresNum, 1], kernelSize: kernelSize, filters: filters, strides: strides, use_bias: true, activation: "relu", kernelInitializer: "VarianceScaling" })) tfModel.add(window.tf.layers.flatten({ })) tfModel.add(window.tf.layers.dense({ units: units, kernelInitializer: "VarianceScaling", activation: "softmax" })) return resolve(tfModel) }) } window.trainCnn = function (tfModel, trainingSet, epochs, batchSize, bMonitor) { if (bMonitor) { printMessage("Summary: ") tfModel.summary() } return new Promise(function (resolve, reject) { try { tfModel.compile({ optimizer: window.tf.train.adam(), loss: "categoricalCrossentropy", metrics: ["accuracy"] }) if (bMonitor) { tfModel.fit(trainingSet.input, trainingSet.output, { batchSize: batchSize, epochs: epochs, shuffle: true, callbacks: tfvis.show.fitCallbacks({ name: "Model Training", tab: "Model", styles: { height: "500px" } }, ["loss", "val_loss", "acc", "val_acc"]) }).then(function (result) { if (typeof result.history.loss != "undefined") { printMessage("Loss after last Epoch (" + result.epoch.length + ") is: " + result.history.loss[result.epoch.length-1]) } resolve() }) $("#tfjs-visor-container").show() } else { tfModel.fit(trainingSet.input, trainingSet.output, { batchSize: batchSize, epochs: epochs, shuffle: true }).then(function (result) { if (typeof result.history.loss != "undefined") { printMessage("Loss after last Epoch (" + result.epoch.length + ") is: " + result.history.loss[result.epoch.length-1]) } resolve() }) } } catch (ex) { reject(ex) } }) } window.checkIfCnnExisted = function (tfModelName) { return new Promise(function (resolve, reject) { (async () => { try { var models = await tf.io.listModels() var key = `localstorage://${tfModelName}` if (models[key]) { resolve({res:true}) } else { resolve({res:false}) } } catch (e) { reject(e.message) } })() }) } window.saveCnn = function (tfModel, tfModelName, bNotLocal) { return new Promise(function (resolve, reject) { (async () => { try { if (typeof bNotLocal == "undefined" || (typeof bNotLocal == "boolean" && !bNotLocal)) { await tfModel.save("localstorage://" + tfModelName) } else { await tfModel.save("downloads://" + tfModelName) } resolve() } catch (e) { reject(e.message) } })() }) } window.loadCnn = function (tfModelName, bNotLocal, jsonFile, weightsFile) { return new Promise(function (resolve, reject) { (async () => { try { var tfModel = null if (typeof bNotLocal == "undefined" || (typeof bNotLocal == "boolean" && !bNotLocal)) { tfModel = await window.tf.loadLayersModel("localstorage://" + tfModelName) } else { tfModel = await window.tf.loadLayersModel(window.tf.io.browserFiles([jsonFile, weightsFile])) } resolve(tfModel) } catch (e) { reject(e.message) } })() }) } window.loadRemoteCnn = function (jsonUrl) { return new Promise(function (resolve, reject) { (async () => { try { var tfModel = await window.tf.loadLayersModel(jsonUrl) resolve(tfModel) } catch (e) { reject(e.message) } })() }) } // Deprecated. It will be retained for compatibility with existing source codes. window.runCnn = function (tfModel, input, inputNum) { return window.tf.tidy(function () { try { return tfModel.predict(window.tf.tensor3d(input, [1, inputNum, 1])).arraySync()[0][0] } catch (e) { return -1 } }) } // substitution for runCnn window.getArgMaxOfCnn = function (tfModel, input, inputNum) { return window.tf.tidy(function () { try { var arr = tfModel.predict(window.tf.tensor3d(input, [1, inputNum, 1])).arraySync()[0] return arr.indexOf(Math.max(...arr)) } catch (e) { return -1 } }) } window.removeCnn = function (tfModelName) { try { window.tf.io.removeModel("localstorage://" + tfModelName) } catch (e) { } }; (async function () { await window.tf.ready() if (window.tf.getBackend() == "webgl") { window.tf.tensor(0).dataSync() try { window.tf.env().registerFlag("WEBGL_DELETE_TEXTURE_THRESHOLD", () => 128 * 1024 * 1024, (val) => { }) } catch (e) { window.tf.env().set("WEBGL_DELETE_TEXTURE_THRESHOLD", 128 * 1024 * 1024) } } })() popupMessage("Tensorflow has been loaded successfully!") } script2.onerror = function () { popupErrorMessage("Failed to load Tensorflow! Please run this plugin again.") } script2.async = true script2.src = tfvisjs } script1.onerror = function () { popupErrorMessage("Failed to load Tensorflow! Please run this plugin again.") } script1.async = true script1.src = tfjs } }, function (context) { // Deinit() }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-Tensorflow/sample_running_cnn_model.js ================================================ registerEA( "sample_running_cnn_model", "An EA sample to run neuron model(v1.04)", [{ // parameters name: "version", value: 1, required: true, type: PARAMETER_TYPE.NUMBER, range: [0, 100] }, { name: "symbolName", value: "EUR/USD", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "timeFrame", value: "H1", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "inputNum", value: 10, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }, { name: "hiddenNum", value: 20, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }, { name: "predictNum", value: 10, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }, { name: "volume", value: 0.01, required: true, type: PARAMETER_TYPE.NUMBER, range: [0.01, 1] }], function (context) { // Init() if (typeof window.tf == "undefined") { printErrorMessage("Please run the plugin to load Tensorflow first.") return } var version = getEAParameter(context, "version") var symbolName = getEAParameter(context, "symbolName") var timeFrame = getEAParameter(context, "timeFrame") var inputNum = getEAParameter(context, "inputNum") var hiddenNum = getEAParameter(context, "hiddenNum") var predictNum = getEAParameter(context, "predictNum") context.runMyCnn = function (input) { if (typeof input == "undefined" || input.length == 0) return -1 var result = window.runCnn(this.tfModel, input, inputNum) printMessage(result) return result } var tfModelName = "Fintechee " + symbolName.replace("/", "") + "-" + timeFrame + "-" + inputNum + "-" + hiddenNum + "-" + predictNum + "-" + version context.tfModel = null window.loadCnn(tfModelName) .then(function (tfModel) { context.tfModel = tfModel }) .catch(function (e) { popupErrorMessage("Failed to load the CNN model.") }) var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame) context.indiHandleMacd = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, "macd", [{ name: "fastEMA", value: 12 },{ name: "slowEMA", value: 26 },{ name: "signalSMA", value: 9 }]) context.tradingManager = { posLong: [], posShort: [], getPosInfo: function (brokerNm, accId, symbolNm) { this.posLong = [] this.posShort = [] var cnt = getOpenTradesListLength(context) for (var i = cnt - 1; i >= 0; i--) { var openTrade = getOpenTrade(context, i) var symbol = getSymbolName(openTrade) if (symbol == symbolNm) { var orderType = getOrderType(openTrade) if (orderType == ORDER_TYPE.OP_BUY) { this.posLong.push(getTradeId(openTrade)) } else { this.posShort.push(getTradeId(openTrade)) } } } }, trade: function (brokerNm, accId, symbolNm, odrType, volume, orderNum) { if (orderNum < 0) return if (orderNum > 0) { var orderLots = volume * orderNum if (odrType == ORDER_TYPE.OP_BUY) { if (this.posLong.length > 0) { return false } sendOrder(brokerNm, accId, symbolNm, ORDER_TYPE.OP_BUY, 0, 0, Math.round(orderLots * 100) / 100, 0, 0, "", 0, 0) return true } else if (odrType == ORDER_TYPE.OP_SELL) { if (this.posShort.length > 0) { return false } sendOrder(brokerNm, accId, symbolNm, ORDER_TYPE.OP_SELL, 0, 0, Math.round(orderLots * 100) / 100, 0, 0, "", 0, 0) return true } } else { if (odrType == ORDER_TYPE.OP_BUY) { var bClosed = false for (var i in this.posLong) { closeTrade(brokerNm, accId, this.posLong[i], 0, 0) bClosed = true } } else if (odrType == ORDER_TYPE.OP_SELL) { var bClosed = false for (var i in this.posShort) { closeTrade(brokerNm, accId, this.posShort[i], 0, 0) bClosed = true } } if (bClosed) { return true } } return false } } context.signalManager = { inputNum: inputNum, checkCnnSignal: function (arrMain) { var arrLen = arrMain.length var input = [] var highVal = -Number.MAX_VALUE var lowVal = Number.MAX_VALUE for (var i = this.inputNum + 1; i >= 2; i--) { if (arrMain[arrLen - i] > highVal) { highVal = arrMain[arrLen - i] } if (arrMain[arrLen - i] < lowVal) { lowVal = arrMain[arrLen - i] } } var height = highVal - lowVal if (height <= 0) { return -1 } for (var i = this.inputNum + 1; i >= 2; i--) { input.push((arrMain[arrLen - i] - lowVal) / height) } var result = this.runMyCnn(input) return result == -1 ? -1 : (result >= 0.5 ? 1 : 0) }, upSl: 0, downSl: 0, predictNum: predictNum, checkCloseSignal: function (currIdx) { var signal = -1 if (this.upSl > 0) { if (currIdx - this.upSl > this.predictNum) { signal = 3 } } if (this.downSl > 0) { if (currIdx - this.downSl > this.predictNum) { signal = 2 } } return signal } } }, function (context) { // Deinit() }, function (context) { // OnTick() if (typeof window.tf == "undefined") { return } if (context.tfModel == null) return 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 = getEAParameter(context, "symbolName") var version = getEAParameter(context, "version") var inputNum = getEAParameter(context, "inputNum") var predictNum = getEAParameter(context, "predictNum") var arrClose = getData(context, context.chartHandle, DATA_NAME.CLOSE) var arrMain = getData(context, context.indiHandleMacd, "main") if (200 >= arrMain.length) throw new Error("No enough data.") var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) var symbolName = getEAParameter(context, "symbolName") var volume = getEAParameter(context, "volume") var signal = -1 var arrLen = arrClose.length var currTick = arrClose[arrLen - 1] context.tradingManager.getPosInfo(brokerName, accountId, symbolName) if (context.signalManager.upSl > 0 || context.signalManager.downSl > 0) { signal = context.signalManager.checkCloseSignal(arrLen - 1) } if (signal == -1) { signal = context.signalManager.checkCnnSignal(arrMain) } if (signal == 1) { if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, volume, 1)) { context.signalManager.upSl = arrLen - 1 } } else if (signal == 0) { if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, volume, 1)) { context.signalManager.downSl = arrLen - 1 } } else if (signal == 3) { if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, volume, 0)) { context.signalManager.upSl = 0 } } else if (signal == 2) { if (context.tradingManager.trade(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, volume, 0)) { context.signalManager.downSl = 0 } } } ) ================================================ FILE: EA/Plugin-for-Tensorflow/sample_training_cnn_model.js ================================================ registerEA( "sample_training_cnn_model", "An EA sample to train neuron model(v1.05)", [{ name: "version", value: 1, required: true, type: PARAMETER_TYPE.NUMBER, range: [0, 100], step: null }, { name: "symbolName", value: "EUR/USD", required: true, type: PARAMETER_TYPE.STRING, range: null, step: null }, { name: "timeFrame", value: "H1", required: true, type: PARAMETER_TYPE.STRING, range: null, step: null }, { name: "inputNum", value: 10, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100], step: null }, { name: "hiddenNum", value: 20, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100], step: null }, { name: "predictNum", value: 10, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100], step: null }, { name: "iterations", value: 10000, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 1000000], step: null }, { name: "batchSize", value: 512, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100000], step: null }, { name: "bContinue", value: false, required: true, type: PARAMETER_TYPE.BOOLEAN, range: null, step: null }, { name: "bTest", value: false, required: true, type: PARAMETER_TYPE.BOOLEAN, range: null, step: null }, { name: "bMem", value: false, required: true, type: PARAMETER_TYPE.BOOLEAN, range: null, step: null }, { name: "bMonitor", value: false, required: true, type: PARAMETER_TYPE.BOOLEAN, range: null, step: null }], function (context) { // Init() if (typeof window.tf == "undefined") { printErrorMessage("Please run the plugin to load Tensorflow first.") return } var version = getEAParameter(context, "version") var symbolName = getEAParameter(context, "symbolName") var timeFrame = getEAParameter(context, "timeFrame") var iterations = getEAParameter(context, "iterations") var inputNum = getEAParameter(context, "inputNum") var hiddenNum = getEAParameter(context, "hiddenNum") var predictNum = getEAParameter(context, "predictNum") var bContinue = getEAParameter(context, "bContinue") var bTest = getEAParameter(context, "bTest") var bMem = getEAParameter(context, "bMem") var bMonitor = getEAParameter(context, "bMonitor") var batchSize = getEAParameter(context, "batchSize") var tfModelName = "Fintechee " + symbolName.replace("/", "") + "-" + timeFrame + "-" + inputNum + "-" + hiddenNum + "-" + predictNum + "-" + version context.buildMyCnn = function () { window.buildCnn(inputNum, inputNum, hiddenNum, inputNum).then(function (tfModel) { context.tfModel = tfModel }) } context.runMyCnn = function (input) { return window.runCnn(this.tfModel, input, inputNum) } context.trainMyCnn = function () { printMessage("Start training!") window.trainCnn(this.tfModel, window.tensorSet, iterations, batchSize, bMonitor).then(function () { printMessage("Training is done!"); window.saveCnn(context.tfModel, tfModelName) var longCnt = 0 var shortCnt = 0 var longWinCnt = 0 var shortWinCnt = 0 var levelCnt = [] var levelWinCnt = [] var levelProfit = [] var levelLoss = [] var longProfit = 0 var shortProfit = 0 var longLoss = 0 var shortLoss = 0 for (var i = 0; i < window.tensorSet.lsCount; i++) { var input = [] for (var j = 0; j < inputNum; j++) { input.push(window.tensorSet.trainingSetI[i * inputNum + j]) } var output = window.tensorSet.trainingSetO[i * 2] var profit = window.tensorSet.trainingSetP[i] var result = context.runMyCnn(input) var resWin = (result == -1 ? false : ((result >= 0.5 ? 1 : 0) == output ? true : false)) var idx = Math.floor(Math.floor(result * 100) / Math.floor(100 / 10)) * Math.floor(100 / 10) if (typeof levelCnt[idx] == "undefined") { levelCnt[idx] = 0 levelWinCnt[idx] = 0 levelProfit[idx] = 0 levelLoss[idx] = 0 } levelCnt[idx]++ if (resWin) { if (output == 1) { longCnt++ longWinCnt++ longProfit += profit } else { shortCnt++ shortWinCnt++ shortProfit += profit } levelWinCnt[idx]++ levelProfit[idx] += profit } else { if (output == 1) { shortCnt++ shortLoss += profit } else { longCnt++ longLoss += profit } levelLoss[idx] += profit } } printMessage(tfModelName) printMessage("Long: " + longCnt + ", " + (longWinCnt / window.tensorSet.lsCount) + ", " + longProfit + ", " + longLoss + ", " + ((longProfit - longLoss) / longCnt)) printMessage("Short: " + shortCnt + ", " + (shortWinCnt / window.tensorSet.lsCount) + ", " + shortProfit + ", " + shortLoss + ", " + ((shortProfit - shortLoss) / shortCnt)) for (var i in levelCnt) { printMessage(i + ", " + levelCnt[i] + ", " + (levelWinCnt[i] / levelCnt[i]) + ", " + levelProfit[i] + ", " + levelLoss[i] + ", " + ((levelProfit[i] - levelLoss[i]) / levelCnt[i])) } $("#tfjs-visor-container").hide() }) } context.testMyCnn = function () { printMessage("Start testing!") var longCnt = 0 var shortCnt = 0 var longWinCnt = 0 var shortWinCnt = 0 var levelCnt = [] var levelWinCnt = [] var levelProfit = [] var levelLoss = [] var longProfit = 0 var shortProfit = 0 var longLoss = 0 var shortLoss = 0 for (var i = 0; i < window.tensorSet.testLsCount; i++) { var input = [] for (var j = 0; j < inputNum; j++) { input.push(window.tensorSet.testSetI[i * inputNum + j]) } var output = window.tensorSet.testSetO[i * 2] var profit = window.tensorSet.testSetP[i] var result = this.runMyCnn(input) var resWin = (result == -1 ? false : ((result >= 0.5 ? 1 : 0) == output ? true : false)) var idx = Math.floor(Math.floor(result * 100) / Math.floor(100 / 10)) * Math.floor(100 / 10) if (typeof levelCnt[idx] == "undefined") { levelCnt[idx] = 0 levelWinCnt[idx] = 0 levelProfit[idx] = 0 levelLoss[idx] = 0 } levelCnt[idx]++ if (resWin) { if (output == 1) { longCnt++ longWinCnt++ longProfit += profit } else { shortCnt++ shortWinCnt++ shortProfit += profit } levelWinCnt[idx]++ levelProfit[idx] += profit } else { if (output == 1) { shortCnt++ shortLoss += profit } else { longCnt++ longLoss += profit } levelLoss[idx] += profit } } printMessage(tfModelName) printMessage("Long: " + longCnt + ", " + (longWinCnt / window.tensorSet.testLsCount) + ", " + longProfit + ", " + longLoss + ", " + ((longProfit - longLoss) / longCnt)) printMessage("Short: " + shortCnt + ", " + (shortWinCnt / window.tensorSet.testLsCount) + ", " + shortProfit + ", " + shortLoss + ", " + ((shortProfit - shortLoss) / shortCnt)) for (var i in levelCnt) { printMessage(i + ", " + levelCnt[i] + ", " + (levelWinCnt[i] / levelCnt[i]) + ", " + levelProfit[i] + ", " + levelLoss[i] + ", " + ((levelProfit[i] - levelLoss[i]) / levelCnt[i])) } printMessage("Testing is done!") } if (bContinue) { window.loadCnn(tfModelName) .then(function (tfModel) { context.tfModel = tfModel if (typeof window.tensorSet != "undefined") { if (bMem) { if (bTest) { setTimeout(function () {context.testMyCnn()}, 5000) } else { setTimeout(function () {context.trainMyCnn()}, 5000) } } } }) .catch(function (e) { popupErrorMessage("Failed to load the CNN model.") }) } else { context.buildMyCnn() } var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, timeFrame) context.indiHandleMacd = getIndicatorHandle(context, brokerName, accountId, symbolName, timeFrame, "macd", [{ name: "fastEMA", value: 12 },{ name: "slowEMA", value: 26 },{ name: "signalSMA", value: 9 }]) }, function (context) { // Deinit() if (typeof window.tf == "undefined") { printErrorMessage("Please run the plugin to load Tensorflow first.") return } var bMem = getEAParameter(context, "bMem") if (bMem && typeof window.tensorSet != "undefined") { return } var version = getEAParameter(context, "version") var inputNum = getEAParameter(context, "inputNum") var predictNum = getEAParameter(context, "predictNum") var bTest = getEAParameter(context, "bTest") var arrOpen = getData(context, context.chartHandle, DATA_NAME.OPEN) var arrMain = getData(context, context.indiHandleMacd, "main") if (200 >= arrMain.length) throw new Error("No enough data.") var trainingSetI = [] var trainingSetO = [] var trainingSetP = [] var longCount = 0 var shortCount = 0 for (var i = 26 + inputNum; i < arrMain.length - predictNum - 1; i++) { var input = [] var highVal = -Number.MAX_VALUE var lowVal = Number.MAX_VALUE for (var j = inputNum - 1; j >= 0; j--) { if (arrMain[i - j] > highVal) { highVal = arrMain[i - j] } if (arrMain[i - j] < lowVal) { lowVal = arrMain[i - j] } } var height = highVal - lowVal if (height <= 0) { continue } for (var j = inputNum - 1; j >= 0; j--) { input.push((arrMain[i - j] - lowVal) / height) } for (var j = 0; j < input.length; j++) { trainingSetI.push(input[j]) } if (arrOpen[i + 1 + predictNum] - arrOpen[i + 1] >= 0) { trainingSetO.push(1) trainingSetO.push(0) longCount++ trainingSetP.push(arrOpen[i + 1 + predictNum] - arrOpen[i + 1]) } else { trainingSetO.push(0) trainingSetO.push(1) shortCount++ trainingSetP.push(arrOpen[i + 1] - arrOpen[i + 1 + predictNum]) } } var lsCount = longCount + shortCount if (!bTest) { var tensorSet = { lsCount: lsCount, trainingSetI: trainingSetI, trainingSetO: trainingSetO, trainingSetP: trainingSetP, input: window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1]), output: window.tf.tensor2d(trainingSetO, [lsCount, 2]), } if (typeof window.tensorSet == "undefined") { tensorSet.testLsCount = lsCount tensorSet.testSetI = trainingSetI tensorSet.testSetO = trainingSetO tensorSet.testSetP = trainingSetP tensorSet.testInput = window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1]) tensorSet.testOutput = window.tf.tensor2d(trainingSetO, [lsCount, 2]) } else { tensorSet.testLsCount = window.tensorSet.testLsCount tensorSet.testSetI = window.tensorSet.testSetI tensorSet.testSetO = window.tensorSet.testSetO tensorSet.testSetP = window.tensorSet.testSetP tensorSet.testInput = window.tensorSet.testInput tensorSet.testOutput = window.tensorSet.testOutput } window.tensorSet = tensorSet context.trainMyCnn() } else { var tensorSet = { testLsCount: lsCount, testSetI: trainingSetI, testSetO: trainingSetO, testSetP: trainingSetP, testInput: window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1]), testOutput: window.tf.tensor2d(trainingSetO, [lsCount, 2]) } if (typeof window.tensorSet == "undefined") { tensorSet.lsCount = lsCount tensorSet.trainingSetI = trainingSetI tensorSet.trainingSetO = trainingSetO tensorSet.trainingSetP = trainingSetP tensorSet.input = window.tf.tensor3d(trainingSetI, [lsCount, inputNum, 1]) tensorSet.output = window.tf.tensor2d(trainingSetO, [lsCount, 2]) } else { tensorSet.lsCount = window.tensorSet.lsCount tensorSet.trainingSetI = window.tensorSet.trainingSetI tensorSet.trainingSetO = window.tensorSet.trainingSetO tensorSet.trainingSetP = window.tensorSet.trainingSetP tensorSet.input = window.tensorSet.input tensorSet.output = window.tensorSet.output } window.tensorSet = tensorSet context.testMyCnn() } printMessage("Training Set or Testing Set: " + longCount + ", " + shortCount) }, function (context) { // OnTick() }, function (context) { // OnTransaction() } ) ================================================ FILE: EA/Plugin-for-Tensorflow/test_loading_tensorflow.js ================================================ registerEA( "test_loading_tensorflow", "A test EA to load Tensorflow2.0 (v1.0)", [{ // parameters name: "url", value: "https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js", required: true, type: PARAMETER_TYPE.STRING, range: null }], function (context) { // Init() if (typeof tf == "undefined") { var url = getEAParameter(context, "url") 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") == url) { tags[i].parentNode.removeChild(tags[i]) } } var script1 = document.createElement("script") document.body.appendChild(script1) script1.onload = function () { } script1.onerror = function () {} script1.async = true script1.src = url } }, function (context) { // Deinit() }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-Tensorflow/test_xor_powered_by_tensorflow.js ================================================ registerEA( "test_xor_powered_by_tensorflow", "A test EA to train XOR by using Tensorflow2.0 (v1.0)", [{ // parameters name: "tfjs", value: "https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js", required: true, type: PARAMETER_TYPE.STRING, range: null },{ name: "tfvisjs", value: "https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis", required: true, type: PARAMETER_TYPE.STRING, range: null },{ name: "epochs", value: 10000, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 1000000] }], function (context) { // Init() window.epochs = getEAParameter(context, "epochs") if (typeof tf == "undefined") { var tfjs = getEAParameter(context, "tfjs") var tfvisjs = getEAParameter(context, "tfvisjs") 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") == tfjs && tags[i].getAttribute("src") == tfvisjs) { 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 () { window.buildCnn = function () { return new Promise(function (resolve, reject) { const model = tf.sequential() model.add(tf.layers.inputLayer({ inputShape: [2, 1, 1], })) model.add(tf.layers.conv2d({ inputShape: [2, 1, 1], kernelSize: 1, filters: 2, strides: 1, use_bias: true, activation: "relu", kernelInitializer: "VarianceScaling" })) model.add(tf.layers.maxPooling2d({ poolSize: [1, 1], strides: [1, 1] })) model.add(tf.layers.flatten({ })) model.add(tf.layers.dense({ units: 2, kernelInitializer: "VarianceScaling", activation: "softmax" })) return resolve(model) }) } window.trainCnn = function (model, trainingSet) { printMessage("Summary: ") model.summary() return new Promise(function (resolve, reject) { try { model.compile({ optimizer: tf.train.adam(), loss: "categoricalCrossentropy", metrics: ["accuracy"] }) model.fit(trainingSet.input, trainingSet.output, { epochs: window.epochs, shuffle: true, callbacks: tfvis.show.fitCallbacks({ name: "Model Training", tab: "Model", styles: { height: "500px" } }, ["loss", "val_loss", "acc", "val_acc"]) }).then(function (result) { printMessage("Loss after last Epoch (" + result.epoch.length + ") is: " + result.history.loss[result.epoch.length-1]) resolve(model) }) } catch (ex) { reject(ex) } }) } window.doCnn = function () { window.buildCnn().then(function (model) { var trainingSet = { input: tf.tensor4d([0, 0, 1, 1, 1, 0, 0, 1], [4, 2, 1, 1]), output: tf.tensor2d([0, 1, 0, 1, 1, 0, 1, 0], [4, 2]) } window.trainCnn(model, trainingSet).then(function (model) { printMessage(model.predict(trainingSet.input)) }) }) } window.doCnn() } script2.onerror = function () {} script2.async = true script2.src = tfvisjs } script1.onerror = function () {} script1.async = true script1.src = tfjs } else { window.doCnn() } }, function (context) { // Deinit() delete window.epochs }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-Tensorflow/usage.txt ================================================ This is the most interesting part that we would like to present to our users. Tensorflow is an AI framework that was utilized to construct the Go bot, AlphaGo. Typically, Market patterns identification is accomplished through neural networks. We can use this Tensorflow plugin to simulate this process, replicating the way our eyes detect market patterns. Just like the EAs that are included in NeuralNetwork folder, EAs that are based on this plugin must be separated into two parts. One piece for training the model, known as the convolutional neural network, and another is utilized to operate the model that has been trained by the previous element. ================================================ FILE: EA/Plugin-for-TradingView/plugin_for_tradingview.js ================================================ registerEA( "tradingview_widget", "A plugin to embed the widget of TradingView(v1.0)", [], function (context) { // Init() // Disclaimer: we are not affiliated with the widget providers or the API providers. if (getLayoutId() != 3) { changeLayout(3) } window.chartIds = getLayout(2) for (var i in window.chartIds) { moveLayout(window.chartIds[i], 1) } embedHtml('
', 2) var script = document.createElement("script") document.body.appendChild(script) script.onload = function () { new TradingView.widget( { "width": "100%", "height": "105%", "symbol": "NASDAQ:AAPL", "interval": "D", "timezone": "Etc/UTC", "theme": "light", "style": "1", "locale": "en", "toolbar_bg": "#f1f3f6", "enable_publishing": false, "allow_symbol_change": true, "container_id": "tradingview_8ac01" } ) } script.onerror = function () { alert("Failed to load required libs. Please re-run this EA again.") } script.async = true script.src = "https://s3.tradingview.com/tv.js" }, function (context) { // Deinit() embedHtml("", 2) for (var i in window.chartIds) { moveLayout(window.chartIds[i], 2) } }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-TrailingStop/plugin_for_trailingstop.js ================================================ registerEA( "plugin_for_trailingstop", "A plugin to manage trailing stop(v1.02)", [{ name: "symbolName", // this parameter to set the symbols that you want to have trailing stops applied value: "EUR/USD", // e.g. EUR/USD,GBP/USD required: true, type: "String", range: null, step: null }, { name: "trailingStop", value: 20, required: true, type: "Number", range: [1, 10000], step: null }], function (context) { // Init() context.openTrades = [] var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) var symbolNames = getEAParameter(context, "symbolName").split(",") for (var i in symbolNames) { var symbolName = symbolNames[i] getQuotes(context, brokerName, accountId, symbolName) } }, function (context) { // Deinit() }, function (context) { // OnTick() var trailingStop = getEAParameter(context, "trailingStop") var tick = getCurrentTick(context) var cnt = context.openTrades.length for (var i = cnt - 1; i >= 0; i--) { var openTrade = context.openTrades[i] if (openTrade.brokerName == tick.brokerName && openTrade.accountId == tick.accountId && openTrade.symbolName == tick.symbolName) { var toFixed = getSymbolInfo(openTrade.brokerName, openTrade.accountId, openTrade.symbolName).toFixed / 10 if (openTrade.orderType == "BUY") { if (tick.bid - Math.max(openTrade.stopLoss, openTrade.price) > trailingStop / toFixed) { openTrade.stopLoss = tick.bid - trailingStop / toFixed } else if (tick.bid <= openTrade.stopLoss) { closeTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0) context.openTrades.splice(i, 1) } } else { if (Math.min(openTrade.stopLoss, openTrade.price) - tick.ask > trailingStop / toFixed) { openTrade.stopLoss = tick.ask + trailingStop / toFixed } else if (tick.ask >= openTrade.stopLoss) { closeTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0) context.openTrades.splice(i, 1) } } } } }, function (context) { // OnTransaction() var trailingStop = getEAParameter(context, "trailingStop") var transType = getLatestTransType(context) if (transType == "Open Trade") { var trans = getLatestTrans(context) var transTradeId = getTradeId(trans) var transBrokerName = getBrokerName(trans) var transAccountId = getAccountId(trans) var transSymbolName = getSymbolName(trans) var transOrderType = getOrderType(trans).split(" ")[0] var transPrice = getOpenPrice(trans) var toFixed = getSymbolInfo(transBrokerName, transAccountId, transSymbolName).toFixed / 10 context.openTrades.push({ tradeId: transTradeId, brokerName: transBrokerName, accountId: transAccountId, symbolName: transSymbolName, orderType: transOrderType, price: transPrice, stopLoss: (transOrderType == "BUY" ? (transPrice - trailingStop / toFixed) : (transPrice + trailingStop / toFixed)) }) } }) ================================================ FILE: EA/Plugin-for-XCoinCH/market_maker_bot.js ================================================ registerEA( "market_maker_bot", "Automated market maker(v1.0)", [{ name: "basePlatform", value: "eth", required: true, type: "String", range: null, step: null }, { name: "baseCryptocurrency", value: "WEENUS", required: true, type: "String", range: null, step: null }, { name: "termPlatform", value: "eos", required: true, type: "String", range: null, step: null }, { name: "termCryptocurrency", value: "JUNGLE", required: true, type: "String", range: null, step: null }], // parameters function (context) { // Init() window.ethAccount = "YOUR ETHEREUM ADDRESS" window.ethPrivateKey = "YOUR ETHEREUM PRIVATE KEY" window.eosAccount = "YOUR EOSIO ACCOUNT" window.eosPrivateKey = "YOUR EOSIO PRIVATE KEY" window.mailAddr = "test@xcoinch.com" window.basePlatform = getEAParameter(context, "basePlatform").toLowerCase() window.baseCryptocurrency = getEAParameter(context, "baseCryptocurrency").toUpperCase() window.termPlatform = getEAParameter(context, "termPlatform").toLowerCase() window.termCryptocurrency = getEAParameter(context, "termCryptocurrency").toUpperCase() window.queue = [] window.tradeInterval = 300000 window.oneHour = 3600000 window.contactId = "0" window.dexConnected = false window.testNet = 1 window.serverUrl = "https://lmk2m8udud.execute-api.eu-central-1.amazonaws.com/v1" window.ethReceiptUrl = null var ethRpcUrl = "https://rinkeby.infura.io/v3/467e60929f46412f8ea456d04ab491da" var ethWeb3 = "https://www.fintechee.com/js/wallet/web3.min.js" var eosRpcUrl = "https://jungle3.cryptolions.io" var eosJsSig = "https://www.fintechee.com/js/wallet/eosjs-jssig.min.js" var eosRpc = "https://www.fintechee.com/js/wallet/eosjs-jsonrpc.min.js" var eosApi = "https://www.fintechee.com/js/wallet/eosjs-api.min.js" if (window.basePlatform != "eth" && window.basePlatform != "eos") { printErrorMessage("The base platforms is not correct.") return } if (window.termPlatform != "eth" && window.termPlatform != "eos") { printErrorMessage("The term platforms is not correct.") return } if (window.ethAccount == null || window.ethAccount == "" || window.eosAccount == null || window.eosAccount == "") { printErrorMessage("The account should not be empty.") return } if (window.ethPrivateKey == null || window.ethPrivateKey == "" || window.eosPrivateKey == null || window.eosPrivateKey == "") { printErrorMessage("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") == eosJsSig || tags[i].getAttribute("src") == eosRpc || tags[i].getAttribute("src") == eosApi || tags[i].getAttribute("src") == ethWeb3)) { tags[i].parentNode.removeChild(tags[i]) } } var script0 = document.createElement("script") document.body.appendChild(script0) script0.onload = function () { window.eth_api = new Web3(ethRpcUrl) window.dexEthLibsLoaded = true } script0.onerror = function () {} script0.async = true script0.src = ethWeb3 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 window.eos_rpc = new eosjs_jsonrpc.JsonRpc(eosRpcUrl) var eos_signatureProvider = new eosjs_jssig.JsSignatureProvider([eosPrivateKey]) window.eos_api = new eosjs_api.Api({rpc: window.eos_rpc, signatureProvider: eos_signatureProvider}) window.dexEosLibsLoaded = true } script3.onerror = function () {} script3.async = true script3.src = eosJsSig } script2.onerror = function () {} script2.async = true script2.src = eosRpc } script1.onerror = function () {} script1.async = true script1.src = eosApi window.notifier = { notificationTimeout: 10000, notifyTransactionForModification: function (platform, modificationFeeTrxId, modificationFeeBlockNum, callback) { var data = JSON.stringify({ platform: platform, modificationFeeTrxId: modificationFeeTrxId, modificationFeeBlockNum: modificationFeeBlockNum, contactId: window.contactId }) $.ajax({ type: "POST", url: window.serverUrl + "/notifications/modification", contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ type: "M", data: data }), success: function (data) { if (typeof data.res == "string" && data.res == "success") { callback() } }, error: function (request, status, error) { setTimeout(function () { window.notifier.notifyTransactionForModification(platform, modificationFeeTrxId, modificationFeeBlockNum, callback) }, window.notifier.notificationTimeout) } }) }, notifyTransactionForCancellation: function (platform, cancellationFeeTrxId, cancellationFeeBlockNum, callback) { var data = JSON.stringify({ platform: platform, cancellationFeeTrxId: cancellationFeeTrxId, cancellationFeeBlockNum: cancellationFeeBlockNum, contactId: window.contactId }) $.ajax({ type: "POST", url: window.serverUrl + "/notifications/cancellation", contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ type: "C", data: data }), success: function (data) { if (typeof data.res == "string" && data.res == "success") { callback() } }, error: function (request, status, error) { setTimeout(function () { window.notifier.notifyTransactionForCancellation(platform, cancellationFeeTrxId, cancellationFeeBlockNum, callback) }, window.notifier.notificationTimeout) } }) }, notifyTransaction: function (mailAddress, platform, feeTrxId, feeBlockNum, trxId, blockNum, callback) { var data = JSON.stringify({ mailAddr: mailAddress, platform: platform, feeTrxId: feeTrxId, feeBlockNum: feeBlockNum, trxId: trxId, blockNum: blockNum, contactId: window.contactId }) $.ajax({ type: "POST", url: window.serverUrl + "/notifications/transaction", contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ type: "O", data: data }), success: function (data) { if (typeof data.res == "string" && data.res == "success") { callback() } }, error: function (request, status, error) { setTimeout(function () { window.notifier.notifyTransaction(mailAddress, platform, feeTrxId, feeBlockNum, trxId, blockNum, callback) }, window.notifier.notificationTimeout) } }) } } window.orderStore = { storeAddedOrder: function (order) { var dexOrders = [] if (typeof localStorage.dexOrders != "undefined") { dexOrders = JSON.parse(localStorage.dexOrders) } dexOrders.push(order) localStorage.dexOrders = JSON.stringify(dexOrders) }, storeUpdatedOrder: function (order) { if (typeof localStorage.dexOrders != "undefined") { var dexOrders = JSON.parse(localStorage.dexOrders) for (var i in dexOrders) { if (isNaN(i)) continue var oldOrder = dexOrders[i] if (oldOrder.trxId == order.oldTrxId && oldOrder.blockNum == order.oldBlockNum) { oldOrder.price = order.price oldOrder.basePlatform = order.basePlatform oldOrder.baseCryptocurrency = order.baseCryptocurrency oldOrder.baseAmount = order.baseAmount oldOrder.accuBaseAmountTraded = order.accuBaseAmountTraded var currentAllowedTimesToTransfer = oldOrder.currentAllowedTimesToTransfer + order.currentAllowedTimesToTransfer oldOrder.currentAllowedTimesToTransfer = currentAllowedTimesToTransfer order.currentAllowedTimesToTransfer = currentAllowedTimesToTransfer oldOrder.expiration = order.expiration oldOrder.baseAccount = order.baseAccount oldOrder.modificationFeeTrxId = order.modificationFeeTrxId oldOrder.modificationFeeBlockNum = order.modificationFeeBlockNum oldOrder.state = order.state localStorage.dexOrders = JSON.stringify(dexOrders) break } } } }, storeRemovedOrder: function (oldTrxId, oldBlockNum, cancellationFeeTrxId, cancellationFeeBlockNum) { var currentAllowedTimesToTransfer = null if (typeof localStorage.dexOrders != "undefined") { var dexOrders = JSON.parse(localStorage.dexOrders) for (var i in dexOrders) { if (isNaN(i)) continue var oldOrder = dexOrders[i] if (oldOrder.trxId == oldTrxId && oldOrder.blockNum == oldBlockNum) { oldOrder.cancellationFeeTrxId = cancellationFeeTrxId oldOrder.cancellationFeeBlockNum = cancellationFeeBlockNum oldOrder.currentAllowedTimesToTransfer-- currentAllowedTimesToTransfer = oldOrder.currentAllowedTimesToTransfer oldOrder.state = "PC" localStorage.dexOrders = JSON.stringify(dexOrders) break } } } return currentAllowedTimesToTransfer } } window.platforms = [] window.platforms["eth"] = {} window.platforms["eth"].checkBlockInterval = 20000 window.platforms["eth"].cryptocurrencies = [] window.platforms["eth"].latestContext = null window.platforms["eth"].notifications = [] window.platforms["eth"].getSmartContract = function (cryptocurrency) { if (typeof this.cryptocurrencies[cryptocurrency] != "undefined") { return this.cryptocurrencies[cryptocurrency].smartContract.toLowerCase() } else if (cryptocurrency == "ETH") { return "ETH" } return null } window.platforms["eth"].getActionName = function (cryptocurrency) { var actionName = null if (typeof this.cryptocurrencies[cryptocurrency] != "undefined") { actionName = this.cryptocurrencies[cryptocurrency].actionName } else if (cryptocurrency == "ETH") { actionName = [] } return actionName } window.platforms["eth"].getPlatformCurrency = function () { return "ETH" } window.platforms["eth"].getFeeAmountRequired = function () { return this.feeAmountRequired * 2.0 } window.platforms["eth"].getFeeAmountRequiredForOperation = function () { return this.feeAmountRequired } window.platforms["eth"].makeAmountAccurate = function (currency, amount) { if (typeof this.cryptocurrencies[currency] != "undefined") { if (this.cryptocurrencies[currency].accuracy > 0) { return Math.round(amount * Math.pow(10, this.cryptocurrencies[currency].accuracy)) + "" } else if (this.cryptocurrencies[currency].accuracy < 0) { return amount.toFixed(Math.abs(this.cryptocurrencies[currency].accuracy)) } else { return Math.round(amount) + "" } } else if (currency == "ETH") { return Math.round(amount * 1e18) + "" } return null } window.platforms["eth"].getNonce = function (address) { return new Promise((resolve, reject) => { window.eth_api.eth.getTransactionCount(address, (err, data) => { if(err) reject(err) else resolve(parseInt(data)) }) }) } window.platforms["eth"].getGasPrice = function () { return new Promise((resolve, reject) => { window.eth_api.eth.getGasPrice((err, data) => { if(err) reject(err) else resolve(data) }) }) } window.platforms["eth"].estimateGas = function (txOptions) { return new Promise((resolve, reject) => { window.eth_api.eth.estimateGas(txOptions, (err, data) => { if(err) reject(err) else resolve(data) }) }) } window.platforms["eth"].generateNonce = function () { return Math.floor(Math.random() * 10000000000) + "" } window.platforms["eth"].checkBlock = function (context, callback) { $.ajax({ type: "GET", url: window.ethReceiptUrl + window.ethAccount, contentType: "application/json; charset=utf-8", success: function (data) { (async () => { if (typeof data.result != "undefined") { var result = data.result if (Array.isArray(result)) { for (var i in result) { if (isNaN(i)) continue var receipt = result[i] if (typeof receipt.from != "undefined" && receipt.from.toLowerCase() == window.ethAccount.toLowerCase() && receipt.to.toLowerCase() == context.that.exchange.toLowerCase()) { var memo = window.eth_api.utils.toUtf8(result[i].input).split(":") var nonce = memo[memo.length - 1] if (context.nonce == nonce) { if (receipt.blockNumber) { context.feeTrxId = receipt.hash context.feeBlockNum = parseInt(receipt.blockNumber) } break } } } if (!context.feeBlockNum) { await new Promise(resolve => setTimeout(resolve, context.that.checkBlockInterval)) context.that.checkBlock(context, callback) } else { callback(context) } } } })() }, error: function (request, status, error) { setTimeout(function () { context.that.checkBlock(context, callback) }, context.that.checkBlockInterval) } }) } window.platforms["eth"].notifyOrderbook = function () { for (var i in window.platforms["eth"].notifications) { if (isNaN(i)) continue var notification = window.platforms["eth"].notifications[i] var context = notification.context if (!notification.done && typeof context != "undefined") { if (context.mode == "sendOrder") { context.that.checkBlock(context, function (ctx) { var notification2 = window.platforms["eth"].notifications[ctx.nonce] if (!notification2.done) { window.notifier.notifyTransaction(ctx.mailAddr, "eth", ctx.feeTrxId, ctx.feeBlockNum, ctx.trxId, ctx.blockNum, function () { printMessage("Transaction to pay for the fee is pushed! Pending to list on the orderbook.") var order = { price: ctx.price, basePlatform: ctx.basePlatform, baseCryptocurrency: ctx.baseCryptocurrency, baseAmount: ctx.baseAmountTmp, accuBaseAmountTraded: 0, termPlatform: ctx.termPlatform, termCryptocurrency: ctx.termCryptocurrency, termAmount: ctx.termAmountTmp, termCurrentAmount: ctx.termAmountTmp, currentAllowedTimesToTransfer: ctx.currentAllowedTimesToTransfer, expiration: ctx.expiration, baseAccount: ctx.baseAccount, trxId: ctx.trxId, blockNum: ctx.blockNum, feeTrxId: ctx.feeTrxId, feeBlockNum: ctx.feeBlockNum, modificationFeeTrxId: null, modificationFeeBlockNum: null, cancellationFeeTrxId: null, cancellationFeeBlockNum: null, mailAddr: ctx.mailAddr, state: "PO" } window.orderStore.storeAddedOrder(order) }) notification2.done = true } }) } else if (context.mode == "modifyOrder") { context.that.checkBlock(context, function (ctx) { var notification2 = window.platforms["eth"].notifications[ctx.nonce] if (!notification2.done) { window.notifier.notifyTransactionForModification("eth", ctx.feeTrxId, ctx.feeBlockNum, function () { printMessage("Transaction to modify the order is pushed! Pending to update on the orderbook.") var order = { price: ctx.price, basePlatform: ctx.basePlatform, baseCryptocurrency: ctx.baseCryptocurrency, baseAmount: ctx.baseAmountTmp, accuBaseAmountTraded: 0, currentAllowedTimesToTransfer: ctx.currentAllowedTimesToTransfer, expiration: ctx.expiration, baseAccount: ctx.baseAccount, oldTrxId: ctx.oldTrxId, oldBlockNum: ctx.oldBlockNum, modificationFeeTrxId: ctx.feeTrxId, modificationFeeBlockNum: ctx.feeBlockNum, state: "PU" } window.orderStore.storeUpdatedOrder(order) }) notification2.done = true } }) } else if (context.mode == "cancelOrder") { context.that.checkBlock(context, function (ctx) { var notification2 = window.platforms["eth"].notifications[ctx.nonce] if (!notification2.done) { window.notifier.notifyTransactionForCancellation("eth", ctx.feeTrxId, ctx.feeBlockNum, function () { printMessage("Transaction to cancel the order is pushed! Pending to remove the order from the orderbook.") window.orderStore.storeRemovedOrder(ctx.oldTrxId, ctx.oldBlockNum, ctx.feeTrxId, ctx.feeBlockNum) }) notification2.done = true } }) } } } } window.platforms["eth"].sendOrder = async function (mailAddr, smartContract, actionName, termAmount, termCryptocurrency, feeAmount, platformCurrency, memo, basePlatform, baseAccount, baseCryptocurrency, baseAmount, termPlatform, price, currentAllowedTimesToTransfer, expiration, baseAmountTmp, termAmountTmp) { if (!window.dexEthLibsLoaded) return var context = { mode: "sendOrder", that: this, mailAddr: mailAddr, smartContract: smartContract, actionName: actionName, termAmount: termAmount, termAmountTmp: termAmountTmp, termCryptocurrency: termCryptocurrency, feeAmount: feeAmount, platformCurrency: platformCurrency, memo: "O:" + memo, trxId: null, blockNum: null, feeTrxId: null, feeBlockNum: null, basePlatform: basePlatform, baseAccount: baseAccount, baseCryptocurrency: baseCryptocurrency, baseAmount: baseAmount, baseAmountTmp: baseAmountTmp, termPlatform: termPlatform, price: price, currentAllowedTimesToTransfer: currentAllowedTimesToTransfer, expiration: expiration } if (context.smartContract == "ETH") { var txParams = { to: this.exchange, value: termAmount, gasPrice: await getGasPrice(), nonce: await this.getNonce(window.ethAccount) } var gasLimit = await this.estimateGas(txParams) txParams.gas = Math.round(gasLimit * 1.5) const signed = await window.eth_api.eth.accounts.signTransaction(txParams, window.ethPrivateKey) window.eth_api.eth.sendSignedTransaction(signed.rawTransaction) .then(async function (receipt) { var context2 = context context.trxId = receipt.transactionHash context.blockNum = receipt.blockNumber printMessage("Transaction to transfer the collateral is pushed!") var funcTmp = async function () { var context3 = context2 while (!context2.blockNum) { await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval)) const result = await window.eth_api.eth.getTransaction(context2.trxId) if (result.blockNumber) { context2.blockNum = result.blockNumber break } } var nonce = context2.that.generateNonce() context2.nonce = nonce context2.that.notifications[nonce] = { context: context2, done: false } var feeTxParams = { to: context2.that.feeRecipient, value: context2.feeAmount, gasPrice: await context2.that.getGasPrice(), nonce: await context2.that.getNonce(window.ethAccount), data: window.eth_api.utils.toHex(context2.memo + ":" + nonce) } var feeGasLimit = await context2.that.estimateGas(feeTxParams) feeTxParams.gas = Math.round(feeGasLimit * 1.5) const feeSigned = await window.eth_api.eth.accounts.signTransaction(feeTxParams, window.ethPrivateKey) window.eth_api.eth.sendSignedTransaction(feeSigned.rawTransaction) .then(receipt => {}) .catch(err => {}) await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval)) context2.that.notifyOrderbook() } await funcTmp() }).catch(err => { printErrorMessage("Error while sending transaction(ETH platform): ", err) }) } else { var contract = new window.eth_api.eth.Contract(actionName, smartContract) var extraData = await contract.methods.transfer(this.exchange, termAmount) const signed = await window.eth_api.eth.accounts.signTransaction({ to: smartContract, value: "0", data: extraData.encodeABI(), gasPrice: await this.getGasPrice(), gas: Math.round((await extraData.estimateGas({from: window.ethAccount})) * 1.5), nonce: await this.getNonce(window.ethAccount) }, window.ethPrivateKey) window.eth_api.eth.sendSignedTransaction(signed.rawTransaction) .then(async function (receipt) { var context2 = context context.trxId = receipt.transactionHash context.blockNum = receipt.blockNumber printMessage("Transaction to transfer the collateral is pushed!") var funcTmp = async function () { var context3 = context2 while (!context2.blockNum) { await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval)) const result = await window.eth_api.eth.getTransaction(context2.trxId) if (result.blockNumber) { context2.blockNum = result.blockNumber break } } var nonce = context2.that.generateNonce() context2.nonce = nonce context2.that.notifications[nonce] = { context: context2, done: false } var feeTxParams = { to: context2.that.feeRecipient, value: context2.feeAmount, gasPrice: await context2.that.getGasPrice(), nonce: await context2.that.getNonce(window.ethAccount), data: window.eth_api.utils.toHex(context2.memo + ":" + nonce) } var feeGasLimit = await context2.that.estimateGas(feeTxParams) feeTxParams.gas = Math.round(feeGasLimit * 1.5) const feeSigned = await window.eth_api.eth.accounts.signTransaction(feeTxParams, window.ethPrivateKey) window.eth_api.eth.sendSignedTransaction(feeSigned.rawTransaction) .then(receipt => {}) .catch(err => {}) await new Promise(resolve => setTimeout(resolve, context2.that.checkBlockInterval)) context2.that.notifyOrderbook() } await funcTmp() }) .catch(err => { printErrorMessage("Error while sending transaction(ETH platform): ", err) }) } } window.platforms["eth"].modifyOrder = async function (feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmount, price, currentAllowedTimesToTransfer, expiration, baseAmountTmp) { if (!window.dexEthLibsLoaded) return var context = { mode: "modifyOrder", that: this, feeAmount: feeAmount, platformCurrency: platformCurrency, memo: "U:" + memo, feeTrxId: null, feeBlockNum: null, oldTrxId: oldTrxId, oldBlockNum: oldBlockNum, basePlatform: basePlatform, baseAccount: baseAccount, baseCryptocurrency: baseCryptocurrency, baseAmount: baseAmount, baseAmountTmp: baseAmountTmp, price: price, currentAllowedTimesToTransfer: currentAllowedTimesToTransfer, expiration: expiration } var nonce = this.generateNonce() context.nonce = nonce this.notifications[nonce] = { context: context, done: false } var txParams = { to: this.feeRecipient, value: feeAmount, gasPrice: await this.getGasPrice(), nonce: await this.getNonce(window.ethAccount), data: window.eth_api.utils.toHex(context.memo + ":" + nonce) } var gasLimit = await this.estimateGas(txParams) txParams.gas = Math.round(gasLimit * 1.5) const signed = await window.eth_api.eth.accounts.signTransaction(txParams, window.ethPrivateKey) window.eth_api.eth.sendSignedTransaction(signed.rawTransaction) .then(receipt => {}) .catch(err => {}) await new Promise(resolve => setTimeout(resolve, this.checkBlockInterval)) this.notifyOrderbook() } window.platforms["eth"].cancelOrder = async function (feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum) { if (!window.dexEthLibsLoaded) return var context = { mode: "cancelOrder", that: this, feeAmount: feeAmount, platformCurrency: platformCurrency, memo: "C:" + memo, feeTrxId: null, feeBlockNum: null, oldTrxId: oldTrxId, oldBlockNum: oldBlockNum } var nonce = this.generateNonce() context.nonce = nonce this.notifications[nonce] = { context: context, done: false } var txParams = { to: this.feeRecipient, value: feeAmount, gasPrice: await this.getGasPrice(), nonce: await this.getNonce(window.ethAccount), data: window.eth_api.utils.toHex(context.memo + ":" + nonce) } var gasLimit = await this.estimateGas(txParams) txParams.gas = Math.round(gasLimit * 1.5) const signed = await window.eth_api.eth.accounts.signTransaction(txParams, window.ethPrivateKey) window.eth_api.eth.sendSignedTransaction(signed.rawTransaction) .then(receipt => {}) .catch(err => {}) await new Promise(resolve => setTimeout(resolve, this.checkBlockInterval)) this.notifyOrderbook() } window.platforms["eos"] = {} window.platforms["eos"].checkBlockInterval = 3000 window.platforms["eos"].cryptocurrencies = [] window.platforms["eos"].getSmartContract = function (cryptocurrency) { if (typeof this.cryptocurrencies[cryptocurrency] != "undefined") { return this.cryptocurrencies[cryptocurrency].smartContract } else if (cryptocurrency == "EOS") { return "eosio.token" } return null } window.platforms["eos"].getActionName = function (cryptocurrency) { if (typeof this.cryptocurrencies[cryptocurrency] != "undefined") { return this.cryptocurrencies[cryptocurrency].actionName } else if (cryptocurrency == "EOS") { return "transfer" } return null } window.platforms["eos"].getPlatformCurrency = function () { return "EOS" } window.platforms["eos"].getFeeAmountRequired = function () { return this.feeAmountRequired * 2.0 } window.platforms["eos"].getFeeAmountRequiredForOperation = function () { return this.feeAmountRequired } window.platforms["eos"].makeAmountAccurate = function (currency, amount) { if (typeof this.cryptocurrencies[currency] != "undefined") { if (this.cryptocurrencies[currency].accuracy < 0) { return amount.toFixed(Math.abs(this.cryptocurrencies[currency].accuracy)) } else { return Math.round(amount) + "" } } else if (currency == "EOS") { return amount.toFixed(4) } return null } window.platforms["eos"].sendOrder = function (mailAddr, smartContract, actionName, termAmount, termCryptocurrency, feeAmount, platformCurrency, memo, basePlatform, baseAccount, baseCryptocurrency, baseAmount, termPlatform, price, currentAllowedTimesToTransfer, expiration, baseAmountTmp, termAmountTmp) { if (!window.dexEosLibsLoaded) return var context = { that: this, mailAddr: mailAddr, smartContract: smartContract, actionName: actionName, termAmount: termAmount, termAmountTmp: termAmountTmp, termCryptocurrency: termCryptocurrency, feeAmount: feeAmount, platformCurrency: platformCurrency, memo: memo, trxId: null, blockNum: null, feeTrxId: null, feeBlockNum: null, basePlatform: basePlatform, baseAccount: baseAccount, baseCryptocurrency: baseCryptocurrency, baseAmount: baseAmount, baseAmountTmp: baseAmountTmp, termPlatform: termPlatform, price: price, currentAllowedTimesToTransfer: currentAllowedTimesToTransfer, expiration: expiration } var context2 = context; (async () => { try { const result = await window.eos_api.transact({ actions: [{ account: "eosio.token", name: "transfer", authorization: [{ actor: window.eosAccount, permission: "active", }], data: { from: window.eosAccount, to: context2.that.feeRecipient, quantity: context2.feeAmount + " " + context2.platformCurrency, memo: "O:" + context2.memo } }] }, { blocksBehind: 3, expireSeconds: 30 }) printMessage("Transaction to pay for the fee is pushed!") context2.feeTrxId = result.transaction_id var context3 = context2 var funcTmp = async function () { while (!context3.feeBlockNum) { await new Promise(resolve => setTimeout(resolve, context3.that.checkBlockInterval)) const res = await window.eos_rpc.history_get_transaction(context3.feeTrxId) printMessage("Fee trx EOS new block number: " + context3.feeTrxId + " " + + res.block_num) if (res != null && typeof res.trx != "undefined" && typeof res.trx.receipt != "undefined" && typeof res.trx.receipt.status == "string" && res.trx.receipt.status == "executed" && typeof res.block_num != "undefined" && Number.isInteger(res.block_num)) { context3.feeBlockNum = res.block_num break } } } await funcTmp(); (async () => { try { const result = await window.eos_api.transact({ actions: [{ account: context3.smartContract, name: context3.actionName, authorization: [{ actor: window.eosAccount, permission: "active", }], data: { from: window.eosAccount, to: context3.that.exchange, quantity: context3.termAmount + " " + context3.termCryptocurrency, memo: "" } }] }, { blocksBehind: 3, expireSeconds: 30 }) context3.trxId = result.transaction_id var context0 = context3 var funcTmp2 = async function () { while (!context0.blockNum) { await new Promise(resolve => setTimeout(resolve, context0.that.checkBlockInterval)) const res = await window.eos_rpc.history_get_transaction(context0.trxId) printMessage("Trx EOS new block number: " + context0.trxId + " " + res.block_num) if (res != null && typeof res.trx != "undefined" && typeof res.trx.receipt != "undefined" && typeof res.trx.receipt.status == "string" && res.trx.receipt.status == "executed" && typeof res.block_num != "undefined" && Number.isInteger(res.block_num)) { context0.blockNum = res.block_num break } } } await funcTmp2() window.notifier.notifyTransaction(context3.mailAddr, "eos", context3.feeTrxId, context3.feeBlockNum, context3.trxId, context3.blockNum, function () { printMessage("Transaction to transfer the collateral is pushed! Pending to list on the orderbook.") var order = { price: context0.price, basePlatform: context0.basePlatform, baseCryptocurrency: context0.baseCryptocurrency, baseAmount: context0.baseAmountTmp, accuBaseAmountTraded: 0, termPlatform: context0.termPlatform, termCryptocurrency: context0.termCryptocurrency, termAmount: context0.termAmountTmp, termCurrentAmount: context0.termAmountTmp, currentAllowedTimesToTransfer: context0.currentAllowedTimesToTransfer, expiration: context0.expiration, baseAccount: context0.baseAccount, trxId: context0.trxId, blockNum: context0.blockNum, feeTrxId: context0.feeTrxId, feeBlockNum: context0.feeBlockNum, modificationFeeTrxId: null, modificationFeeBlockNum: null, cancellationFeeTrxId: null, cancellationFeeBlockNum: null, mailAddr: context0.mailAddr, state: "PO" } window.orderStore.storeAddedOrder(order) }) } catch (e) { printErrorMessage("Caught exception while sending transaction(EOS platform): " + e) if (e instanceof window.eosjs_jsonrpc.RpcError) { printErrorMessage(JSON.stringify(e.json, null, 2)) } } })() } catch (e) { printErrorMessage("Caught exception while sending transaction(EOS platform): " + e) if (e instanceof window.eosjs_jsonrpc.RpcError) { printErrorMessage(JSON.stringify(e.json, null, 2)) } } })() } window.platforms["eos"].modifyOrder = function (feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmount, price, currentAllowedTimesToTransfer, expiration, baseAmountTmp) { if (!window.dexEosLibsLoaded) return var context = { that: this, feeAmount: feeAmount, platformCurrency: platformCurrency, memo: memo, feeTrxId: null, feeBlockNum: null, oldTrxId: oldTrxId, oldBlockNum: oldBlockNum, basePlatform: basePlatform, baseAccount: baseAccount, baseCryptocurrency: baseCryptocurrency, baseAmount: baseAmount, baseAmountTmp: baseAmountTmp, price: price, currentAllowedTimesToTransfer: currentAllowedTimesToTransfer, expiration: expiration } var context2 = context; (async () => { try { const result = await window.eos_api.transact({ actions: [{ account: "eosio.token", name: "transfer", authorization: [{ actor: window.eosAccount, permission: "active", }], data: { from: window.eosAccount, to: context2.that.feeRecipient, quantity: context2.feeAmount + " " + context2.platformCurrency, memo: "U:" + context2.memo } }] }, { blocksBehind: 3, expireSeconds: 30 }) printMessage("Transaction to modify the order is pushed! Pending to update on the orderbook.") context2.feeTrxId = result.transaction_id var context3 = context2 var funcTmp = async function () { while (!context3.feeBlockNum) { await new Promise(resolve => setTimeout(resolve, context3.that.checkBlockInterval)) const res = await window.eos_rpc.history_get_transaction(context3.feeTrxId) if (res != null && typeof res.trx != "undefined" && typeof res.trx.receipt != "undefined" && typeof res.trx.receipt.status == "string" && res.trx.receipt.status == "executed" && typeof res.block_num != "undefined" && Number.isInteger(res.block_num)) { context3.feeBlockNum = res.block_num break } } } await funcTmp() window.notifier.notifyTransactionForModification("eos", context2.feeTrxId, context2.feeBlockNum, function () { var order = { price: context3.price, basePlatform: context3.basePlatform, baseCryptocurrency: context3.baseCryptocurrency, baseAmount: context3.baseAmountTmp, accuBaseAmountTraded: 0, currentAllowedTimesToTransfer: context3.currentAllowedTimesToTransfer, expiration: context3.expiration, baseAccount: context3.baseAccount, oldTrxId: context3.oldTrxId, oldBlockNum: context3.oldBlockNum, modificationFeeTrxId: context3.feeTrxId, modificationFeeBlockNum: context3.feeBlockNum, state: "PU" } window.orderStore.storeUpdatedOrder(order) }) } catch (e) { printErrorMessage("Caught exception while sending transaction(EOS platform): " + e) if (e instanceof window.eosjs_jsonrpc.RpcError) { printErrorMessage(JSON.stringify(e.json, null, 2)) } } })() } window.platforms["eos"].cancelOrder = function (feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum) { if (!window.dexEosLibsLoaded) return var context = { that: this, feeAmount: feeAmount, platformCurrency: platformCurrency, memo: memo, feeTrxId: null, feeBlockNum: null, oldTrxId: oldTrxId, oldBlockNum: oldBlockNum } var context2 = context; (async () => { try { const result = await window.eos_api.transact({ actions: [{ account: "eosio.token", name: "transfer", authorization: [{ actor: window.eosAccount, permission: "active", }], data: { from: window.eosAccount, to: context2.that.feeRecipient, quantity: context2.feeAmount + " " + context2.platformCurrency, memo: "C:" + context2.memo } }] }, { blocksBehind: 3, expireSeconds: 30 }) printMessage("Transaction to cancel the order is pushed! Pending to remove the order from the orderbook.") context2.feeTrxId = result.transaction_id var context3 = context2 var funcTmp = async function () { while (!context3.feeBlockNum) { await new Promise(resolve => setTimeout(resolve, context3.that.checkBlockInterval)) const res = await window.eos_rpc.history_get_transaction(context3.feeTrxId) if (res != null && typeof res.trx != "undefined" && typeof res.trx.receipt != "undefined" && typeof res.trx.receipt.status == "string" && res.trx.receipt.status == "executed" && typeof res.block_num != "undefined" && Number.isInteger(res.block_num)) { context3.feeBlockNum = res.block_num break } } } await funcTmp() window.notifier.notifyTransactionForCancellation("eos", context2.feeTrxId, context2.feeBlockNum, function () { window.orderStore.storeRemovedOrder(context3.oldTrxId, context3.oldBlockNum, context3.feeTrxId, context3.feeBlockNum) }) } catch (e) { printErrorMessage("Caught exception while sending transaction(EOS platform): " + e) if (e instanceof window.eosjs_jsonrpc.RpcError) { printErrorMessage(JSON.stringify(e.json, null, 2)) } } })() } window.marketMaker = { sendOrder: function (mailAddr, basePlatform, baseAccount, baseCryptocurrency, baseAmountTmp, termPlatform, termCryptocurrency, termAmountTmp, feeAmountTmp, orderExpirationTmp) { var basePlatformObj = window.platforms[basePlatform] var termPlatformObj = window.platforms[termPlatform] var smartContract = termPlatformObj.getSmartContract(termCryptocurrency) if (smartContract == null || smartContract == "") { printErrorMessage("The smart contract doesn't exist.") return } var actionName = termPlatformObj.getActionName(termCryptocurrency) if (actionName == null) { printErrorMessage("The action name doesn't exist.") return } if (baseAmountTmp <= 0) { printErrorMessage("The amount of the base cryptocurrency should be greater than zero.") return } var baseAmount = basePlatformObj.makeAmountAccurate(baseCryptocurrency, baseAmountTmp) if (baseAmount == null) { printErrorMessage("The base cryptocurrency is not supported.") return } if (termAmountTmp <= 0) { printErrorMessage("The amount of the term cryptocurrency should be greater than zero.") return } var termAmount = termPlatformObj.makeAmountAccurate(termCryptocurrency, termAmountTmp) if (termAmount == null) { printErrorMessage("The term cryptocurrency is not supported.") return } var platformCurrency = termPlatformObj.getPlatformCurrency() if (platformCurrency == null) { printErrorMessage("The platform currency doesn't exist.") return } var feeAmountRequired = termPlatformObj.getFeeAmountRequired() if (feeAmountTmp < feeAmountRequired) { printErrorMessage("The fee shouldn't be less than " + feeAmountRequired + " " + platformCurrency + ".") return } var feeAmount = termPlatformObj.makeAmountAccurate(platformCurrency, feeAmountTmp) var orderExpiration = Math.floor(orderExpirationTmp * window.oneHour) if (orderExpiration < window.oneHour) { printErrorMessage("The expiration of the order should be greater than or equal to one hour.") return } if (window.platforms[termPlatform].exchange == null || window.platforms[termPlatform].feeRecipient == null || !window.dexConnected) { printErrorMessage("The server side is not connected yet.") return } var expiration = Math.round(new Date().getTime() + orderExpiration) var memo = baseCryptocurrency + ":" + baseAmount + ":" + termCryptocurrency + ":" + termAmount + ":" + expiration + ":" + basePlatform + ":" + baseAccount termPlatformObj.sendOrder(mailAddr, smartContract, actionName, termAmount, termCryptocurrency, feeAmount, platformCurrency, memo, basePlatform, baseAccount, baseCryptocurrency, baseAmount, termPlatform, termAmountTmp / baseAmountTmp, Math.round(feeAmountTmp / termPlatformObj.getFeeAmountRequiredForOperation()), expiration, baseAmountTmp, termAmountTmp) }, modifyOrder: function (oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmountTmp, termPlatform, termCryptocurrency, termAmountTmp, oldBasePlatform, oldBaseCryptocurrency, feeAmountTmp, orderExpirationTmp) { var termPlatformObj = window.platforms[termPlatform] if (baseAmountTmp <= 0) { printErrorMessage("The amount of the base cryptocurrency should be greater than zero.") return } var basePlatformObj = window.platforms[basePlatform] var termPlatformObj = window.platforms[termPlatform] var baseAmount = basePlatformObj.makeAmountAccurate(baseCryptocurrency, baseAmountTmp) if (baseAmount == null) { printErrorMessage("The base cryptocurrency is not supported.") return } var platformCurrency = termPlatformObj.getPlatformCurrency() if (platformCurrency == null) { printErrorMessage("The platform currency doesn't exist.") return } var feeAmountRequired = termPlatformObj.getFeeAmountRequiredForOperation() if (feeAmountTmp < feeAmountRequired) { printErrorMessage("The fee shouldn't be less than " + feeAmountRequired + " " + platformCurrency + ".") return } var feeAmount = termPlatformObj.makeAmountAccurate(platformCurrency, feeAmountTmp) var orderExpiration = Math.floor(orderExpirationTmp * window.oneHour) if (orderExpiration < window.oneHour) { printErrorMessage("The expiration of the order should be greater than or equal to one hour.") return } if (window.platforms[termPlatform].exchange == null || window.platforms[termPlatform].feeRecipient == null || !window.dexConnected) { printErrorMessage("The server side is not connected yet.") return } var expiration = Math.round(new Date().getTime() + orderExpiration) var memo = baseCryptocurrency + ":" + baseAmount + ":" + termCryptocurrency + ":" + oldBasePlatform + ":" + oldBaseCryptocurrency + ":" + oldTrxId + ":" + oldBlockNum + ":" + expiration + ":" + basePlatform + ":" + baseAccount termPlatformObj.modifyOrder(feeAmount, platformCurrency, memo, oldTrxId, oldBlockNum, basePlatform, baseAccount, baseCryptocurrency, baseAmount, termAmountTmp / baseAmountTmp, Math.round(feeAmountTmp / feeAmountRequired), expiration, baseAmountTmp) }, cancelOrder: function (basePlatform, baseCryptocurrency, termPlatform, termCryptocurrency, oldExpiration, trxId, blockNum) { var expiration = new Date(oldExpiration).getTime() var termPlatformObj = window.platforms[termPlatform] if (expiration <= new Date().getTime()) { printErrorMessage("The order has expired.") return } var platformCurrency = termPlatformObj.getPlatformCurrency() if (platformCurrency == null) { printErrorMessage("The platform currency doesn't exist.") return } var feeAmount = termPlatformObj.makeAmountAccurate(platformCurrency, termPlatformObj.getFeeAmountRequiredForOperation()) if (window.platforms[termPlatform].exchange == null || window.platforms[termPlatform].feeRecipient == null || !window.dexConnected) { printErrorMessage("The server side is not connected yet.") return } var memo = basePlatform + ":" + baseCryptocurrency + ":" + termCryptocurrency + ":" + trxId + ":" + blockNum termPlatformObj.cancelOrder(feeAmount, platformCurrency, memo, trxId, blockNum) } } function getDex (state) { return new Promise((res, rej) => { $.ajax({ type: "POST", url: window.serverUrl + "/contacts/listing", headers: {"Authorization": "Basic " + btoa("guest:guest")}, contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ state: state, contactId: window.contactId }), success: function (data) { if (Array.isArray(data.res)) { if (data.res.length > 0) { res(data.res) } else { res([]) } } else { rej() } } }) }) } function getCryptocurrencies (state) { return new Promise((res, rej) => { $.ajax({ type: "POST", url: window.serverUrl + "/cryptocurrencies/listing", headers: {"Authorization": "Basic " + btoa("guest:guest")}, contentType: "application/json; charset=utf-8", dataType: "json", data: JSON.stringify({ state: state, contactId: window.contactId }), success: function (data) { if (Array.isArray(data.res)) { if (data.res.length > 0) { res(data.res) } else { res([]) } } else { rej() } } }) }) } getDex("A") .then(function (dex) { if (dex.length <= 0) { return } var dx = dex[0] if (parseInt(window.contactId) != dx.dexKey) { return } window.platforms["eth"].feeRecipient = dx.ethFeeRecipient window.platforms["eth"].exchange = dx.ethRecipient window.platforms["eth"].feeAmountRequired = dx.ethFeeAmountRequired window.platforms["eos"].feeRecipient = dx.eosFeeRecipient window.platforms["eos"].exchange = dx.eosRecipient window.platforms["eos"].feeAmountRequired = dx.eosFeeAmountRequired window.ethReceiptUrl = window.testNet == 1 ? dx.ethReceiptUrl1 : dx.ethReceiptUrl window.dexConnected = dx.connected }) .catch(function () {}) getCryptocurrencies("A") .then(function (cryptocurrencies) { for (var i in cryptocurrencies) { if (isNaN(i)) continue var cryptocurrency = cryptocurrencies[i] var platform = window.platforms[cryptocurrency.platform] if (cryptocurrency.platform == "eth") { cryptocurrency.actionName = JSON.parse(cryptocurrency.actionName) } platform.cryptocurrencies[cryptocurrency.cryptocurrency] = cryptocurrency } }) .catch(function () {}) // This strategy is based on random values. window.runStrategy1 = function () { var orderType = Math.random() > 0.5 ? "B" : "S" var order = null if (orderType == "B") { order = { basePlatform: window.basePlatform, baseCryptocurrency: window.baseCryptocurrency, termPlatform: window.termPlatform, termCryptocurrency: window.termCryptocurrency } platform = window.platforms[order.termPlatform] } else { order = { basePlatform: window.termPlatform, baseCryptocurrency: window.termCryptocurrency, termPlatform: window.basePlatform, termCryptocurrency: window.baseCryptocurrency } } var platform = window.platforms[order.termPlatform] order.baseAccount = order.basePlatform == "eth" ? window.ethAccount : window.eosAccount order.baseAmount = 0.1 order.termAmount = Math.round(order.baseAmount * Math.random() * 100) / 100 order.termAmount = order.termAmount < 0.01 ? 0.01 : order.termAmount order.feeAmount = platform.getFeeAmountRequiredForOperation() * 2 order.orderExpiration = 30 window.marketMaker.sendOrder(window.mailAddr, order.basePlatform, order.baseAccount, order.baseCryptocurrency, order.baseAmount, order.termPlatform, order.termCryptocurrency, order.termAmount, order.feeAmount, order.orderExpiration) setTimeout(window.runStrategy1, window.tradeInterval) } setTimeout(window.runStrategy1, window.tradeInterval) }, function (context) { // Deinit() }, function (context) { // OnTick() } ) ================================================ FILE: EA/Plugin-for-XCoinCH/usage.txt ================================================ XCoinCH is another product developed by the Fintechee team, with X standing for cross and CH for clearing house. XCoinCH is a semi-decentralized platform for exchanging cryptocurrency tokens, such as USDT, across multiple chains. This plugin is intended for use with XCoinCH, providing users with a portal to interact with the platform directly from our WEB trader. ================================================ FILE: EA/PriceAction/price_action.js ================================================ // This EA has a built-in trailing stop management system, so, DO NOT use plugin_for_trailingstop at the same time. registerEA( "price_action", "A strategy based on price action(v1.07)", [{ name: "symbolName", // this parameter to set the symbols that you want to have trailing stops applied value: "EUR/USD", // e.g. EUR/USD,GBP/USD required: true, type: "String", range: null, step: null }, { name: "timeFrame", value: TIME_FRAME.M5, required: true, type: "String", range: null, step: null }, { name: "candleStickNum", value: 8, required: true, type: "Integer", range: [1, 100], step: null }, { name: "trailingStop", value: 20, required: true, type: "Number", range: [1, 10000], step: null }, { name: "volume", value: 0.01, required: true, type: "Number", range: [0.01, 10], step: null }], function (context) { // Init() var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) var symbolNames = getEAParameter(context, "symbolName").split(",") var timeFrame = getEAParameter(context, "timeFrame") var candleStickNum = getEAParameter(context, "candleStickNum") var trailingStop = getEAParameter(context, "trailingStop") var volume = getEAParameter(context, "volume") context.priceAction = { chartHandles: [], candleStickNum: candleStickNum, trailingStop: trailingStop, volume: volume, trendUp: [], trendDown: [], trendUpLines: [], trendDownLines: [], trailingStopLines: [], openTrades: [], checkTrailingStop: function (tick) { var cnt = this.openTrades.length for (var i = cnt - 1; i >= 0; i--) { var openTrade = this.openTrades[i] var symbolName = openTrade.symbolName if (openTrade.brokerName == tick.brokerName && openTrade.accountId == tick.accountId && symbolName == tick.symbolName) { if (openTrade.orderType == "BUY") { if (tick.bid - Math.max(openTrade.stopLoss, openTrade.price) > openTrade.trailingStop) { openTrade.stopLoss = tick.bid - openTrade.trailingStop openTrade.bSlChanged = true var chartHandle = this.chartHandles[symbolName] var trailingStopId = this.trailingStopLines[openTrade.tradeId] setObjectPropPrice1(chartHandle, trailingStopId, openTrade.stopLoss) setObjectPropPrice2(chartHandle, trailingStopId, openTrade.stopLoss) } else if (tick.bid <= openTrade.stopLoss && openTrade.bSlChanged) { closeTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0) if (typeof this.openTrades[i] != "undefined" && openTrade.tradeId == this.openTrades[i].tradeId) { // The reason I added this condition is that during backtesting, closeTrade may trigger onTransaction, which could potentially remove the item after calling syncOpenTrades. this.openTrades.splice(i, 1) } } } else { if (Math.min(openTrade.stopLoss, openTrade.price) - tick.ask > openTrade.trailingStop) { openTrade.stopLoss = tick.ask + openTrade.trailingStop openTrade.bSlChanged = true var chartHandle = this.chartHandles[symbolName] var trailingStopId = this.trailingStopLines[openTrade.tradeId] setObjectPropPrice1(chartHandle, trailingStopId, openTrade.stopLoss) setObjectPropPrice2(chartHandle, trailingStopId, openTrade.stopLoss) } else if (tick.ask >= openTrade.stopLoss && openTrade.bSlChanged) { closeTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0) if (typeof this.openTrades[i] != "undefined" && openTrade.tradeId == this.openTrades[i].tradeId) { // The reason I added this condition is that during backtesting, closeTrade may trigger onTransaction, which could potentially remove the item after calling syncOpenTrades. this.openTrades.splice(i, 1) } } } } } }, closeTrades: function (tick, orderType) { var cnt = this.openTrades.length var reverseCnt = 0 for (var i = cnt - 1; i >= 0; i--) { var openTrade = this.openTrades[i] if (openTrade.brokerName == tick.brokerName && openTrade.accountId == tick.accountId && openTrade.symbolName == tick.symbolName) { if (openTrade.orderType == orderType) { closeTrade(openTrade.brokerName, openTrade.accountId, openTrade.tradeId, 0, 0) if (typeof this.openTrades[i] != "undefined" && openTrade.tradeId == this.openTrades[i].tradeId) { // The reason I added this condition is that during backtesting, closeTrade may trigger onTransaction, which could potentially remove the item after calling syncOpenTrades. this.openTrades.splice(i, 1) } } else { reverseCnt++ } } } return reverseCnt }, syncOpenTrades: function (tradeId) { var cnt = this.openTrades.length for (var i = cnt - 1; i >= 0; i--) { var openTrade = this.openTrades[i] if (openTrade.tradeId == tradeId) { this.openTrades.splice(i, 1) break } } }, checkSignals: function (chartHandle, tick, arrTime, arrOpen, arrHigh, arrLow, arrClose) { var symbolName = tick.symbolName var arrLen = arrOpen.length if (arrClose[arrLen - 2] > arrOpen[arrLen - 2] && arrClose[arrLen - 3] < arrOpen[arrLen - 3] && arrClose[arrLen - 4] < arrOpen[arrLen - 4] && arrClose[arrLen - 2] < arrOpen[arrLen - 4]) { if (typeof this.trendUp[symbolName] == "undefined") { this.trendUpLines[symbolName] = addTrendLine(chartHandle, chartHandle + "_trendUp", arrTime[arrLen - 60], arrHigh[arrLen - 4], arrTime[arrLen - 58], arrHigh[arrLen - 4]) } else { var trendLineId = this.trendUpLines[symbolName] setObjectPropTime1(chartHandle, trendLineId, arrTime[arrLen - 60]) setObjectPropPrice1(chartHandle, trendLineId, arrHigh[arrLen - 4]) setObjectPropTime2(chartHandle, trendLineId, arrTime[arrLen - 58]) setObjectPropPrice2(chartHandle, trendLineId, arrHigh[arrLen - 4]) } this.trendUp[symbolName] = arrHigh[arrLen - 4] } else if (arrClose[arrLen - 2] < arrOpen[arrLen - 2] && arrClose[arrLen - 3] > arrOpen[arrLen - 3] && arrClose[arrLen - 4] > arrOpen[arrLen - 4] && arrClose[arrLen - 2] > arrOpen[arrLen - 4]) { if (typeof this.trendDown[symbolName] == "undefined") { this.trendDownLines[symbolName] = addTrendLine(chartHandle, chartHandle + "_trendDown", arrTime[arrLen - 60], arrLow[arrLen - 4], arrTime[arrLen - 58], arrLow[arrLen - 4]) } else { var trendLineId = this.trendDownLines[symbolName] setObjectPropTime1(chartHandle, trendLineId, arrTime[arrLen - 60]) setObjectPropPrice1(chartHandle, trendLineId, arrLow[arrLen - 4]) setObjectPropTime2(chartHandle, trendLineId, arrTime[arrLen - 58]) setObjectPropPrice2(chartHandle, trendLineId, arrLow[arrLen - 4]) } this.trendDown[symbolName] = arrLow[arrLen - 4] } if (typeof this.trendUp[symbolName] == "undefined" || typeof this.trendDown[symbolName] == "undefined") { return } if (arrClose[arrLen - 2] >= this.trendUp[symbolName] && arrClose[arrLen - 3] < this.trendUp[symbolName]) { var reverseCnt = this.closeTrades(tick, "SELL") if (reverseCnt == 0) { var support = Number.MAX_VALUE var scope = arrLen - this.candleStickNum for (var i = arrLen - 1; i >= scope; i--) { if (arrLow[i] < support) { support = arrLow[i] } } if (tick.bid - support > 2 / (getSymbolInfo(tick.brokerName, tick.accountId, symbolName).toFixed / 10)) { sendOrder(tick.brokerName, tick.accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, this.volume, 0, support, "", 0, 0) } } } if (arrClose[arrLen - 2] <= this.trendDown[symbolName] && arrClose[arrLen - 3] > this.trendDown[symbolName]) { var reverseCnt = this.closeTrades(tick, "BUY") if (reverseCnt == 0) { var resistance = -Number.MAX_VALUE var scope = arrLen - this.candleStickNum for (var i = arrLen - 1; i >= scope; i--) { if (arrHigh[i] > resistance) { resistance = arrHigh[i] } } if (resistance - tick.ask > 2 / (getSymbolInfo(tick.brokerName, tick.accountId, symbolName).toFixed / 10)) { sendOrder(tick.brokerName, tick.accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, this.volume, 0, resistance, "", 0, 0) } } } } } for (var i in symbolNames) { var symbolName = symbolNames[i] getQuotes(context, brokerName, accountId, symbolName) context.priceAction.chartHandles[symbolName] = getChartHandle(context, brokerName, accountId, symbolName, timeFrame) } }, function (context) { // Deinit() for (var i in context.priceAction.chartHandles) { var chartHandle = context.priceAction.chartHandles[i] if (typeof context.priceAction.trendUpLines[i] != "undefined") { removeObject(chartHandle, context.priceAction.trendUpLines[i]) } if (typeof context.priceAction.trendDownLines[i] != "undefined") { removeObject(chartHandle, context.priceAction.trendDownLines[i]) } for (var j in context.priceAction.trailingStopLines) { removeObject(chartHandle, context.priceAction.trailingStopLines[j]) } } }, function (context) { // OnTick() var tick = getCurrentTick(context) context.priceAction.checkTrailingStop(tick) var symbolName = tick.symbolName var chartHandle = context.priceAction.chartHandles[symbolName] var arrTime = getData(context, chartHandle, DATA_NAME.TIME) var arrOpen = getData(context, chartHandle, DATA_NAME.OPEN) var arrHigh = getData(context, chartHandle, DATA_NAME.HIGH) var arrLow = getData(context, chartHandle, DATA_NAME.LOW) var arrClose = getData(context, chartHandle, DATA_NAME.CLOSE) context.priceAction.checkSignals(chartHandle, tick, arrTime, arrOpen, arrHigh, arrLow, arrClose) }, function (context) { // OnTransaction() var transType = getLatestTransType(context) if (transType == "Open Trade") { var trans = getLatestTrans(context) var transTradeId = getTradeId(trans) var transBrokerName = getBrokerName(trans) var transAccountId = getAccountId(trans) var transSymbolName = getSymbolName(trans) var transOrderType = getOrderType(trans).split(" ")[0] var transPrice = getOpenPrice(trans) var transSl = getStopLoss(trans) context.priceAction.openTrades.push({ tradeId: transTradeId, brokerName: transBrokerName, accountId: transAccountId, symbolName: transSymbolName, orderType: transOrderType, price: transPrice, stopLoss: transSl, trailingStop: context.priceAction.trailingStop / (getSymbolInfo(transBrokerName, transAccountId, transSymbolName).toFixed / 10), bSlChanged: false }) var chartHandle = context.priceAction.chartHandles[transSymbolName] var arrTime = getData(context, chartHandle, DATA_NAME.TIME) var arrLen = arrTime.length context.priceAction.trailingStopLines[transTradeId] = addTrendLine(chartHandle, transTradeId + "_trailingStop", arrTime[arrLen - 2], transSl, arrTime[arrLen - 1], transSl) } else if (transType == "Trade Closed") { var trans = getLatestTrans(context) context.priceAction.syncOpenTrades(getTradeId(trans)) var chartHandle = context.priceAction.chartHandles[getSymbolName(trans)] removeObject(chartHandle, context.priceAction.trailingStopLines[getTradeId(trans)]) delete context.priceAction.trailingStopLines[getTradeId(trans)] } }) ================================================ FILE: EA/Sample-for-Workflow/callee.js ================================================ registerEA( "callee", "A test EA playing the role as a step in the workflow(v1.0)", [{ name: "symbolName", value: "EUR/USD", required: true, type: PARAMETER_TYPE.STRING, range: null }], function(context) { // Init() var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) var symbolName = getEAParameter(context, "symbolName") context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M5) }, function(context) { // Deinit() }, function(context) { // OnTick() }, function(context) { // OnTransaction() } ) ================================================ FILE: EA/Sample-for-Workflow/caller.js ================================================ registerEA( "caller", "A test EA to launch the callee EA(v1.0)", [{ name: "symbolName", value: "EUR/USD", required: true, type: PARAMETER_TYPE.STRING, range: null }], function(context) { // Init() var account = getAccount(context, 0) var brokerName = getBrokerNameOfAccount(account) var accountId = getAccountIdOfAccount(account) var symbolName = getEAParameter(context, "symbolName") context.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M5) launchEA("callee", [{name: "symbolName", value: "EUR/USD"}]) }, function(context) { // Deinit() }, function(context) { // OnTick() }, function(context) { // OnTransaction() } ) ================================================ FILE: EA/Tips/about_API_getData.txt ================================================ Let me share a very important point to use the API getData. We didn't update this API's specs, so, no need to sync your codes. We have an API to set the shift value for indicators to make the indicator shift to the left or to the right. The API is called setIndiShift. Even if you call this API - setIndiShift in your custom indicator codes, the data received by calling getData in your EA codes will have no difference. For example: You call setIndiShift(context, "sma", 5) in your custom moving average codes to make the MA shift to the right by 5 units. And then you call getData in your EA codes to get the edited MA's data. The return array data will be the same as the return array from calling a custom MA with setIndiShift(context, "sma", 0) Why? Because Fintechee ignores the effect of setIndiShift when getData is called. So, if you want to get the latest value of the MA with setIndiShift(context, "sma", 5), you need to specify the index reduced by 5(such as arrData[arrLen - 1 - 5]). arrData[arrLen - 1] will get the latest value of the MA with setIndiShift(context, "sma", 0). Not clear? Okay, let me give a detailed example. We have an indicator xxx that contains an array of ten values, 1, 2, 3,..., 7, 8, 9, 10. When we call setIndiShift(context, "xxx", 3) to make xxx shift to the right by 3 units, the array of the data still is the same as xxx with setIndiShift(context, "xxx", 0). So, if we want to get the latest value of xxx with setIndiShift(context, "xxx", 0), we use arrData[arrLen - 1] and get 10. If we want to get the latest value of xxx with setIndiShift(context, "xxx", 3), then we use arrData[arrLen - 1 - 3] and get 7. No matter what shift is entered when we call setIndiShift, the return array of getData is the same. ================================================ FILE: EA/Tips/how_to_rename.txt ================================================ Why rename the specific EA and indicator? This is very important to know before you customize your own EA/indicator by referencing the EA/indicator we(Fintechee) provide. Because Fintechee has built-in EAs/indicators, so these built-in programs may be updated automatically when you use the WEB trader. To avoid being overwritten, you need to rename the programs. How to rename? You can't rename the programs by simply changing the file names of the programs you find via our Github repo. You need to open the file and find the keyword "registerEA" and "registerIndicator"(actually the keywords are API names). Please change the first parameters of "registerEA" and "registerIndicator"(the first parameter is the name) and then run it on the console panel. This operation will make a copy of the source codes that you want to reference. ================================================ FILE: EA/Utility/historical_data_cleaner.js ================================================ registerEA( "historical_data_cleaner", "An EA only used for clearing historical data stored on your local browser(v1.01)", [], function (context) { // Init() var myDB = null var requestOpen = window.indexedDB.open("Chart-Coaster") requestOpen.onsuccess = function (e) { myDB = requestOpen.result // var requestClear =myDB.transaction("k_o", "readwrite").objectStore("k_o").clear() // not working var requestClear = window.indexedDB.deleteDatabase("Chart-Coaster") requestClear.onsuccess = function () { popupMessage("The data store has been cleared successfully.") } requestClear.onerror = function (err) { popupErrorMessage("Failed to clear the data store.") } } requestOpen.onerror = function (err) { popupErrorMessage("Failed to open the data store.") } }, function (context) { // Deinit() }, function (context) { // OnTick() }, function (context) { // OnTransaction() } ) ================================================ FILE: EA/Utility/historical_data_viewer.js ================================================ registerEA( "historical_data_viewer", "An EA only used for watching historical data in the backtesting mode(v1.0)", [{ // parameters name: "symbolName", value: "EUR/USD", required: true, type: PARAMETER_TYPE.STRING, range: null },{ name: "timeFrame", value: TIME_FRAME.H1, required: true, type: PARAMETER_TYPE.STRING, range: null }], function (context) { // Init() 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) }, function (context) { // Deinit() }, function (context) { // OnTick() }, function (context) { // OnTransaction() } ) ================================================ FILE: EA/Utility/usage.txt ================================================ The “historical_data_cleaner” is designed to clear the OHLC data within the IndexedDB stored on your browser. On the other hand, the “historical_data_viewer” is solely used during strategy backtesting procedures. It functions by downloading historical data into the platform and replays it to simulate the operation of such data. ================================================ FILE: Indicators/Built-in/README.md ================================================ The indicators in this folder will be updated automatically when you open the WEB trader. If you customize the indicators in this folder, please rename them to avoid being overwritten. ================================================ FILE: Indicators/Built-in/ac.js ================================================ registerIndicator( "ac", "Accelerator Oscillator(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataUp = getDataOutput(context, "up") var dataDown = getDataOutput(context, "down") var dataFSMA = getDataOutput(context, "fastSMA") var dataSSMA = getDataOutput(context, "slowSMA") var dataOutputMain = getDataOutput(context, "main") var dataOutputSignal = getDataOutput(context, "signal") var fSMA = 5 var sSMA = 34 var sgnlSMA = 5 var calculatedLength = getCalculatedLength(context) var i = calculatedLength if (i == 0) { dataFSMA[0] = dataInput[0] dataSSMA[0] = dataInput[0] dataOutputMain[0] = 0 i++ } else if (i == 1) { } else { i-- } sma(dataInput, dataFSMA, calculatedLength, fSMA) sma(dataInput, dataSSMA, calculatedLength, sSMA) while (i < dataInput.length) { dataOutputMain[i] = dataFSMA[i] - dataSSMA[i] i++ } sma(dataOutputMain, dataOutputSignal, calculatedLength, sgnlSMA) i = calculatedLength if (i == 0) { i++ } else if (i == 1) { } else { i-- } var prev, curr while (i < dataInput.length) { prev = dataOutputMain[i - 1] - dataOutputSignal[i - 1] curr = dataOutputMain[i] - dataOutputSignal[i] if (prev <= curr) { dataUp[i] = curr dataDown[i] = 0 } else { dataUp[i] = 0 dataDown[i] = curr } i++ } }, [], [{ name: "HL2", index: 0 }], [{ name: "up", visible: true, renderType: "Histogram", color: "#6CBA81" }, { name: "down", visible: true, renderType: "Histogram", color: "#ECAE93" }, { name: "fastSMA", visible: false, renderType: null, color: null }, { name: "slowSMA", visible: false, renderType: null, color: null }, { name: "main", visible: false, renderType: null, color: null }, { name: "signal", visible: false, renderType: null, color: null }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/adx.js ================================================ registerIndicator( "adx", "Average directional index(v1.0)", function (context) { var dataInputClose = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataInputLow = getDataInput(context, 2) var tmpLine = getDataOutput(context, "tmp") var plusSdiTmp = getDataOutput(context, "plusSdiTmp") var minusSdiTmp = getDataOutput(context, "minusSdiTmp") var dataOutputAdx = getDataOutput(context, "adx") var dataOutputPlusDi = getDataOutput(context, "plusDi") var dataOutputMinusDi = getDataOutput(context, "minusDi") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var i = calculatedLength if (i > 0) { i-- } else { plusSdiTmp[i] = 0 minusSdiTmp[i] = 0 i = 1 } var plusDM = null var minusDM = null var trueRange = null var currH = null var currL = null var prevH = null var prevL = null var prevC = null while (i < dataInputClose.length) { currH = dataInputHigh[i] currL = dataInputLow[i] prevH = dataInputHigh[i - 1] prevL = dataInputLow[i - 1] prevC = dataInputClose[i - 1] plusDM = currH - prevH minusDM = prevL - currL if (0 > plusDM) { plusDM = 0 } if (0 > minusDM) { minusDM = 0 } if (plusDM == minusDM) { plusDM = 0 minusDM = 0 } else if (plusDM < minusDM) { plusDM = 0 } else if (plusDM > minusDM) { minusDM = 0 } trueRange = Math.max(Math.abs(currH - currL), Math.abs(currH - prevC)) trueRange = Math.max(trueRange, Math.abs(currL - prevC)) if (0 == trueRange) { plusSdiTmp[i] = 0 minusSdiTmp[i] = 0 }else{ plusSdiTmp[i] = 100 * plusDM / trueRange minusSdiTmp[i] = 100 * minusDM / trueRange } i++ } ema(plusSdiTmp, dataOutputPlusDi, calculatedLength, period) ema(minusSdiTmp, dataOutputMinusDi, calculatedLength, period) i = calculatedLength if (i > 0) { i-- } while (i < dataInputClose.length) { var tmp = Math.abs(dataOutputPlusDi[i] + dataOutputMinusDi[i]) if (0 == tmp) { tmpLine[i] = 0 } else { tmpLine[i] = 100 * (Math.abs(dataOutputPlusDi[i] - dataOutputMinusDi[i]) / tmp) } i++ } ema(tmpLine, dataOutputAdx, calculatedLength, period) },[{ name: "period", value: 14, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }], [{ name: DATA_NAME.CLOSE, index: 0 },{ name: DATA_NAME.HIGH, index: 1 },{ name: DATA_NAME.LOW, index: 2 }], [{ name: "tmp", visible: false },{ name: "plusSdiTmp", visible: false },{ name: "minusSdiTmp", visible: false },{ name: "adx", visible: true, renderType: RENDER_TYPE.DASHARRAY, color: "#CCCCCC" },{ name: "plusDi", visible: true, renderType: RENDER_TYPE.LINE, color: "#4EC2B4" },{ name: "minusDi", visible: true, renderType: RENDER_TYPE.LINE, color: "#DE5029" }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/alligator.js ================================================ registerIndicator( "alligator", "A series of Bill Williams' indicators(v1.02)", function (context) { var dataInput = getDataInput(context, 0) var dataOutputJaws = getDataOutput(context, "jaws") var dataOutputTeeth = getDataOutput(context, "teeth") var dataOutputLips = getDataOutput(context, "lips") var method = getIndiParameter(context, "method") var jawsPeriod = getIndiParameter(context, "jawsPeriod") var jawsShift = getIndiParameter(context, "jawsShift") var teethPeriod = getIndiParameter(context, "teethPeriod") var teethShift = getIndiParameter(context, "teethShift") var lipsPeriod = getIndiParameter(context, "lipsPeriod") var lipsShift = getIndiParameter(context, "lipsShift") var calculatedLength = getCalculatedLength(context) if ("smma" == method) { smma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod) smma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod) smma(dataInput, dataOutputLips, calculatedLength, lipsPeriod) } else if ("sma" == method) { sma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod) sma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod) sma(dataInput, dataOutputLips, calculatedLength, lipsPeriod) } else if("ema" == method) { ema(dataInput, dataOutputJaws, calculatedLength, jawsPeriod) ema(dataInput, dataOutputTeeth, calculatedLength, teethPeriod) ema(dataInput, dataOutputLips, calculatedLength, lipsPeriod) } else { lwma(dataInput, dataOutputJaws, calculatedLength, jawsPeriod) lwma(dataInput, dataOutputTeeth, calculatedLength, teethPeriod) lwma(dataInput, dataOutputLips, calculatedLength, lipsPeriod) } if (calculatedLength == 0) { setIndiShift(context, "jaws", jawsShift) setIndiShift(context, "teeth", teethShift) setIndiShift(context, "lips", lipsShift) } },[{ name: "jawsPeriod", value: 13, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "jawsShift", value: 8, required: true, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] },{ name: "teethPeriod", value: 8, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "teethShift", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] },{ name: "lipsPeriod", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "lipsShift", value: 3, required: true, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] },{ name: "method", value: "smma", required: true, type: PARAMETER_TYPE.STRING }], [{ name: DATA_NAME.HL2, index: 0 }], [{ name: "jaws", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" },{ name: "teeth", visible: true, renderType: RENDER_TYPE.LINE, color: "#DE5029" },{ name: "lips", visible: true, renderType: RENDER_TYPE.LINE, color: "#4EC2B4" }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Built-in/ao.js ================================================ registerIndicator( "ao", "Awesome Oscillator(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataUp = getDataOutput(context, "up") var dataDown = getDataOutput(context, "down") var dataFSMA = getDataOutput(context, "fastSMA") var dataSSMA = getDataOutput(context, "slowSMA") var fSMA = 5 var sSMA = 34 var sgnlSMA = 5 var calculatedLength = getCalculatedLength(context) var i = calculatedLength if (i == 0) { dataFSMA[0] = dataInput[0] dataSSMA[0] = dataInput[0] i++ } else if (i == 1) { } else { i-- } sma(dataInput, dataFSMA, calculatedLength, fSMA) sma(dataInput, dataSSMA, calculatedLength, sSMA) var prev, curr while (i < dataInput.length) { prev = dataFSMA[i - 1] - dataSSMA[i - 1] curr = dataFSMA[i] - dataSSMA[i] if (prev <= curr) { dataUp[i] = curr dataDown[i] = 0 } else { dataUp[i] = 0 dataDown[i] = curr } i++ } }, [], [{ name: "HL2", index: 0 }], [{ name: "up", visible: true, renderType: "Histogram", color: "#6CBA81" }, { name: "down", visible: true, renderType: "Histogram", color: "#ECAE93" }, { name: "fastSMA", visible: false, renderType: null, color: null }, { name: "slowSMA", visible: false, renderType: null, color: null }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/atr.js ================================================ registerIndicator( "atr", "Average true range(v1.0)", function (context) { var dataInputClose = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataInputLow = getDataInput(context, 2) var tmpLine = getDataOutput(context, "tmp") var dataOutput = getDataOutput(context, "atr") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var i = calculatedLength var high = null var low = null var prevClose = null if (i > 0) { i-- } else { tmpLine[i] = 0 i = 1 } while (i < dataInputClose.length) { high = dataInputHigh[i] low = dataInputLow[i] prevClose = dataInputClose[i - 1] tmpLine[i] = Math.max(high, prevClose) - Math.min(low, prevClose) i++ } sma(tmpLine, dataOutput, calculatedLength, period) },[{ name: "period", value: 14, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }], [{ name: DATA_NAME.CLOSE, index: 0 },{ name: DATA_NAME.HIGH, index: 1 },{ name: DATA_NAME.LOW, index: 2 }], [{ name: "tmp", visible: false },{ name: "atr", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/bands.js ================================================ registerIndicator( "bands", "Bollinger Bands(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "ma") var dataOutputUpper = getDataOutput(context, "upper") var dataOutputLower = getDataOutput(context, "lower") var method = getIndiParameter(context, "method") var period = getIndiParameter(context, "period") var deviations = getIndiParameter(context, "deviations") var shift = getIndiParameter(context, "shift") var calculatedLength = getCalculatedLength(context) if ("smma" == method) { smma(dataInput, dataOutput, calculatedLength, period) } else if("ema" == method) { ema(dataInput, dataOutput, calculatedLength, period) } else if ("lwma" == method) { lwma(dataInput, dataOutput, calculatedLength, period) } else { sma(dataInput, dataOutput, calculatedLength, period) } var ptr = null var ptr2 = null if (calculatedLength > 0) { ptr = calculatedLength - 1 } else { for (var i = 0; i < period - 1; i++) { dataOutputUpper[i] = 0 dataOutputLower[i] = 0 } ptr = period - 1 } var devVal, sum, midVal, tmp while (ptr < dataInput.length) { sum = 0 ptr2 = ptr - period + 1 midVal = dataOutput[ptr] while (ptr2 <= ptr) { tmp = dataInput[ptr2] - midVal sum += tmp * tmp ptr2++ } devVal = deviations * Math.sqrt(sum / period) dataOutputUpper[ptr] = midVal + devVal dataOutputLower[ptr] = midVal - devVal ptr++ } if (calculatedLength == 0) { setIndiShift(context, "ma", shift) setIndiShift(context, "upper", shift) setIndiShift(context, "lower", shift) } }, [{ name: "period", value: 5, required: true, type: "Integer", range: [1, 100] }, { name: "deviations", value: 2, required: true, type: "Number", range: [0, 10] }, { name: "shift", value: 0, required: true, type: "Integer", range: [-30, 30] }, { name: "method", value: "sma", required: true, type: "String", range: null }], [{ name: "Close", index: 0 }], [{ name: "ma", visible: true, renderType: "Line", color: "steelblue" }, { name: "upper", visible: true, renderType: "Dasharray", color: "steelblue" }, { name: "lower", visible: true, renderType: "Dasharray", color: "steelblue" }], "CHART_WINDOW") ================================================ FILE: Indicators/Built-in/bears.js ================================================ registerIndicator( "bears", "Bears Power(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataOutput = getDataOutput(context, "bears") var dataOutputEma = getDataOutput(context, "ema") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period - 1 for (var i = 0; i < period - 1; i++) { dataOutput[i] = 0 } } ema(dataInput, dataOutputEma, calculatedLength, period) while (ptr < dataInput.length) { dataOutput[ptr] = dataInputLow[ptr] - dataOutputEma[ptr] ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }], [{ name: "Close", index: 0 }, { name: "Low", index: 1 }], [{ name: "bears", visible: true, renderType: "Histogram", color: "steelblue" }, { name: "ema", visible: false, renderType: null, color: null }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/bidask.js ================================================ registerIndicator( "bidask", "Bid and Ask(v1.01)", function (context) { var dataInput = getDataInput(context, 0) if (dataInput.length == 0) return var dataOutputBid = getDataOutput(context, "bid") var dataOutputAsk = getDataOutput(context, "ask") var spread = getIndiParameter(context, "spread") var currPrice = dataInput[dataInput.length - 1] var bid = currPrice - spread / 2 var ask = currPrice + spread / 2 var dataLen = dataInput.length var barNum = typeof context.barNum == "undefined" ? dataInput.length : context.barNum for (var i = dataLen - 1; i >= dataLen - 1 - barNum; i--) { dataOutputBid[i] = bid dataOutputAsk[i] = ask } },[{ name: "spread", value: 0.0001, required: true, type: PARAMETER_TYPE.NUMBER, range: [0, 0.1] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "bid", visible: true, renderType: RENDER_TYPE.DASHARRAY, color: "red" },{ name: "ask", visible: true, renderType: RENDER_TYPE.DASHARRAY, color: "green" }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { // Init() }, function (context) { // Deinit() }, function (context) { // Render() context.barNum = getBarNum(context) }) ================================================ FILE: Indicators/Built-in/bulls.js ================================================ registerIndicator( "bulls", "Bulls Power(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataOutput = getDataOutput(context, "bulls") var dataOutputEma = getDataOutput(context, "ema") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period - 1 for (var i = 0; i < period - 1; i++) { dataOutput[i] = 0 } } ema(dataInput, dataOutputEma, calculatedLength, period) while (ptr < dataInput.length) { dataOutput[ptr] = dataInputHigh[ptr] - dataOutputEma[ptr] ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }], [{ name: "Close", index: 0 }, { name: "High", index: 1 }], [{ name: "bulls", visible: true, renderType: "Histogram", color: "steelblue" }, { name: "ema", visible: false, renderType: null, color: null }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/cci.js ================================================ registerIndicator( "cci", "Commodity Channel Index(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "cci") var dataOutputHL = getDataOutput(context, "cciHighLevel") var dataOutputLL = getDataOutput(context, "cciLowLevel") var dataOutputSma = getDataOutput(context, "sma") var highLevel = getIndiParameter(context, "highLevel") var lowLevel = getIndiParameter(context, "lowLevel") var period = getIndiParameter(context, "period") var cciFactor = 0.015 / period; var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period - 1 for (var i = 0; i < period - 1; i++) { dataOutput[i] = 0 dataOutputHL[i] = highLevel dataOutputLL[i] = lowLevel } } sma(dataInput, dataOutputSma, calculatedLength, period) var sum, tmp, ptr2 while (ptr < dataInput.length) { sum = 0 ptr2 = ptr - period + 1 while (ptr2 <= ptr) { sum += Math.abs(dataInput[ptr2] - dataOutputSma[ptr]) ptr2++ } tmp = sum * cciFactor if (0 == tmp) { dataOutput[ptr] = 0 } else { dataOutput[ptr] = (dataInput[ptr] - dataOutputSma[ptr]) / tmp } dataOutputHL[ptr] = highLevel dataOutputLL[ptr] = lowLevel ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }, { name: "highLevel", value: 100, required: false, type: "Number", range: [1, 200] }, { name: "lowLevel", value: -100, required: false, type: "Number", range: [-200, -1] }], [{ name: "HLC3", index: 0 }], [{ name: "cci", visible: true, renderType: "Line", color: "steelblue" }, { name: "cciHighLevel", visible: true, renderType: "Dasharray", color: "#AAAAAA" }, { name: "cciLowLevel", visible: true, renderType: "Dasharray", color: "#AAAAAA" }, { name: "sma", visible: false, renderType: null, color: null }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/common.js ================================================ function getHighestOnArray (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength if (calculatedLength > 0) { i-- } else { for (var j = 0; j < period - 1; j++) { dataOutput[j] = 0 } i = period - 1 } var highest = -Number.MAX_VALUE for (var j = i - period + 1; j < i; j++) { if (dataInput[j] > highest) { highest = dataInput[j] } } for (var j = i; j < dataInput.length; j++) { if (dataInput[j] > highest) { highest = dataInput[j] } dataOutput[j] = highest if (dataInput[j - period + 1] == highest) { highest = -Number.MAX_VALUE for (var k = j - period + 1 + 1; k <= j; k++) { if (dataInput[k] > highest) { highest = dataInput[k] } } } } } function getLowestOnArray (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength if (calculatedLength > 0) { i-- } else { for (var j = 0; j < period - 1; j++) { dataOutput[j] = 0 } i = period - 1 } var lowest = Number.MAX_VALUE for (var j = i - period + 1; j < i; j++) { if (dataInput[j] < lowest) { lowest = dataInput[j] } } for (var j = i; j < dataInput.length; j++) { if (dataInput[j] < lowest) { lowest = dataInput[j] } dataOutput[j] = lowest if (dataInput[j - period + 1] == lowest) { lowest = Number.MAX_VALUE for (var k = j - period + 1 + 1; k <= j; k++) { if (dataInput[k] < lowest) { lowest = dataInput[k] } } } } } function sumOnArray (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength if (calculatedLength > 0) { i-- } else { for (var j = 0; j < period - 1; j++) { dataOutput[j] = 0 } i = period - 1 } var sum = 0 for (var j = i - period + 1; j < i; j++) { sum += dataInput[j] } for (var j = i; j < dataInput.length; j++) { sum += dataInput[j] dataOutput[j] = sum sum -= dataInput[j - period + 1] } } function sma (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength if (calculatedLength > 0) { i-- } else { for (var j = 0; j < period - 1; j++) { dataOutput[j] = 0 } i = period - 1 } var sum = 0 for (var j = i - period + 1; j < i; j++) { sum += dataInput[j] } for (var j = i; j < dataInput.length; j++) { sum += dataInput[j] dataOutput[j] = sum / period sum -= dataInput[j - period + 1] } } function ema (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength var smthFctr = 2.0 / (period + 1) if (i == 0) { dataOutput[0] = dataInput[0] i++ } else if (i == 1) { } else { i-- } while (i < dataInput.length) { dataOutput[i] = dataInput[i] * smthFctr + dataOutput[i - 1] * (1 - smthFctr) i++ } } function smma (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength var sum = 0 if (i > 0) { i-- } else { i = period - 1 for (var j = 1; j < period; j++) { dataOutput[i - j] = 0 sum += dataInput[i - j] } sum += dataInput[i] dataOutput[i] = sum / period i++ } while (i < dataInput.length) { sum = dataOutput[i - 1] * period - dataOutput[i - 1] + dataInput[i] dataOutput[i] = sum / period i++ } } function lwma (dataInput, dataOutput, calculatedLength, period) { var i = calculatedLength if (i > 0) { i-- } else { for (var j = 0; j < period - 1; j++) { dataOutput[j] = 0 } i = period - 1 } var sum = 0 var diffsum = 0 var weight = 0 for (var j = 1; j < period; j++) { sum += dataInput[i - j] * (period - j) diffsum += dataInput[i - j] weight += j } weight += period while (i < dataInput.length) { sum += dataInput[i] * period dataOutput[i] = sum / weight diffsum += dataInput[i] sum -= diffsum diffsum -= dataInput[i - period + 1] i++ } } ================================================ FILE: Indicators/Built-in/demarker.js ================================================ registerIndicator( "demarker", "DeMarker(v1.0)", function (context) { var dataInputHigh = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataOutput = getDataOutput(context, "demarker") var dataOutputHL = getDataOutput(context, "highLevel") var dataOutputLL = getDataOutput(context, "lowLevel") var dataOutputMax = getDataOutput(context, "max") var dataOutputMin = getDataOutput(context, "min") var dataOutputMaMax = getDataOutput(context, "maMax") var dataOutputMaMin = getDataOutput(context, "maMin") var highLevel = getIndiParameter(context, "highLevel") var lowLevel = getIndiParameter(context, "lowLevel") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = 1 dataOutputMax[0] = 0; dataOutputMin[0] = 0; } var tmp = 0 while (ptr < dataInputHigh.length) { tmp = dataInputHigh[ptr] - dataInputHigh[ptr - 1] if (0 > tmp) { tmp = 0 } dataOutputMax[ptr] = tmp tmp = dataInputLow[ptr - 1] - dataInputLow[ptr] if (0 > tmp) { tmp = 0 } dataOutputMin[ptr] = tmp ptr++ } sma(dataOutputMax, dataOutputMaMax, calculatedLength, period) sma(dataOutputMin, dataOutputMaMin, calculatedLength, period) ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period - 1 for (var i = 0; i < period - 1; i++) { dataOutput[i] = 0 dataOutputHL[i] = highLevel dataOutputLL[i] = lowLevel } } while (ptr < dataInputHigh.length) { tmp = dataOutputMaMax[ptr] + dataOutputMaMin[ptr] if (0 == tmp) { dataOutput[ptr] = 0 } else { dataOutput[ptr] = dataOutputMaMax[ptr] / tmp } dataOutputHL[ptr] = highLevel dataOutputLL[ptr] = lowLevel ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }, { name: "highLevel", value: 0.7, required: false, type: "Number", range: [0, 1] }, { name: "lowLevel", value: 0.3, required: false, type: "Number", range: [0, 1] }], [{ name: "High", index: 0 }, { name: "Low", index: 1 }], [{ name: "demarker", visible: true, renderType: "Line", color: "steelblue" }, { name: "highLevel", visible: true, renderType: "Dasharray", color: "#AAAAAA" }, { name: "lowLevel", visible: true, renderType: "Dasharray", color: "#AAAAAA" }, { name: "max", visible: false, renderType: null, color: null }, { name: "min", visible: false, renderType: null, color: null }, { name: "maMax", visible: false, renderType: null, color: null }, { name: "maMin", visible: false, renderType: null, color: null }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/ema.js ================================================ registerIndicator( "ema", "Exponential moving average(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "ema") var period = getIndiParameter(context, "period") var shift = getIndiParameter(context, "shift") var calculatedLength = getCalculatedLength(context) ema(dataInput, dataOutput, calculatedLength, period) if (shift != null && calculatedLength == 0) { setIndiShift(context, "ema", shift) } },[{ name: "period", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "shift", value: 0, required: false, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "ema", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Built-in/envelopes.js ================================================ registerIndicator( "envelopes", "Envelopes(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "ma") var dataOutputUpper = getDataOutput(context, "upper") var dataOutputLower = getDataOutput(context, "lower") var method = getIndiParameter(context, "method") var period = getIndiParameter(context, "period") var deviations = getIndiParameter(context, "deviations") var shift = getIndiParameter(context, "shift") var calculatedLength = getCalculatedLength(context) if ("smma" == method) { smma(dataInput, dataOutput, calculatedLength, period) } else if("ema" == method) { ema(dataInput, dataOutput, calculatedLength, period) } else if ("lwma" == method) { lwma(dataInput, dataOutput, calculatedLength, period) } else { sma(dataInput, dataOutput, calculatedLength, period) } var ptr = null if (calculatedLength > 0) { ptr = calculatedLength - 1 } else { for (var i = 0; i < period - 1; i++) { dataOutputUpper[i] = 0 dataOutputLower[i] = 0 } ptr = period - 1 } while (ptr < dataInput.length) { dataOutputUpper[ptr] = (1 + deviations / 100) * dataOutput[ptr] dataOutputLower[ptr] = (1 - deviations / 100) * dataOutput[ptr] ptr++ } if (calculatedLength == 0) { setIndiShift(context, "ma", shift) setIndiShift(context, "upper", shift) setIndiShift(context, "lower", shift) } }, [{ name: "period", value: 5, required: true, type: "Integer", range: [1, 100] }, { name: "deviations", value: 0.05, required: true, type: "Number", range: [0, 10] }, { name: "shift", value: 0, required: true, type: "Integer", range: [-30, 30] }, { name: "method", value: "sma", required: true, type: "String", range: null }], [{ name: "Close", index: 0 }], [{ name: "ma", visible: true, renderType: "Line", color: "steelblue" }, { name: "upper", visible: true, renderType: "Dasharray", color: "steelblue" }, { name: "lower", visible: true, renderType: "Dasharray", color: "steelblue" }], "CHART_WINDOW") ================================================ FILE: Indicators/Built-in/fractals.js ================================================ registerIndicator( "fractals", "Fractals(v1.02)", function (context) { var dataInputHigh = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataOutputUp = getDataOutput(context, "fractalsUp") var dataOutputDown = getDataOutput(context, "fractalsDown") var calculatedLength = getCalculatedLength(context) var ptr = null if (calculatedLength > 0) { ptr = calculatedLength - 3 } else { for (var i = 0; i < dataInputHigh.length; i++) { dataOutputUp[i] = 0 dataOutputDown[i] = 0 } ptr = 2 } var bHFound = false var bLFound = false var highest = null var lowest = null while (ptr < dataInputHigh.length - 2) { bHFound = false highest = dataInputHigh[ptr] if (highest > dataInputHigh[ptr - 1] && highest > dataInputHigh[ptr - 2] && highest > dataInputHigh[ptr + 1] && highest > dataInputHigh[ptr + 2]) { bHFound = true dataOutputUp[ptr] = highest } bLFound = false lowest = dataInputLow[ptr] if (lowest < dataInputLow[ptr - 1] && lowest < dataInputLow[ptr - 2] && lowest < dataInputLow[ptr + 1] && lowest < dataInputLow[ptr + 2]) { bLFound = true dataOutputDown[ptr] = lowest } ptr++ } if (!bHFound) { dataOutputUp[dataInputHigh.length - 3] = 0 } if (!bLFound) { dataOutputDown[dataInputLow.length - 3] = 0 } },[], [{ name: DATA_NAME.HIGH, index: 0 },{ name: DATA_NAME.LOW, index: 1 }], [{ name: "fractalsUp", visible: true, renderType: RENDER_TYPE.ROUND, color: "green" },{ name: "fractalsDown", visible: true, renderType: RENDER_TYPE.ROUND, color: "red" }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Built-in/heikin-ashi.js ================================================ registerIndicator("heikin-ashi", "Heikin-Ashi(v1.01)", function (context) { var dataInputO = getDataInput(context, 0) var dataInputH = getDataInput(context, 1) var dataInputL = getDataInput(context, 2) var dataInputC = getDataInput(context, 3) var dataOutputO = getDataOutput(context, "ha_open") var dataOutputH = getDataOutput(context, "ha_high") var dataOutputL = getDataOutput(context, "ha_low") var dataOutputC = getDataOutput(context, "ha_close") var calculatedLength = getCalculatedLength(context) var i = calculatedLength if (i > 0) { i-- } else { dataOutputC[i] = (dataInputO[i] + dataInputH[i] + dataInputL[i] + dataInputC[i]) / 4 dataOutputO[i] = (dataInputO[i] + dataInputC[i]) / 2 dataOutputH[i] = Math.max(dataInputH[i], dataOutputO[i], dataOutputC[i]) dataOutputL[i] = Math.max(dataInputL[i], dataOutputO[i], dataOutputC[i]) i = 1 } while (i < dataInputC.length) { dataOutputC[i] = (dataInputO[i] + dataInputH[i] + dataInputL[i] + dataInputC[i]) / 4 dataOutputO[i] = (dataOutputO[i - 1] + dataOutputC[i - 1]) / 2 dataOutputH[i] = Math.max(dataInputH[i], dataOutputO[i], dataOutputC[i]) dataOutputL[i] = Math.max(dataInputL[i], dataOutputO[i], dataOutputC[i]) i++ } },[{ name: "colorLong", value: "green", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "colorShort", value: "red", required: true, type: PARAMETER_TYPE.STRING, range: null }], [{ name: DATA_NAME.OPEN, index: 0 }, { name: DATA_NAME.HIGH, index: 1 }, { name: DATA_NAME.LOW, index: 2 }, { name: DATA_NAME.CLOSE, index: 3 }], [{ name: "ha_open", visible: false }, { name: "ha_high", visible: false }, { name: "ha_low", visible: false }, { name: "ha_close", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { // Init() var colorLong = getIndiParameter(context, "colorLong") var colorShort = getIndiParameter(context, "colorShort") var chartHandle = getChartHandleByContext(context) context.heikinAshi = { colorLong: colorLong, colorShort: colorShort, canvas: getSvgCanvas(chartHandle) } }, function (context) { // Deinit() var chartHandle = getChartHandleByContext(context) var canvas = context.heikinAshi.canvas canvas.selectAll(".haHL").select(function() { return this.parentNode; }).select(function() { return this.parentNode; }).each(function (d, i) { if (i == 0) { d3.select(this).selectAll(".cc_k_c_oc").attr("opacity", 1) d3.select(this).selectAll(".cc_k_c_hl").attr("opacity", 1) } }) canvas.selectAll(".haHL").data([]).exit().remove() canvas.selectAll(".haOC").data([]).exit().remove() }, function (context) { // Render() var dataOutputO = getDataOutput(context, "ha_open") var dataOutputH = getDataOutput(context, "ha_high") var dataOutputL = getDataOutput(context, "ha_low") var dataOutputC = getDataOutput(context, "ha_close") var barNum = getBarNum(context) var cursor = getCursor(context) var width = getCanvasWidth(context) var height = getCanvasHeight(context) var xScale = getXScale(context) var yScale = getYScale(context) var ha = [] var cursor2 = Math.min(cursor + barNum, dataOutputC.length) for (var i = cursor; i < cursor2; i++) { ha.push({ o: dataOutputO[i], h: dataOutputH[i], l: dataOutputL[i], c: dataOutputC[i] }) } var colorLong = context.heikinAshi.colorLong var colorShort = context.heikinAshi.colorShort var canvas = context.heikinAshi.canvas var haHL = canvas.selectAll(".haHL").data(ha) haHL.attr("x1", function (d, i) { return xScale(i) }) .attr("x2", function (d, i) { return xScale(i) }) .attr("y1", function (d) { return yScale(d.h) }) .attr("y2", function (d) { return yScale(d.l) }) .attr("stroke", function (d) { return d.o > d.c ? colorShort : colorLong }) haHL.enter().append("line") .attr("class", "haHL") .attr("x1", function (d, i) { return xScale(i) }) .attr("x2", function (d, i) { return xScale(i) }) .attr("y1", function (d) { return yScale(d.h) }) .attr("y2", function (d) { return yScale(d.l) }) .attr("stroke", function (d) { return d.o > d.c ? colorShort : colorLong }) haHL.exit().remove() var barWidth = Math.floor(0.8 * width / barNum) var halfWidth = barWidth / 2 var haOC = canvas.selectAll(".haOC").data(ha) haOC.attr("x", function (d, i) { return xScale(i) - halfWidth }) .attr("y", function (d) { return yScale(Math.max(d.o, d.c)) }) .attr("width", barWidth) .attr("height", function (d) { return d.o == d.c ? 1 : (yScale(Math.min(d.o, d.c)) - yScale(Math.max(d.o, d.c))) }) .attr("fill", function (d) { if (d.o == d.c) return "black" else return d.o > d.c ? colorShort : colorLong }) .attr("stroke", function (d) { if (d.o == d.c) return "black" else return d.o > d.c ? colorShort : colorLong }) haOC.enter().append("rect") .attr("class", "haOC") .attr("x", function (d, i) { return xScale(i) - halfWidth }) .attr("y", function (d) { return yScale(Math.max(d.o, d.c)) }) .attr("width", barWidth) .attr("height", function (d) { return d.o == d.c ? 1 : (yScale(Math.min(d.o, d.c)) - yScale(Math.max(d.o, d.c))) }) .attr("fill", function (d) { if (d.o == d.c) return "black" else return d.o > d.c ? colorShort : colorLong }) .attr("stroke", function (d) { if (d.o == d.c) return "black" else return d.o > d.c ? colorShort : colorLong }) .attr("strokeWidth", 2) haOC.exit().remove() canvas.selectAll(".haHL").select(function() { return this.parentNode; }).select(function() { return this.parentNode; }).each(function (d, i) { if (i == 0) { d3.select(this).selectAll(".cc_k_c_oc").attr("opacity", 0) d3.select(this).selectAll(".cc_k_c_hl").attr("opacity", 0) } }) }) ================================================ FILE: Indicators/Built-in/ichimoku.js ================================================ registerIndicator( "ichimoku", "Ichimoku Kinko Hyo(v1.0)", function (context) { var dataInputHigh = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataInputClose = getDataInput(context, 2) var dataOutputTenkan = getDataOutput(context, "tenkan") var dataOutputKijun = getDataOutput(context, "kijun") var dataOutputChikou = getDataOutput(context, "chikou") var dataOutputSpanA = getDataOutput(context, "spana") var dataOutputSpanB = getDataOutput(context, "spanb") var tenkan = getIndiParameter(context, "tenkan") var kijun = getIndiParameter(context, "kijun") var senkou = getIndiParameter(context, "senkou") var spanA; if (kijun < tenkan) { spanA = tenkan; }else{ spanA = kijun; } var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength var maxParam = Math.max(tenkan, kijun, spanA, senkou) if (ptr > 0) { ptr-- } else { ptr = maxParam - 1 for (var i = 1; i < maxParam; i++) { dataOutputTenkan[ptr - i] = 0 dataOutputKijun[ptr - i] = 0 dataOutputChikou[ptr - i] = 0 dataOutputSpanA[ptr - i] = 0 dataOutputSpanB[ptr - i] = 0 } } var ptr2, tmp, highest, lowest while (ptr < dataInputHigh.length) { tmp = null highest = -Number.MAX_VALUE lowest = Number.MAX_VALUE ptr2 = ptr - tenkan + 1 while (ptr2 <= ptr) { tmp = dataInputHigh[ptr2] if (highest < tmp) { highest = tmp } tmp = dataInputLow[ptr2] if (lowest > tmp) { lowest = tmp } ptr2++ } dataOutputTenkan[ptr] = (highest + lowest) / 2 tmp = null highest = -Number.MAX_VALUE lowest = Number.MAX_VALUE ptr2 = ptr - kijun + 1 while (ptr2 <= ptr) { tmp = dataInputHigh[ptr2] if (highest < tmp) { highest = tmp } tmp = dataInputLow[ptr2] if (lowest > tmp) { lowest = tmp } ptr2++ } dataOutputKijun[ptr] = (highest + lowest) / 2 dataOutputSpanA[ptr] = (dataOutputTenkan[ptr] + dataOutputKijun[ptr]) / 2 tmp = null highest = -Number.MAX_VALUE lowest = Number.MAX_VALUE ptr2 = ptr - senkou + 1 while (ptr2 <= ptr) { tmp = dataInputHigh[ptr2] if (highest < tmp) { highest = tmp } tmp = dataInputLow[ptr2] if (lowest > tmp) { lowest = tmp } ptr2++ } dataOutputSpanB[ptr] = (highest + lowest) / 2 dataOutputChikou[ptr] = dataInputClose[ptr] ptr++ } if (calculatedLength == 0) { setIndiShift(context, "chikou", -kijun) setIndiShift(context, "spana", kijun) setIndiShift(context, "spanb", kijun) } }, [{ name: "tenkan", value: 9, required: true, type: "Integer", range: [1, 100] }, { name: "kijun", value: 26, required: true, type: "Integer", range: [1, 100] }, { name: "senkou", value: 52, required: true, type: "Integer", range: [1, 100] }], [{ name: "High", index: 0 }, { name: "Low", index: 1 }, { name: "Close", index: 2 }], [{ name: "tenkan", visible: true, renderType: "Line", color: "#DE5029" }, { name: "kijun", visible: true, renderType: "Line", color: "steelblue" }, { name: "chikou", visible: true, renderType: "Dasharray", color: "#4EC2B4" }, { name: "spana", visible: true, renderType: "Round", color: "steelblue" }, { name: "spanb", visible: true, renderType: "Round", color: "#CCCCCC" }], "CHART_WINDOW") ================================================ FILE: Indicators/Built-in/lwma.js ================================================ registerIndicator( "lwma", "Linear weighted moving average(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "lwma") var period = getIndiParameter(context, "period") var shift = getIndiParameter(context, "shift") var calculatedLength = getCalculatedLength(context) lwma(dataInput, dataOutput, calculatedLength, period) if (shift != null && calculatedLength == 0) { setIndiShift(context, "lwma", shift) } },[{ name: "period", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "shift", value: 0, required: false, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "lwma", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Built-in/macd.js ================================================ registerIndicator( "macd", "MACD(v1.01)", function (context) { var dataInput = getDataInput(context, 0) var dataFEMA = getDataOutput(context, "fastEMA") var dataSEMA = getDataOutput(context, "slowEMA") var dataOutputMain = getDataOutput(context, "main") var dataOutputSignal = getDataOutput(context, "signal") var fEMA = getIndiParameter(context, "fastEMA") var sEMA = getIndiParameter(context, "slowEMA") var sgnlSMA = getIndiParameter(context, "signalSMA") var calculatedLength = getCalculatedLength(context) var i = calculatedLength if (i == 0) { dataFEMA[0] = dataInput[0] dataSEMA[0] = dataInput[0] dataOutputMain[0] = 0 i++ } else if (i == 1) { } else { i-- } ema(dataInput, dataFEMA, calculatedLength, fEMA) ema(dataInput, dataSEMA, calculatedLength, sEMA) while (i < dataInput.length) { dataOutputMain[i] = dataFEMA[i] - dataSEMA[i] i++ } sma(dataOutputMain, dataOutputSignal, calculatedLength, sgnlSMA) },[{ name: "fastEMA", value: 12, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "slowEMA", value: 26, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "signalSMA", value: 9, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "fastEMA", visible: false },{ name: "slowEMA", visible: false },{ name: "main", visible: true, renderType: RENDER_TYPE.HISTOGRAM, color: "#4EC2B4" },{ name: "signal", visible: true, renderType: RENDER_TYPE.LINE, color: "#CCCCCC" }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/mfi.js ================================================ registerIndicator("mfi", "Market Facilitation Index(v1.01)", function (context) { var dataInputHigh = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataInputVol = getDataInput(context, 2) var dataOutput = getDataOutput(context, "mfi") var dataOutputH = getDataOutput(context, "highestTmp") var dataOutputL = getDataOutput(context, "lowestTmp") var dataOutputV = getDataOutput(context, "volSumTmp") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) getHighestOnArray(dataInputHigh, dataOutputH, calculatedLength, period) getLowestOnArray(dataInputLow, dataOutputL, calculatedLength, period) sumOnArray(dataInputVol, dataOutputV, calculatedLength, period) var i = calculatedLength if (i != 0) { i-- } while (i < dataInputVol.length) { if (dataOutputV[i] == 0) { dataOutput[i] = 0 } else { dataOutput[i] = (dataOutputH[i] - dataOutputL[i]) / dataOutputV[i] } i++ } },[{ name: "period", value: 1, required: false, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }], [{ name: DATA_NAME.HIGH, index: 0 },{ name: DATA_NAME.LOW, index: 1 },{ name: DATA_NAME.VOLUME, index: 2 }], [{ name: "mfi", visible: true, renderType: RENDER_TYPE.HISTOGRAM, color: "steelblue" },{ name: "highestTmp", visible: false },{ name: "lowestTmp", visible: false },{ name: "volSumTmp", visible: false }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/momentum.js ================================================ registerIndicator( "momentum", "Momentum(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "momentum") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period - 1 for (var i = 0; i < period - 1; i++) { dataOutput[i] = 0 } } while (ptr < dataInput.length) { dataOutput[ptr] = dataInput[ptr] * 100 / dataInput[ptr - period] ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }], [{ name: "Close", index: 0 }], [{ name: "momentum", visible: true, renderType: "Line", color: "steelblue" }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/rsi.js ================================================ registerIndicator( "rsi", "Relative strength index(v1.01)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "rsi") var dataOutputHL = getDataOutput(context, "rsiHighLevel") var dataOutputLL = getDataOutput(context, "rsiLowLevel") var gainTmp = getDataOutput(context, "gainTmp") var lossTmp = getDataOutput(context, "lossTmp") var period = getIndiParameter(context, "period") var highLevel = getIndiParameter(context, "highLevel") var lowLevel = getIndiParameter(context, "lowLevel") var calculatedLength = getCalculatedLength(context) var ptr = null var ptr2 = null var diff = null var gain = null var loss = null var gainSum = 0 var lossSum = 0 if (calculatedLength > 0) { ptr = calculatedLength - 1 ptr2 = calculatedLength - period } else { for (var i = 0; i < period; i++) { dataOutput[i] = 0 dataOutputHL[i] = highLevel dataOutputLL[i] = lowLevel } ptr = period ptr2 = 1 while (ptr2 <= ptr) { diff = dataInput[ptr2] - dataInput[ptr2 - 1] if (0 < diff) { gainSum += diff } else { lossSum -= diff } ptr2++ } gain = gainSum / period loss = lossSum / period if (0 == (gain + loss)) { dataOutput[ptr] = 0 } else { dataOutput[ptr] = 100 * gain / (gain + loss) } dataOutputHL[ptr] = highLevel dataOutputLL[ptr] = lowLevel gainTmp[ptr] = gain lossTmp[ptr] = loss ptr++ } while (ptr < dataInput.length) { gain = gainTmp[ptr - 1] * (period - 1) loss = lossTmp[ptr - 1] * (period - 1) diff = dataInput[ptr] - dataInput[ptr - 1] if (0 < diff) { gain += diff } else { loss -= diff } gain = gain / period loss = loss / period if (0 == (gain + loss)) { dataOutput[ptr] = 0 } else { dataOutput[ptr] = 100 * gain / (gain + loss) } dataOutputHL[ptr] = highLevel dataOutputLL[ptr] = lowLevel gainTmp[ptr] = gain lossTmp[ptr] = loss ptr++ } },[{ name: "period", value: 14, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "highLevel", value: 70, required: false, type: PARAMETER_TYPE.NUMBER, range: [1, 100] },{ name: "lowLevel", value: 30, required: false, type: PARAMETER_TYPE.NUMBER, range: [1, 100] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "rsi", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" },{ name: "rsiHighLevel", visible: true, renderType: RENDER_TYPE.DASHARRAY, color: "#AAAAAA" },{ name: "rsiLowLevel", visible: true, renderType: RENDER_TYPE.DASHARRAY, color: "#AAAAAA" },{ name: "gainTmp", visible: false },{ name: "lossTmp", visible: false }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/rvi.js ================================================ registerIndicator( "rvi", "Relative Vigor Index(v1.0)", function (context) { var dataInputOpen = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataInputLow = getDataInput(context, 2) var dataInputClose = getDataInput(context, 3) var dataOutputMain = getDataOutput(context, "main") var dataOutputSignal = getDataOutput(context, "signal") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period + 2 for (var i = 0; i < period + 2; i++) { dataOutputMain[i] = 0 dataOutputSignal[i] = 0 } } var upTmp, downTmp, tmp, dTmp while (ptr < dataInputOpen.length) { tmp = 0 dTmp = 0 for (var i = ptr; i > ptr - period; i--) { upTmp = ((dataInputClose[i] - dataInputOpen[i]) + 2 * (dataInputClose[i - 1] - dataInputOpen[i - 1]) + 2 * (dataInputClose[i - 2] - dataInputOpen[i - 2]) + (dataInputClose[i - 3] - dataInputOpen[i - 3])) / 6 downTmp = ((dataInputHigh[i] - dataInputLow[i]) + 2 * (dataInputHigh[i - 1] - dataInputLow[i - 1]) + 2 * (dataInputHigh[i - 2] - dataInputLow[i - 2]) + (dataInputHigh[i - 3] - dataInputLow[i - 3])) / 6 tmp += upTmp dTmp += downTmp } if (0 == dTmp) { dataOutputMain[ptr] = tmp } else { dataOutputMain[ptr] = tmp / dTmp } ptr++ } ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period + 2 } while (ptr < dataInputOpen.length) { dataOutputSignal[ptr] = (dataOutputMain[ptr] + 2 * dataOutputMain[ptr - 1] + 2 * dataOutputMain[ptr - 2] + dataOutputMain[ptr - 3]) / 6 ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }], [{ name: "Open", index: 0 }, { name: "High", index: 1 }, { name: "Low", index: 2 }, { name: "Close", index: 3 }], [{ name: "main", visible: true, renderType: "Line", color: "#6CBA81" }, { name: "signal", visible: true, renderType: "Line", color: "#ECAE93" }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/sar.js ================================================ registerIndicator( "sar", "Parabolic SAR(v1.01)", function (context) { var dataInputHigh = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataOutput = getDataOutput(context, "sar") var dataOutputIsLong = getDataOutput(context, "isLong") var dataOutputAf = getDataOutput(context, "af") var dataOutputEp = getDataOutput(context, "ep") var acceleration = getIndiParameter(context, "acceleration") var afMax = getIndiParameter(context, "afMax") var calculatedLength = getCalculatedLength(context) var i = calculatedLength var prevH = null var prevL = null var currH = null var currL = null var sar = null var isLong = null var af = acceleration var ep = null if (i > 0) { i -= 2 prevH = dataInputHigh[i - 1] prevL = dataInputLow[i - 1] isLong = dataOutputIsLong[i] sar = dataOutput[i] af = dataOutputAf[i] ep = dataOutputEp[i] } else { dataOutput[i] = 0 dataOutputIsLong[i] = true dataOutputAf[i] = af dataOutputEp[i] = 0 i = 1 prevH = dataInputHigh[i - 1] prevL = dataInputLow[i - 1] isLong = true sar = prevL ep = prevH } while (i < dataInputHigh.length) { currH = dataInputHigh[i] currL = dataInputLow[i] if (isLong) { if (currL <= sar) { isLong = false sar = Math.max(ep, currH, prevH) dataOutput[i] = sar af = acceleration ep = currL sar = sar + af * (ep - sar) sar = Math.max(sar, currH, prevH) } else { dataOutput[i] = sar if (currH > ep) { ep = currH if (af - dataOutputAf[i - 1] <= 0) { af += acceleration } if (af > afMax) { af = afMax } } sar = sar + af * (ep - sar) sar = Math.min(sar, currL, prevL) } } else { if (currH >= sar) { isLong = true sar = Math.min(ep, currL, prevL) dataOutput[i] = sar af = acceleration ep = currH sar = sar + af * (ep - sar) sar = Math.min(sar, currL, prevL) } else { dataOutput[i] = sar if (currL < ep) { ep = currL if (af - dataOutputAf[i - 1] <= 0) { af += acceleration } if (af > afMax) { af = afMax } } sar = sar + af * (ep - sar) sar = Math.max(sar, currH, prevH) } } dataOutputIsLong[i] = isLong dataOutputAf[i] = af dataOutputEp[i] = ep i++ prevH = currH prevL = currL } }, [{ name: "acceleration", value: 0.02, required: true, type: "Number", range: [0.01, 0.1] }, { name: "afMax", value: 0.2, required: true, type: "Number", range: [0.1, 1] }], [{ name: "High", index: 0 }, { name: "Low", index: 1 }], [{ name: "sar", visible: true, renderType: "Round", color: "steelblue" }, { name: "isLong", visible: false, renderType: null, color: null }, { name: "af", visible: false, renderType: null, color: null }, { name: "ep", visible: false, renderType: null, color: null }], "CHART_WINDOW") ================================================ FILE: Indicators/Built-in/sma.js ================================================ registerIndicator( "sma", "Simple moving average(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "sma") var period = getIndiParameter(context, "period") var shift = getIndiParameter(context, "shift") var calculatedLength = getCalculatedLength(context) sma(dataInput, dataOutput, calculatedLength, period) if (shift != null && calculatedLength == 0) { setIndiShift(context, "sma", shift) } },[{ name: "period", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "shift", value: 0, required: false, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "sma", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Built-in/smma.js ================================================ registerIndicator( "smma", "Smoothed moving average(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "smma") var period = getIndiParameter(context, "period") var shift = getIndiParameter(context, "shift") var calculatedLength = getCalculatedLength(context) smma(dataInput, dataOutput, calculatedLength, period) if (shift != null && calculatedLength == 0) { setIndiShift(context, "smma", shift) } },[{ name: "period", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "shift", value: 0, required: false, type: PARAMETER_TYPE.INTEGER, range: [-30, 30] }], [{ name: DATA_NAME.CLOSE, index: 0 }], [{ name: "smma", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Built-in/stochastic.js ================================================ registerIndicator( "stochastic", "Stochastic oscillator(v1.01)", function (context) { var dataInputClose = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataInputLow = getDataInput(context, 2) var highestTmp = getDataOutput(context, "highestTmp") var lowestTmp = getDataOutput(context, "lowestTmp") var dataOutputMain = getDataOutput(context, "main") var dataOutputSignal = getDataOutput(context, "signal") var kP = getIndiParameter(context, "KPeriod") var slowing = getIndiParameter(context, "slowing") var dP = getIndiParameter(context, "DPeriod") var method = getIndiParameter(context, "method") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength var maxParam = Math.max(kP + slowing - 1, dP) if (ptr > 0) { ptr-- } else { ptr = maxParam - 1 for (var i = 1; i < maxParam; i++) { dataOutputMain[ptr - i] = 0 highestTmp[ptr - i] = 0 lowestTmp[ptr - i] = 0 } } while (ptr < dataInputClose.length) { var tmp = null var highest = Number.MIN_VALUE var lowest = Number.MAX_VALUE for (var ptr2 = (ptr - kP + 1); ptr2 <= ptr; ptr2++){ tmp = dataInputHigh[ptr2] if (highest < tmp) { highest = tmp } tmp = dataInputLow[ptr2] if (lowest > tmp) { lowest = tmp } } highestTmp[ptr] = highest lowestTmp[ptr] = lowest ptr++ } ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = maxParam - 1 } while (ptr < dataInputClose.length) { var highestSum = 0 var lowestSum = 0 for (var ptr2 = ptr - slowing + 1; ptr2 <= ptr; ptr2++) { highestSum += highestTmp[ptr2] - lowestTmp[ptr2] lowestSum += dataInputClose[ptr2] - lowestTmp[ptr2] } if (0 == highestSum) { dataOutputMain[ptr] = 100 }else{ dataOutputMain[ptr] = lowestSum / highestSum * 100 } ptr++ } if ("sma" == method) { sma(dataOutputMain, dataOutputSignal, calculatedLength, dP) } else if ("ema" == method) { ema(dataOutputMain, dataOutputSignal, calculatedLength, dP) } else if ("smma" == method) { smma(dataOutputMain, dataOutputSignal, calculatedLength, dP) } else { lwma(dataOutputMain, dataOutputSignal, calculatedLength, dP) } },[{ name: "KPeriod", value: 5, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "slowing", value: 3, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "DPeriod", value: 3, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] },{ name: "method", value: "sma", required: true, type: PARAMETER_TYPE.STRING }], [{ name: DATA_NAME.CLOSE, index: 0 },{ name: DATA_NAME.HIGH, index: 1 },{ name: DATA_NAME.LOW, index: 2 }], [{ name: "highestTmp", visible: false },{ name: "lowestTmp", visible: false },{ name: "main", visible: true, renderType: RENDER_TYPE.LINE, color: "#DE5029" },{ name: "signal", visible: true, renderType: RENDER_TYPE.DASHARRAY, color: "#4EC2B4" }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/volume.js ================================================ registerIndicator("volume", "Volume of OHLC(v1.0)", function (context) { var dataInput = getDataInput(context, 0) var dataOutput = getDataOutput(context, "volume") var calculatedLength = getCalculatedLength(context) var i = calculatedLength if (i != 0) { i-- } while (i < dataInput.length) { dataOutput[i] = dataInput[i] i++ } },[], [{ name: DATA_NAME.VOLUME, index: 0 }], [{ name: "volume", visible: true, renderType: RENDER_TYPE.HISTOGRAM, color: "steelblue" }], WHERE_TO_RENDER.SEPARATE_WINDOW) ================================================ FILE: Indicators/Built-in/wpr.js ================================================ registerIndicator( "wpr", "Williams' Percent Range(v1.0)", function (context) { var dataInputClose = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataInputLow = getDataInput(context, 2) var dataOutput = getDataOutput(context, "wpr") var dataOutputHL = getDataOutput(context, "wprHighLevel") var dataOutputLL = getDataOutput(context, "wprLowLevel") var highLevel = getIndiParameter(context, "highLevel") var lowLevel = getIndiParameter(context, "lowLevel") var period = getIndiParameter(context, "period") var calculatedLength = getCalculatedLength(context) var ptr = calculatedLength if (ptr > 0) { ptr-- } else { ptr = period - 1 for (var i = 0; i < period - 1; i++) { dataOutput[i] = 0 dataOutputHL[i] = highLevel dataOutputLL[i] = lowLevel } } while (ptr < dataInputClose.length) { var maxArr = [] for (var i = 0; i < period; i++) { maxArr.push(dataInputHigh[ptr - i]) } var highest = Math.max.apply(null, maxArr) var minArr = [] for (var i = 0; i < period; i++) { minArr.push(dataInputLow[ptr - i]) } var lowest = Math.min.apply(null, minArr) if (0 == highest - lowest) { dataOutput[ptr] = 0 } else { dataOutput[ptr] = -100 * (highest - dataInputClose[ptr]) / (highest - lowest) } dataOutputHL[ptr] = highLevel dataOutputLL[ptr] = lowLevel ptr++ } }, [{ name: "period", value: 14, required: true, type: "Integer", range: [1, 100] }, { name: "highLevel", value: -20, required: false, type: "Number", range: [-100, 0] }, { name: "lowLevel", value: -80, required: false, type: "Number", range: [-100, 0] }], [{ name: "Close", index: 0 }, { name: "High", index: 1 }, { name: "Low", index: 2 }], [{ name: "wpr", visible: true, renderType: "Line", color: "steelblue" }, { name: "wprHighLevel", visible: true, renderType: "Dasharray", color: "#AAAAAA" }, { name: "wprLowLevel", visible: true, renderType: "Dasharray", color: "#AAAAAA" }], "SEPARATE_WINDOW") ================================================ FILE: Indicators/Built-in/zigzag.js ================================================ registerIndicator("zigzag", "ZigZag based on SAR(v1.03)", function (context) { var dataInputHigh = getDataInput(context, 0) var dataInputLow = getDataInput(context, 1) var dataOutputZZLine = getDataOutput(context, "zigzagLine") var dataOutputZZ = getDataOutput(context, "zigzag") var dataOutput = getDataOutput(context, "sar") var dataOutputIsLong = getDataOutput(context, "isLong") var dataOutputAf = getDataOutput(context, "af") var dataOutputEp = getDataOutput(context, "ep") var acceleration = getIndiParameter(context, "acceleration") var afMax = getIndiParameter(context, "afMax") var arrLen = dataInputHigh.length var calculatedLength = getCalculatedLength(context) var i = calculatedLength var prevH = null var prevL = null var currH = null var currL = null var sar = null var isLong = null var af = acceleration var ep = null if (i > 0) { i -= 2 prevH = dataInputHigh[i - 1] prevL = dataInputLow[i - 1] isLong = dataOutputIsLong[i] sar = dataOutput[i] af = dataOutputAf[i] ep = dataOutputEp[i] } else { dataOutput[i] = 0 dataOutputIsLong[i] = true dataOutputAf[i] = af dataOutputEp[i] = 0 i = 1 prevH = dataInputHigh[i - 1] prevL = dataInputLow[i - 1] isLong = true sar = prevL ep = prevH } while (i < arrLen) { currH = dataInputHigh[i] currL = dataInputLow[i] if (isLong) { if (currL <= sar) { isLong = false sar = Math.max(ep, currH, prevH) dataOutput[i] = sar af = acceleration ep = currL sar = sar + af * (ep - sar) sar = Math.max(sar, currH, prevH) } else { dataOutput[i] = sar if (currH > ep) { ep = currH if (af - dataOutputAf[i - 1] <= 0) { af += acceleration } if (af > afMax) { af = afMax } } sar = sar + af * (ep - sar) sar = Math.min(sar, currL, prevL) } } else { if (currH >= sar) { isLong = true sar = Math.min(ep, currL, prevL) dataOutput[i] = sar af = acceleration ep = currH sar = sar + af * (ep - sar) sar = Math.min(sar, currL, prevL) } else { dataOutput[i] = sar if (currL < ep) { ep = currL if (af - dataOutputAf[i - 1] <= 0) { af += acceleration } if (af > afMax) { af = afMax } } sar = sar + af * (ep - sar) sar = Math.max(sar, currH, prevH) } } dataOutputIsLong[i] = isLong dataOutputAf[i] = af dataOutputEp[i] = ep i++ prevH = currH prevL = currL } var zigzag = [] var latestZZ = null var latestZZIdx = -1 if (calculatedLength > 0) { dataOutputZZ[calculatedLength - 1] = 0 dataOutputZZLine[calculatedLength - 1] = 0 for (i = arrLen - 1; i >= 0; i--) { if (dataOutputZZ[i] != 0) { latestZZ = { value: dataOutputZZ[i], index: i } latestZZIdx = i break } } } else { dataOutputZZ[0] = (dataInputHigh[0] + dataInputLow[0]) / 2 dataOutputZZLine[0] = dataOutputZZ[0] for (i = 1; i < arrLen; i++) { dataOutputZZ[i] = 0 } latestZZ = { value: dataOutputZZ[0], index: 0 } latestZZIdx = 0 } i = arrLen - 1 var foundIdx = -1 var lowestZZ = Number.MAX_VALUE var highestZZ = -Number.MAX_VALUE var bNextLong = dataOutputIsLong[i] while (i >= 0 && i >= latestZZIdx) { if (dataOutputIsLong[i]) { if (bNextLong && i != 0) { if (dataInputHigh[i] > highestZZ) { foundIdx = i highestZZ = dataInputHigh[i] } } else { if (foundIdx != -1) { zigzag.splice(0, 0, { value: lowestZZ, index: foundIdx }) } foundIdx = i lowestZZ = Number.MAX_VALUE highestZZ = dataInputHigh[i] bNextLong = true } } else { if (!bNextLong && i != 0) { if (dataInputLow[i] < lowestZZ) { foundIdx = i lowestZZ = dataInputLow[i] } } else { if (foundIdx != -1) { zigzag.splice(0, 0, { value: highestZZ, index: foundIdx }) } foundIdx = i lowestZZ = dataInputLow[i] highestZZ = -Number.MAX_VALUE bNextLong = false } } i-- } zigzag.splice(0, 0, latestZZ) var zzLen = zigzag.length > 1 ? (zigzag.length - 1) : 1 for (i = 0; i < zzLen; i++) { dataOutputZZ[zigzag[i].index] = zigzag[i].value } if (arrLen - 1 > zigzag[zigzag.length - 1].index) { zigzag.push({ value: (dataInputHigh[arrLen - 1] + dataInputLow[arrLen - 1]) / 2, index: arrLen - 1 }) } for (i = 1; i < zigzag.length; i++) { var step = (zigzag[i].value - zigzag[i - 1].value) / (zigzag[i].index - zigzag[i - 1].index) var nextIdx = zigzag[i].index var startValue = zigzag[i - 1].value var startIdx = zigzag[i - 1].index for (var j = zigzag[i - 1].index; j < nextIdx; j++) { dataOutputZZLine[j] = startValue + step * (j - startIdx) } } dataOutputZZLine[arrLen - 1] = zigzag[zigzag.length - 1].value },[{ name: "acceleration", value: 0.01, required: true, type: PARAMETER_TYPE.NUMBER, range: [0.001, 0.1] },{ name: "afMax", value: 0.05, required: true, type: PARAMETER_TYPE.NUMBER, range: [0.01, 1] }], [{ name: DATA_NAME.HIGH, index: 0 },{ name: DATA_NAME.LOW, index: 1 }], [{ name: "zigzagLine", visible: true, renderType: RENDER_TYPE.LINE, color: "orange" },{ name: "zigzag", visible: false },{ name: "sar", visible: false },{ name: "isLong", visible: false },{ name: "af", visible: false },{ name: "ep", visible: false }], WHERE_TO_RENDER.CHART_WINDOW) ================================================ FILE: Indicators/Oldie/README.md ================================================ This folder contains deprecated programs. ================================================ FILE: Indicators/Oldie/README.txt ================================================ This folder contains deprecated programs. ================================================ FILE: Indicators/Oldie/fintechee_oanda_loader.js ================================================ registerIndicator("fintechee_oanda_loader", "A plugin to load Oanda's streaming quotes and transactions(v1.11)", function (context) { // Deprecated. A new version has been released. Please refer to EA/Plugin-for-Oanda. // Disclaimer: we are not affiliated with the data providers or the API providers. }, [{ name: "oandaDemo", value: true, required: true, type: PARAMETER_TYPE.BOOLEAN, range: null }, { name: "oandaAccountId", value: "XXX-XXX-XXXXXXXX-XXX", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "oandaTradeKey", value: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", required: true, type: PARAMETER_TYPE.STRING, range: null }], [{ name: DATA_NAME.TIME, index: 0 }], [{ name: "oanda", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { // Init setDefaultIndicator("fintechee_oanda_loader", true) window.oandaDemo = getIndiParameter(context, "oandaDemo") window.oandaAccountId = getIndiParameter(context, "oandaAccountId") window.oandaTradeKey = getIndiParameter(context, "oandaTradeKey") if (typeof window.oandaChangeCallback == "undefined") { window.oandaChangeCallback = function (ctx) { var symbolName = getExtraSymbolName(ctx) if (typeof window.oandaApiLoader.currenciesList[symbolName] != "undefined") { var chartId = getChartHandleByContext(ctx) var symbol = window.oandaApiLoader.currenciesList[symbolName].symbolName.split("_") var baseCurrency = symbol[0] var termCurrency = symbol[1] setTakeoverMode(chartId) changeChartMenuItemName(ctx) var timeFrame = getTimeFrame(ctx) window.oandaApiLoader.ticksList.add(baseCurrency) window.oandaApiLoader.ticksList.add(termCurrency) if (typeof window.oandaApiLoader.charts[chartId + ""] == "undefined") { window.oandaApiLoader.charts[chartId + ""] = { chartId: chartId, timeFrame: null, baseCurrency: null, termCurrency: null, baseCurrencyPrice: null, termCurrencyPrice: null } } var chart = window.oandaApiLoader.charts[chartId + ""] chart.timeFrame = timeFrame chart.baseCurrency = baseCurrency chart.termCurrency = termCurrency // Solution A: // Worked as well // You can compare the two solutions. // $.ajax({ // type: "GET", // url: (window.oandaDemo ? "https://api-fxpractice.oanda.com/v3/instruments/" : "https://api-fxtrade.oanda.com/v3/instruments/") + chart.baseCurrency + "_" + chart.termCurrency + "/candles?granularity=" + timeFrame.toUpperCase(), // contentType: "application/json; charset=utf-8", // dataType: "json", // headers: { // "Authorization": "bearer " + window.oandaTradeKey, // "Accept-Datetime-Format": "UNIX" // }, // success: function (res) { // var data = [] // // if (Array.isArray(res.candles)) { // for (var i in res.candles) { // var ohlc = res.candles[i].mid // // data.push({ // time: Math.floor(res.candles[i].time / 1000), // volume: res.candles[i].volume, // open: parseFloat(ohlc.o), // high: parseFloat(ohlc.h), // low: parseFloat(ohlc.l), // close: parseFloat(ohlc.c) // }) // } // // takeoverLoad(chartId, data) // } // } // }) // Solution B: window.oandaDataAPI.instruments.candles(window.oandaAccountId, chart.baseCurrency + "_" + chart.termCurrency, { granularity: timeFrame.toUpperCase() }) .then(function (res) { var data = [] if (Array.isArray(res.candles)) { for (var i in res.candles) { var ohlc = res.candles[i].mid data.push({ time: Math.floor(new Date(res.candles[i].time).getTime() / 1000), volume: res.candles[i].volume, open: parseFloat(ohlc.o), high: parseFloat(ohlc.h), low: parseFloat(ohlc.l), close: parseFloat(ohlc.c) }) } takeoverLoad(chartId, data) } }) } else { var chartId = getChartHandleByContext(ctx) unsetTakeoverMode(chartId) takeoverLoad(chartId, []) delete window.oandaApiLoader.charts[chartId + ""] } } } if (typeof window.oandaRemoveCallback == "undefined") { window.oandaRemoveCallback = function (ctx) { var chartId = getChartHandleByContext(ctx) unsetTakeoverMode(chartId) takeoverLoad(chartId, []) delete window.oandaApiLoader.charts[chartId + ""] } } var chartId = getChartHandleByContext(context) if (typeof window.oandaApiLoader == "undefined") { window.oandaApiLoader = { currenciesList: [], charts: [], ticksList: new Set(), socket: null, sendOrder: function (symbolName, volume) { }, onTick: function (msg) { var ticks = msg.data for (var i in window.oandaApiLoader.charts) { var chart = window.oandaApiLoader.charts[i] var bUpdatable1 = false var bUpdatable2 = false for (var j in ticks) { if (j == chart.baseCurrency) { chart.baseCurrencyPrice = parseFloat(ticks[j]) bUpdatable1 = true } if (j == chart.termCurrency) { chart.termCurrencyPrice = parseFloat(ticks[j]) bUpdatable2 = true } } if (bUpdatable1 && bUpdatable2) { if (chart.baseCurrencyPrice != null && chart.termCurrencyPrice != null && chart.baseCurrencyPrice > 0 && chart.termCurrencyPrice > 0) { var tick = { time: Math.floor(new Date().getTime() / 1000), volume: (typeof ticks.volume != "undefined" ? ticks.volume : 0), price: Math.round(chart.baseCurrencyPrice / chart.termCurrencyPrice * 100000) / 100000 } if (chart.timeFrame == "M1") { takeoverUpdate(chart.chartId, 60, tick) } else if (chart.timeFrame == "M5") { takeoverUpdate(chart.chartId, 300, tick) } else if (chart.timeFrame == "M15") { takeoverUpdate(chart.chartId, 900, tick) } else if (chart.timeFrame == "M30") { takeoverUpdate(chart.chartId, 1800, tick) } else if (chart.timeFrame == "H1") { takeoverUpdate(chart.chartId, 3600, tick) } else if (chart.timeFrame == "H4") { takeoverUpdate(chart.chartId, 14400, tick) } else if (chart.timeFrame == "D") { takeoverUpdate(chart.chartId, 86400, tick) } else { takeoverUpdate(chart.chartId, 86400, tick) } } } } }, onTransaction: function (data) { }, setupSocket: function () { var symbolsList = [] for (var i in window.oandaApiLoader.currenciesList) { symbolsList.push(window.oandaApiLoader.currenciesList[i].symbolName) } if (symbolsList.length > 0) { var script = document.createElement("script") document.body.appendChild(script) script.onload = function () { window.latestTickTime = 0 window.oandaDataAPI.addToken(window.oandaDemo, window.oandaAccountId, window.oandaTradeKey) window.oandaDataCallback = function (res) { window.latestOandaTickTime = new Date().getTime() window.oandaLoaded = true if (typeof res.instrument != "undefined") { var data = { data: [] } var ask = null var bid = null var price = null if (Array.isArray(res.asks)) { ask = parseFloat(res.asks[0].price) price = ask } if (Array.isArray(res.bids)) { bid = parseFloat(res.bids[0].price) if (price != null) { price = (price + bid) / 2 } else { price = bid } } var instrument = res.instrument.split("_") data.data[instrument[0]] = price data.data[instrument[1]] = 1 window.oandaApiLoader.oandaQuotes[instrument[0] + "/" + instrument[1]] = { ask: ask, bid: bid } window.oandaApiLoader.onTick(data) } } window.oandaDataAPI.pricing.stream(window.oandaAccountId, {instruments: symbolsList.join(","), snapshot: false}, window.oandaDataCallback) window.oandaOrderAPI.addToken(window.oandaDemo, window.oandaAccountId, window.oandaTradeKey) window.oandaOrderCallback = function (res) { if (typeof res.type != "undefined") { var data = { } if (res.type == "ORDER_FILL") { } else if (res.type == "HEARTBEAT") { } // {"accountBalance":"6505973.49885","accountID":"","batchID":"777","financing":"0.00000","id":"778","instrument":"EUR_USD","orderID":"777","pl":"0.00000","price":"1.11625","reason":"MARKET_ORDER","time":"2016-09-20T18:18:22.126490230Z","tradeOpened":{"tradeID":"778","units":"100"},"type":"ORDER_FILL","units":"100","userID":1179508} window.oandaApiLoader.onTransaction(data) } } window.oandaOrderAPI.transactions.stream(window.oandaAccountId, window.oandaOrderCallback) } script.onerror = function () { alert("Failed to load required libs. Please refresh this page again.") } script.async = true script.src = "https://www.fintechee.com/js/oanda/oanda_wrapper.js" } }, resetupSocket: function () { var symbolsList = [] for (var i in window.oandaApiLoader.currenciesList) { symbolsList.push(window.oandaApiLoader.currenciesList[i].symbolName) } if (symbolsList.length > 0) { window.oandaDataAPI.pricing.stream(window.oandaAccountId, {instruments: symbolsList.join(","), snapshot: false}, window.oandaDataCallback) window.oandaOrderAPI.transactions.stream(window.oandaAccountId, window.oandaOrderCallback) } } } var chartIds = getLayout(1).concat(getLayout(2)).concat(getLayout(3)).concat(getLayout(4)) for (var i in chartIds) { if (typeof window.oandaApiLoader.charts[chartIds[i] + ""] == "undefined") { window.oandaApiLoader.charts[chartIds[i] + ""] = { chartId: chartIds[i], timeFrame: null, baseCurrency: null, termCurrency: null, baseCurrencyPrice: null, termCurrencyPrice: null } createTakeover(chartIds[i], window.oandaChangeCallback, window.oandaRemoveCallback) } } var currenciesList = [{ symbolName: "AUD_CAD", displayName: "AUD/CAD (Oanda)" }, { symbolName: "AUD_CHF", displayName: "AUD/CHF (Oanda)" }, { symbolName: "AUD_JPY", displayName: "AUD/JPY (Oanda)" }, { symbolName: "AUD_USD", displayName: "AUD/USD (Oanda)" }, { symbolName: "EUR_GBP", displayName: "EUR/GBP (Oanda)" }, { symbolName: "EUR_JPY", displayName: "EUR/JPY (Oanda)" }, { symbolName: "EUR_USD", displayName: "EUR/USD (Oanda)" }, { symbolName: "GBP_AUD", displayName: "GBP/AUD (Oanda)" }, { symbolName: "GBP_CHF", displayName: "GBP/CHF (Oanda)" }, { symbolName: "GBP_JPY", displayName: "GBP/JPY (Oanda)" }, { symbolName: "GBP_USD", displayName: "GBP/USD (Oanda)" }, { symbolName: "USD_CAD", displayName: "USD/CAD (Oanda)" }, { symbolName: "USD_CHF", displayName: "USD/CHF (Oanda)" }, { symbolName: "USD_JPY", displayName: "USD/JPY (Oanda)" }] window.oandaApiLoader.oandaQuotes = [] for (var i in currenciesList) { window.oandaApiLoader.currenciesList[currenciesList[i].displayName] = currenciesList[i] window.oandaApiLoader.oandaQuotes[currenciesList[i].symbolName.replace("_", "/")] = null } addExtraSymbols(currenciesList) window.oandaApiLoader.setupSocket() } else if (typeof window.oandaApiLoader.charts[chartId + ""] == "undefined") { window.oandaApiLoader.charts[chartId + ""] = { chartId: chartId, baseCurrency: null, termCurrency: null, baseCurrencyPrice: null, termCurrencyPrice: null } createTakeover(chartId, window.oandaChangeCallback, window.oandaRemoveCallback) } }, function (context) { // Deinit }, function (context) { // Render }) ================================================ FILE: Indicators/Oldie/line_segment_sample.js ================================================ // This is just an example to implement chart elements by using custom indicator. registerIndicator("line_segment_sample", "A line segment implemented by using custom indicator(v1.0)", function (context) { },[{ name: "color", value: "#AAA", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "strokeWidth", value: 2, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 10] }], [{ name: DATA_NAME.TIME, index: 0 }], [{ name: "line", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { // Init() var color = getIndiParameter(context, "color") var strokeWidth = getIndiParameter(context, "strokeWidth") window.dragObj = d3.drag() .on("start", function (d) { d3.select(this).raise().classed("active", true) }) .on("drag", function (d) { if (d3.select(this).attr("class").includes("lineSegmentStarts")) { window.lineSegment.dragStart(this, d3.event.x, d3.event.y, d) } else if (d3.select(this).attr("class").includes("lineSegmentEnds")) { window.lineSegment.dragEnd(this, d3.event.x, d3.event.y, d) } }) .on("end", function (d) { d3.select(this).classed("active", false) }) window.lineSegment = { data: [], canvas: getSvgCanvas(getIndiHandleByContext(context)), dragStart: function (svgObj, x, y, d) { var startIdx = Math.round(d.xScale.invert(x)) if (startIdx < 0) { startIdx = 0 } else if (startIdx >= d.barNum) { startIdx = d.barNum - 1 } var val = y if (val < 0) { val = 0 } else if (val > d.height) { val = d.height } d.startVal = d.yScale.invert(val) d.startIdx = startIdx + d.cursor d3.select(svgObj).attr("cx", d.xScale(startIdx)).attr("cy", val) d3.select("#lineSegments_" + d.id) .attr("x1", d.xScale(startIdx)).attr("y1", val) }, dragEnd: function (svgObj, x, y, d) { var endIdx = Math.round(d.xScale.invert(x)) if (endIdx < 0) { endIdx = 0 } else if (endIdx >= d.barNum) { endIdx = d.barNum - 1 } var val = y if (val < 0) { val = 0 } else if (val > d.height) { val = d.height } d.endVal = d.yScale.invert(val) d.endIdx = endIdx + d.cursor d3.select(svgObj).attr("cx", d.xScale(endIdx)).attr("cy", val) d3.select("#lineSegments_" + d.id) .attr("x2", d.xScale(endIdx)).attr("y2", val) }, render: function () { var lineSegmentStarts = this.canvas.selectAll(".lineSegmentStarts").data(this.data) lineSegmentStarts .attr("cx", function (d) {return d.xScale(d.startIdx - d.cursor)}) .attr("cy", function (d) {return d.yScale(d.startVal)}) .attr("r", function (d) {return d.radius}) lineSegmentStarts.enter().append("circle") .attr("id", function (d) {return "lineSegmentStarts_" + d.id}) .attr("class", "lineSegmentStarts") .attr("cx", function (d) {return d.xScale(d.startIdx - d.cursor)}) .attr("cy", function (d) {return d.yScale(d.startVal)}) .attr("r", function (d) {return d.radius}) .attr("fill", function (d) {return d.color}) .attr("opacity", 1.0) .attr("stroke", function (d) {return d.color}) .call(window.dragObj) lineSegmentStarts.exit().remove() var lineSegmentEnds = this.canvas.selectAll(".lineSegmentEnds").data(this.data) lineSegmentEnds .attr("cx", function (d) {return d.xScale(d.endIdx - d.cursor)}) .attr("cy", function (d) {return d.yScale(d.endVal)}) .attr("r", function (d) {return d.radius}) lineSegmentEnds.enter().append("circle") .attr("id", function (d) {return "lineSegmentEnds_" + d.id}) .attr("class", "lineSegmentEnds") .attr("cx", function (d) {return d.xScale(d.endIdx - d.cursor)}) .attr("cy", function (d) {return d.yScale(d.endVal)}) .attr("r", function (d) {return d.radius}) .attr("fill", function (d) {return d.color}) .attr("opacity", 1.0) .attr("stroke", function (d) {return d.color}) .call(window.dragObj) lineSegmentEnds.exit().remove() var lineSegments = this.canvas.selectAll(".lineSegments").data(this.data) lineSegments .attr("x1", function (d) {return d.xScale(d.startIdx - d.cursor)}) .attr("y1", function (d) {return d.yScale(d.startVal)}) .attr("x2", function (d) {return d.xScale(d.endIdx - d.cursor)}) .attr("y2", function (d) {return d.yScale(d.endVal)}) lineSegments.enter().append("line") .attr("id", function (d) {return "lineSegments_" + d.id}) .attr("class", "lineSegments") .attr("x1", function (d) {return d.xScale(d.startIdx - d.cursor)}) .attr("y1", function (d) {return d.yScale(d.startVal)}) .attr("x2", function (d) {return d.xScale(d.endIdx - d.cursor)}) .attr("y2", function (d) {return d.yScale(d.endVal)}) .attr("stroke", function (d) {return d.color}) .attr("strokeWidth", function (d) {return d.strokeWidth}) lineSegments.exit().remove() } } window.lineSegment.data.push({ id: 1, color: color, strokeWidth: strokeWidth, radius: 5 }) }, function (context) { // Deinit() window.lineSegment.data = [] window.lineSegment.render() }, function (context) { // Render() var barNum = getBarNum(context) var cursor = getCursor(context) var width = getCanvasWidth(context) var height = getCanvasHeight(context) var xScale = getXScale(context) var yScale = getYScale(context) if (getCalculatedLength(context) == 0) { for (var i in window.lineSegment.data) { var data = window.lineSegment.data[i] data.startIdx = xScale.invert(width / 3) + cursor data.endIdx = xScale.invert(width * 2 / 3) + cursor data.startVal = yScale.invert(height * 2 / 3) data.endVal = yScale.invert(height / 3) } } for (var i in window.lineSegment.data) { var data = window.lineSegment.data[i] data.barNum = barNum data.cursor = cursor data.width = width data.height = height data.xScale = xScale data.yScale = yScale } window.lineSegment.render() }) ================================================ FILE: Indicators/Plugin-for-Data-API/crypto_loader.js ================================================ registerIndicator("fintechee_crypto_loader", "A plugin to load the specific cryptocurrency's streaming quotes(v1.02)", function (context) { // Disclaimer: we are not affiliated with the data providers or the API providers. }, [], [{ name: DATA_NAME.TIME, index: 0 }], [{ name: "crypto", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { setDefaultIndicator("fintechee_crypto_loader", true) if (typeof window.cryptoChangeCallback == "undefined") { window.cryptoChangeCallback = function (ctx) { var symbolName = getExtraSymbolName(ctx) if (typeof window.fintecheeCryptoLoader.cryptocurrenciesList[symbolName] != "undefined") { var chartId = getChartHandleByContext(ctx) var symbol = window.fintecheeCryptoLoader.cryptocurrenciesList[symbolName].symbolName.split("/") var baseCurrency = symbol[0] var termCurrency = symbol[1] setTakeoverMode(chartId) changeChartMenuItemName(ctx) var timeFrame = getTimeFrame(ctx) window.fintecheeCryptoLoader.ticksList.add(baseCurrency) window.fintecheeCryptoLoader.ticksList.add(termCurrency) if (typeof window.fintecheeCryptoLoader.charts[chartId + ""] == "undefined") { window.fintecheeCryptoLoader.charts[chartId + ""] = { chartId: chartId, timeFrame: null, baseCurrency: null, termCurrency: null, baseCurrencyPrice: null, termCurrencyPrice: null } } var chart = window.fintecheeCryptoLoader.charts[chartId + ""] chart.timeFrame = timeFrame chart.baseCurrency = baseCurrency chart.termCurrency = termCurrency $.ajax({ type: "GET", url: "https://api.coincap.io/v2/candles", contentType: "application/json; charset=utf-8", dataType: "json", data: { exchange: "poloniex", interval: timeFrame.toLowerCase(), baseId: baseCurrency, quoteId: termCurrency }, success: function (res) { if (typeof res.data != "undefined") { var data = [] if (Array.isArray(res.data)) { for (var i in res.data) { var ohlc = res.data[i] data.push({ time: Math.floor(ohlc.period / 1000), volume: parseFloat(ohlc.volume), open: parseFloat(ohlc.open), high: parseFloat(ohlc.high), low: parseFloat(ohlc.low), close: parseFloat(ohlc.close) }) } takeoverLoad(chartId, data) } } } }) window.fintecheeCryptoLoader.setupSocket() } else { var chartId = getChartHandleByContext(ctx) unsetTakeoverMode(chartId) takeoverLoad(chartId, []) delete window.fintecheeCryptoLoader.charts[chartId + ""] } } } if (typeof window.cryptoRemoveCallback == "undefined") { window.cryptoRemoveCallback = function (ctx) { var chartId = getChartHandleByContext(ctx) unsetTakeoverMode(chartId) takeoverLoad(chartId, []) delete window.fintecheeCryptoLoader.charts[chartId + ""] } } var chartId = getChartHandleByContext(context) if (typeof window.fintecheeCryptoLoader == "undefined") { window.fintecheeCryptoLoader = { cryptocurrenciesList: [], charts: [], ticksList: new Set(), socket: null, onTick: function (msg) { var ticks = JSON.parse(msg.data) for (var i in window.fintecheeCryptoLoader.charts) { var chart = window.fintecheeCryptoLoader.charts[i] var bUpdatable = false for (var j in ticks) { if (j == chart.baseCurrency) { chart.baseCurrencyPrice = parseFloat(ticks[j]) bUpdatable = true } if (j == chart.termCurrency) { chart.termCurrencyPrice = parseFloat(ticks[j]) bUpdatable = true } } if (bUpdatable) { if (chart.baseCurrencyPrice != null && chart.termCurrencyPrice != null && chart.baseCurrencyPrice > 0 && chart.termCurrencyPrice > 0) { var tick = { time: Math.floor(new Date().getTime() / 1000), volume: 0, price: chart.baseCurrencyPrice / chart.termCurrencyPrice } if (chart.timeFrame == "M1") { takeoverUpdate(chart.chartId, 60, tick) } else if (chart.timeFrame == "M5") { takeoverUpdate(chart.chartId, 300, tick) } else if (chart.timeFrame == "M15") { takeoverUpdate(chart.chartId, 900, tick) } else if (chart.timeFrame == "M30") { takeoverUpdate(chart.chartId, 1800, tick) } else if (chart.timeFrame == "H1") { takeoverUpdate(chart.chartId, 3600, tick) } else if (chart.timeFrame == "H4") { takeoverUpdate(chart.chartId, 14400, tick) } else if (chart.timeFrame == "D") { takeoverUpdate(chart.chartId, 86400, tick) } else { takeoverUpdate(chart.chartId, 86400, tick) } } } } }, setupSocket: function () { if (window.fintecheeCryptoLoader.socket != null) { if(window.fintecheeCryptoLoader.socket.readyState == WebSocket.OPEN) { window.fintecheeCryptoLoader.socket.close() } window.fintecheeCryptoLoader.socket = null } var ticksList = Array.from(window.fintecheeCryptoLoader.ticksList) if (ticksList.length > 0) { window.fintecheeCryptoLoader.socket = new WebSocket("wss://ws.coincap.io/prices?assets=" + ticksList.join(",")) window.fintecheeCryptoLoader.socket.onclose = function (e) {} window.fintecheeCryptoLoader.socket.onmessage = this.onTick } window.addEventListener("unload", function () { if (window.fintecheeCryptoLoader.socket != null) { if(window.fintecheeCryptoLoader.socket.readyState == WebSocket.OPEN) { window.fintecheeCryptoLoader.socket.close() } window.fintecheeCryptoLoader.socket = null } }) } } var chartIds = getLayout(1).concat(getLayout(2)).concat(getLayout(3)).concat(getLayout(4)) for (var i in chartIds) { if (typeof window.fintecheeCryptoLoader.charts[chartIds[i] + ""] == "undefined") { window.fintecheeCryptoLoader.charts[chartIds[i] + ""] = { chartId: chartIds[i], timeFrame: null, baseCurrency: null, termCurrency: null, baseCurrencyPrice: null, termCurrencyPrice: null } createTakeover(chartIds[i], window.cryptoChangeCallback, window.cryptoRemoveCallback) } } var cryptocurrenciesList = [{ symbolName: "ethereum/bitcoin", displayName: "ETH/BTC" }] for (var i in cryptocurrenciesList) { window.fintecheeCryptoLoader.cryptocurrenciesList[cryptocurrenciesList[i].displayName] = cryptocurrenciesList[i] } addExtraSymbols(cryptocurrenciesList) } else if (typeof window.fintecheeCryptoLoader.charts[chartId + ""] == "undefined") { window.fintecheeCryptoLoader.charts[chartId + ""] = { chartId: chartId, baseCurrency: null, termCurrency: null, baseCurrencyPrice: null, termCurrencyPrice: null } createTakeover(chartId, window.cryptoChangeCallback, window.cryptoRemoveCallback) } }, function (context) { }) ================================================ FILE: Indicators/Plugin-for-Data-API/usage.txt ================================================ This folder includes programs used for integrating with data providers, specifically crypto data providers. We plan to refactor the programs within this folder. Additionally, the program for connecting with the Oanda API, which was previously located in this folder, has been moved to a new directory named Plugin-for-Oanda. This directory has also undergone refactoring. If you need to reference the structure of a data provider's connectivity, we suggest referring to Plugin-for-Oanda. ================================================ FILE: Indicators/Plugin-for-Youtube/tutorial_videos.js ================================================ registerIndicator("tutorial_videos", "Embedded tutorial videos(v1.0)", function (context) { },[{ name: "url", value: "https://www.youtube.com/embed/EUjAIfttCoA", required: true, type: PARAMETER_TYPE.STRING, range: null }], [{ name: DATA_NAME.TIME, index: 0 }], [{ name: "sma", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { // Init() if (getLayoutId() != 2) { changeLayout(2) } window.chartIds = getLayout(2) for (var i in window.chartIds) { moveLayout(window.chartIds[i], 1) } embedHtml('', 2) }, function (context) { // Deinit() embedHtml("", 2) for (var i in window.chartIds) { moveLayout(window.chartIds[i], 2) } }) ================================================ FILE: Indicators/Plugin-for-Youtube/usage.txt ================================================ This plugin is designed to enable the display of YouTube videos, including live streams, within the chart layout. This allows YouTubers to conduct live trading activities and engage with their fans through social media. With the aid of this plugin, YouTubers can screen share their trading sessions while streaming live on YouTube. This facilitates real-time communication with viewership, while fans comment and ask questions, making the trading experience more engaging. ================================================ FILE: Indicators/atr_comparison/README.md ================================================ ![Fintechee ATR comparison indicator](https://github.com/fintechees/Expert-Advisor-Studio/blob/master/Indicators/atr_comparison/atr_comparison_screenshot.png?raw=true) ================================================ FILE: Indicators/atr_comparison/atr_comparison.js ================================================ registerIndicator( "atr_comparison", "An improved Average True Range(v1.0)", function (context) { // Please add atr_exporter to the target charts before you add this indicator to one of the target charts. // For example, if you want to compare EUR/USD with AUD/USD, then you need to add atr_exporter to the target charts EUR/USD and AUD/USD respectively. // After that, you need to add atr_comparison to either EUR/USD or AUD/USD. var name1 = getIndiParameter(context, "name1") var name2 = getIndiParameter(context, "name2") if (typeof window.inventoryForATR == "undefined" || typeof window.inventoryForATR[name1] == "undefined" || typeof window.inventoryForATR[name2] == "undefined") { delete context.bFirstRun return } else { if (typeof context.bFirstRun == "undefined") { context.bFirstRun = true } } var dataInput1 = window.inventoryForATR[name1] var dataInput2 = window.inventoryForATR[name2] var dataOutput1 = getDataOutput(context, "atr1") var dataOutput2 = getDataOutput(context, "atr2") var dataInputLen1 = dataInput1.length var dataInputLen2 = dataInput2.length var dataOutputLen1 = dataOutput1.length var dataOutputLen2 = dataOutput2.length if (context.bFirstRun) { var dataLen = 0 if (dataInputLen1 <= dataInputLen2) { dataLen = dataInputLen1 } else { dataLen = dataInputLen2 } for (var i = dataInputLen1 - 1; i >= dataInputLen1 - dataLen; i--) { dataOutput1[i] = dataInput1[i] } for (var i = dataInputLen1 - dataLen - 1; i >= 0; i--) { dataOutput1[i] = 0 } for (var i = dataInputLen2 - 1; i >= dataInputLen2 - dataLen; i--) { dataOutput2[i] = dataInput2[i] } for (var i = dataInputLen2 - dataLen - 1; i >= 0; i--) { dataOutput2[i] = 0 } } else { dataOutput1[dataOutputLen1 - 1] = dataInput1[dataInputLen1 - 1] dataOutput2[dataOutputLen2 - 1] = dataInput2[dataInputLen2 - 1] } },[{ name: "name1", value: "chart1", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "name2", value: "chart2", required: true, type: PARAMETER_TYPE.STRING, range: null }], [{ name: DATA_NAME.TIME, index: 0 }], [{ name: "atr1", visible: true, renderType: RENDER_TYPE.LINE, color: "steelblue" },{ name: "atr2", visible: true, renderType: RENDER_TYPE.LINE, color: "orange" }], WHERE_TO_RENDER.SEPARATE_WINDOW, function (context) { // Init() }, function (context) { // Deinit() }, function (context) { // Render() }) ================================================ FILE: Indicators/atr_comparison/atr_comparison_guide.txt ================================================ We expand ATR to an improved version that helps us compare the volatilities of different symbols at the same time in one chart. How it works? We implemented two indicators, one is used to export the data you want to aggregate, such as EURUSD H1 and AUDUSD H1, so you need to add the atr_exporter to EURUSD H1 and AUDUSD H1 both charts. There is a parameter named "name". You need to set this parameter to make the other indicator atr_comparison identify the charts you are referring to. You can set the name for EURUSD H1 chart to "chart1", you can set the name for AUDUSD H1 to "chart2". And then, you add atr_comparison to either of the two charts. Let's say EURUSD H1. atr_comparison has two parameters, one should be set "chart1" to make it point to EURUSD H1, the other one should be set "chart2" to make it point to AUDUSD H1. Finally, you put both charts data in one indicator window, and now you can monitor the differences of the fluctuations to find the chance. This indicator only supports two symbols. You can expand it to be able to monitor more symbols by just a little editing the original version. ================================================ FILE: Indicators/atr_comparison/atr_exporter.js ================================================ registerIndicator( "atr_exporter", "A tool to export the data of Average True Range to the window object(v1.01)", function (context) { var dataInputClose = getDataInput(context, 0) var dataInputHigh = getDataInput(context, 1) var dataInputLow = getDataInput(context, 2) var tmpLine = getDataOutput(context, "tmp") var dataOutput = getDataOutput(context, "atr") var period = getIndiParameter(context, "period") var name = getIndiParameter(context, "name") var calculatedLength = getCalculatedLength(context) var i = calculatedLength var high = null var low = null var prevClose = null if (i > 0) { i-- } else { tmpLine[i] = 0 i = 1 } while (i < dataInputClose.length) { high = dataInputHigh[i] low = dataInputLow[i] prevClose = dataInputClose[i - 1] tmpLine[i] = Math.max(high, prevClose) - Math.min(low, prevClose) i++ } sma(tmpLine, dataOutput, calculatedLength, period) if (calculatedLength == 0) { window.inventoryForATR[name] = dataOutput } },[{ name: "period", value: 14, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 100] }, { name: "name", value: "chart1", required: true, type: PARAMETER_TYPE.STRING, range: null }], [{ name: DATA_NAME.CLOSE, index: 0 },{ name: DATA_NAME.HIGH, index: 1 },{ name: DATA_NAME.LOW, index: 2 }], [{ name: "tmp", visible: false },{ name: "atr", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function (context) { // Init() if (typeof window.inventoryForATR == "undefined") { window.inventoryForATR = [] } }, function (context) { // Deinit() var name = getIndiParameter(context, "name") delete window.inventoryForATR[name] }, function (context) { // Render() }) ================================================ FILE: Indicators/barrage/barrage.js ================================================ registerIndicator("barrage", "A plugin to display barrages on the chart(v1.03)", function(context) {}, [{ name: "color", value: "#FAE2BE", required: true, type: PARAMETER_TYPE.STRING, range: null }, { name: "strokeWidth", value: 2, required: true, type: PARAMETER_TYPE.INTEGER, range: [1, 10] }], [{ name: DATA_NAME.TIME, index: 0 }], [{ name: "barrage", visible: false }], WHERE_TO_RENDER.CHART_WINDOW, function(context) { // Init() var chartHandle = getChartHandleByContext(context) if (typeof window.fintecheeBarrage == "undefined") { var barrageStyles = ` .barrage-class { position: absolute; background-color: #f0f0f0; border: 1px solid #ccc; padding: 5px; border-radius: 5px; font-size: 12px; } ` var styleElement = $("