Digital Currency Spot Multi Variety Double Moving Average Strategy Teaching
Related articles:https://www.fmz.com/bbs-topic/8512
Related articles:https://www.fmz.com/bbs-topic/8512
Parameters
| Name | Default | What it controls |
|---|---|---|
| symbols | ETH_USDT,ETC_USDT,LTC_USDT | Trading Pair Code |
| ema1Periods | 10,15,20 | First EMA indicator |
| ema2Periods | 15,20,25 | Second EMA indicator |
| orderAmounts | 1,1,1 | Order quantity, number of coins |
| takeLevel | 10 | Order Slots |
| isReset | false | Reset all data |
Source JavaScript
function cancelAll(e) {
while (true) {
var orders = _C(e.GetOrders)
if (orders.length == 0) {
break
} else {
for (var i = 0 ; i < orders.length ; i++) {
e.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
}
Sleep(500)
}
}
function getProfit(account, initAccount, lastPrices) {
var sum = 0
_.each(account, function(val, key) {
if (key != "USDT" && typeof(initAccount[key]) == "number" && lastPrices[key + "_USDT"]) {
sum += (account[key] - initAccount[key]) * lastPrices[key + "_USDT"]
}
})
return account["USDT"] - initAccount["USDT"] + sum
}
function createChartConfig(symbol, ema1Period, ema2Period) {
var chart = {
__isStock: true,
extension: {
layout: 'single',
height: 600,
},
title : { text : symbol},
xAxis: { type: 'datetime'},
series : [
{
type: 'candlestick',
name: symbol,
id: symbol,
data: []
}, {
type: 'line',
name: symbol + ',EMA1:' + ema1Period,
data: [],
}, {
type: 'line',
name: symbol + ',EMA2:' + ema2Period,
data: []
}
]
}
return chart
}
function main() {
// Reset all data
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("Reset all data", "#FF0000")
}
// Parse Parameters
var arrSymbols = symbols.split(",")
var arrEma1Periods = ema1Periods.split(",")
var arrEma2Periods = ema2Periods.split(",")
var arrAmounts = orderAmounts.split(",")
var account = {}
var initAccount = {}
var currTradeMsg = {}
var lastPrices = {}
var lastBarTime = {}
var arrChartConfig = []
if (_G("currTradeMsg")) {
currTradeMsg = _G("currTradeMsg")
Log("Restore Records", currTradeMsg)
}
// Initializeaccount
_.each(arrSymbols, function(symbol, index) {
exchange.SetCurrency(symbol)
var arrCurrencyName = symbol.split("_")
var baseCurrency = arrCurrencyName[0]
var quoteCurrency = arrCurrencyName[1]
if (quoteCurrency != "USDT") {
throw "only support quoteCurrency: USDT"
}
if (!account[baseCurrency] || !account[quoteCurrency]) {
cancelAll(exchange)
var acc = _C(exchange.GetAccount)
account[baseCurrency] = acc.Stocks
account[quoteCurrency] = acc.Balance
}
lastBarTime[symbol] = 0
arrChartConfig.push(createChartConfig(symbol, arrEma1Periods[index], arrEma2Periods[index]))
})
if (_G("initAccount")) {
initAccount = _G("initAccount")
Log("Restore initial account records", initAccount)
} else {
_.each(account, function(val, key) {
initAccount[key] = val
})
}
Log("account:", account, "initAccount:", initAccount)
var chart = Chart(arrChartConfig)
chart.reset()
while (true) {
_.each(arrSymbols, function(symbol, index) {
exchange.SetCurrency(symbol)
var arrCurrencyName = symbol.split("_")
var baseCurrency = arrCurrencyName[0]
var quoteCurrency = arrCurrencyName[1]
var ema1Period = parseFloat(arrEma1Periods[index])
var ema2Period = parseFloat(arrEma2Periods[index])
var amount = parseFloat(arrAmounts[index])
var r = exchange.GetRecords()
if (!r || r.length < Math.max(ema1Period, ema2Period)) {
Sleep(1000)
return
}
var currBarTime = r[r.length - 1].Time
lastPrices[symbol] = r[r.length - 1].Close
var ema1 = TA.EMA(r, ema1Period)
var ema2 = TA.EMA(r, ema2Period)
if (ema1.length < 3 || ema2.length < 3) {
Sleep(1000)
return
}
var ema1Last2 = ema1[ema1.length - 2]
var ema1Last3 = ema1[ema1.length - 3]
var ema2Last2 = ema2[ema2.length - 2]
var ema2Last3 = ema2[ema2.length - 3]
// Write chart data
var klineIndex = index + 2 * index
for (var i = 0 ; i < r.length ; i++) {
if (r[i].Time == lastBarTime[symbol]) {
// Update
chart.add(klineIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close], -1)
chart.add(klineIndex + 1, [r[i].Time, ema1[i]], -1)
chart.add(klineIndex + 2, [r[i].Time, ema2[i]], -1)
} else if (r[i].Time > lastBarTime[symbol]) {
// Add
lastBarTime[symbol] = r[i].Time
chart.add(klineIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close])
chart.add(klineIndex + 1, [r[i].Time, ema1[i]])
chart.add(klineIndex + 2, [r[i].Time, ema2[i]])
}
}
if (ema1Last3 < ema2Last3 && ema1Last2 > ema2Last2 && currTradeMsg[symbol] != currBarTime) {
var depth = exchange.GetDepth()
var price = depth.Asks[Math.min(takeLevel, depth.Asks.length)].Price
if (depth && price * amount <= account[quoteCurrency]) {
exchange.Buy(price, amount, ema1Last3, ema2Last3, ema1Last2, ema2Last2)
cancelAll(exchange)
var acc = _C(exchange.GetAccount)
if (acc.Stocks != account[baseCurrency]) {
account[baseCurrency] = acc.Stocks
account[quoteCurrency] = acc.Balance
currTradeMsg[symbol] = currBarTime
_G("currTradeMsg", currTradeMsg)
var profit = getProfit(account, initAccount, lastPrices)
if (profit) {
LogProfit(profit, account, initAccount)
}
}
}
} else if (ema1Last3 > ema2Last3 && ema1Last2 < ema2Last2 && currTradeMsg[symbol] != currBarTime) {
var depth = exchange.GetDepth()
var price = depth.Bids[Math.min(takeLevel, depth.Bids.length)].Price
if (depth && amount <= account[baseCurrency]) {
exchange.Sell(price, amount, ema1Last3, ema2Last3, ema1Last2, ema2Last2)
cancelAll(exchange)
var acc = _C(exchange.GetAccount)
if (acc.Stocks != account[baseCurrency]) {
account[baseCurrency] = acc.Stocks
account[quoteCurrency] = acc.Balance
currTradeMsg[symbol] = currBarTime
_G("currTradeMsg", currTradeMsg)
var profit = getProfit(account, initAccount, lastPrices)
if (profit) {
LogProfit(profit, account, initAccount)
}
}
}
}
Sleep(1000)
})
var tbl = {
type : "table",
title : "Account Information",
cols : [],
rows : []
}
tbl.cols.push("--")
tbl.rows.push(["initial"])
tbl.rows.push(["Current"])
_.each(account, function(val, key) {
if (typeof(initAccount[key]) == "number") {
tbl.cols.push(key)
tbl.rows[0].push(initAccount[key]) // initial
tbl.rows[1].push(val) // Current
}
})
LogStatus(_D(), "\n", "profit:", getProfit(account, initAccount, lastPrices), "\n", "`" + JSON.stringify(tbl) + "`")
}
}Published by 发明者量化-小小梦 on the FMZ strategy square · last modified 2021-12-07. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Digital-Currency-Spot-Multi-Variety-Double-Moving-Average-Strategy-Teaching.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.
Related specs
- Test About the Long Term Effect of MartinJavaScript · Other · 1d
- Three Moving Average System ExodusJavaScript · Other · 1h
- 8 Hours EMAJavaScript · Other · 4h
- Teaching Strategy TCI Strategy Mai Language TransplantationJavaScript · Other · 1d
- Test Using KDJ and VOL Volume to Filter for Coins with Potential to RiseJavaScript · Other · 1d
- Digital Currency Futures Double Moving Average Turning Point Strategy TeachingJavaScript · Other · 1h