この記事では,簡単なトレンド戦略の設計を戦略設計レベルからのみ説明し,初心者が簡単な戦略の設計方法と戦略プログラムの実行プロセスを理解することを学ぶのを助ける. 戦略のパフォーマンスの質については,戦略パラメータと大きく関係しています (これはほとんどすべてのトレンド戦略の場合です).
EMAの2つの指標を使用すると,両方の移動平均値がブレイクポイントを有し,ブレイクポイントは,長期および短期ポジションを開く (または逆転) 信号として使用され,固定目標利益分散を設計する.コメントは,読みやすくするために戦略コードに直接書かれています.全体的な戦略コードは非常に短く,初心者にとって適しています.
/*backtest
start: 2021-09-01 00:00:00
end: 2021-12-02 00:00:00
period: 1h
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
// above /**/ inside these are the default backtest settings; the backtest page can be reset by the related controls on the backtest page
var LONG = 1 // mark of holding long positions; enum constant
var SHORT = -1 // mark of holding short positions; enum constant
var IDLE = 0 // mark of not holding no position; enum constant
// obtain the positions with a specified direction; positions indicates position data; direction indicates the direction of the positions to be obtained
function getPosition(positions, direction) {
var ret = {Price : 0, Amount : 0, Type : ""} // define a structure when holding no position
// traverse positions, among which find the positions conforming to the direction
if (pos.Type == direction) {
ret = pos
}
})
// return the positions found
return ret
}
// cancel all pending orders of the current trading pair and contract
function cancellAll() {
// infinite loop, detect without stop, until break is triggered
while (true) {
// obtain the pending orders data of the current trading pair and contract, namely orders
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
// when orders is a null array, namely orders.length == 0, execute "break" statement to break the while loop
break
} else {
// traverse all the current pending orders, and cancel them one by one
for (var i = 0 ; i < orders.length ; i++) {
// the function to cancel a specified order, canceling the order with an ID of:orders[i].Id
exchange.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
}
Sleep(500)
}
}
// function of closing position, which executes close position, according to the passed tradeFunc and direction
function cover(tradeFunc, direction) {
var mapDirection = {"closebuy": PD_LONG, "closesell": PD_SHORT}
var positions = _C(exchange.GetPosition) // obtain the position data of the current trading pair and contract
var pos = getPosition(positions, mapDirection[direction]) // find the position information of the specified close position direction
// when position volume is over 0 (only when there is a position, you can operate close position)
if (pos.Amount > 0) {
// cancel all possibly existing pending orders
cancellAll()
// set trading direction
exchange.SetDirection(direction)
// execute close position tradefunc
if (tradeFunc(-1, pos.Amount)) {
// if ordering successfully, return true
return true
} else {
// if the ordering fails, return false
return false
}
}
// no position returns true
return true
}
// strategy main function
function main() {
// used to switch to OKEX V5 simulated bot
if (okexSimulate) {
exchange.IO("simulate", true) // switch to OKEX V5 simulated bot to test
Log("switch to OKEX V5 simulated bot")
}
// set contract code; set ct to swap, namely set the current operated contract to a perpetual contract
exchange.SetContractType(ct)
// the initial status is no position
var state = IDLE
// the initial position price is 0
var holdPrice = 0
// innitialize the timestamp for comparison, to compare whether the current K-line BAR changes
var preTime = 0
// strategy main loop
while (true) {
// obtain the K-line data of the current trading pair and contract
var r = _C(exchange.GetRecords)
// obtain the K-line length, namely 1
var l = r.length
// judge the K-line length of 1, which has to be longer than the indicator period (if the length is less than the indicator period, the indicator function cannot calculate the effective indicatorr data); if not, the loop will be restarted
if (l < Math.max(ema1Period, ema2Period)) {
// wait 1000 miliseconds, namely 1 second, to avoid rotating too fast
Sleep(1000)
// ignore the code after "if" at the moment, and restart the while loop
continue
}
// calculate EMA indicator data
var ema1 = TA.EMA(r, ema1Period)
var ema2 = TA.EMA(r, ema2Period)
// plot
$.PlotRecords(r, 'K-line') // draw K-line chart
// when the timestamp of the last BAR changes, namely when the new K-line BAR is generated
if(preTime !== r[l - 1].Time){
// before the new K-line BAR is generated, it is the last update of the last BAR
$.PlotLine('ema1', ema1[l - 2], r[l - 2].Time)
$.PlotLine('ema2', ema2[l - 2], r[l - 2].Time)
// draw the EMA lines of the new BAR, namely the EMA indicator data on the current last BAR
$.PlotLine('ema1', ema1[l - 1], r[l - 1].Time)
$.PlotLine('ema2', ema2[l - 1], r[l - 1].Time)
// update the timestamp for comparison
preTime = r[l - 1].Time
} else {
// at the moment when there is no new BAR generated, just update the EMA indicator data of the last BAR in the chart
$.PlotLine('ema1', ema1[l - 1], r[l - 1].Time)
$.PlotLine('ema2', ema2[l - 1], r[l - 1].Time)
}
// condition of open long position, breakpoint
var up = (ema1[l - 2] > ema1[l - 3] && ema1[l - 4] > ema1[l - 3]) && (ema2[l - 2] > ema2[l - 3] && ema2[l - 4] > ema2[l - 3])
// condition of open short position, breakpoint
var down = (ema1[l - 2] < ema1[l - 3] && ema1[l - 4] < ema1[l - 3]) && (ema2[l - 2] < ema2[l - 3] && ema2[l - 4] < ema2[l - 3])
// when the condition of open long position is triggered and currently short positions are held, or when the condition of open long position is triggered but there is no position
if (up && (state == SHORT || state == IDLE)) {
// if holding short, close first
if (state == SHORT && cover(exchange.Buy, "closesell")) {
// after close positions, mark the status of no position
state = IDLE
// reset the position price to 0
holdPrice = 0
// mark on the chart
$.PlotFlag(r[l - 1].Time, 'coverShort', 'CS')
}
// after close positions, reverse to open long
exchange.SetDirection("buy")
if (exchange.Buy(-1, amount)) {
// mark the current status
state = LONG
// record the current price
holdPrice = r[l - 1].Close
$.PlotFlag(r[l - 1].Time, 'openLong', 'L')
}
} else if (down && (state == LONG || state == IDLE)) {
// similar to the judge of up condition
if (state == LONG && cover(exchange.Sell, "closebuy")) {
state = IDLE
holdPrice = 0
$.PlotFlag(r[l - 1].Time, 'coverLong', 'CL')
}
exchange.SetDirection("sell")
if (exchange.Sell(-1, amount)) {
state = SHORT
holdPrice = r[l - 1].Close
$.PlotFlag(r[l - 1].Time, 'openShort', 'S')
}
}
// stop profit
if (state == LONG && r[l - 1].Close - holdPrice > profitTarget && cover(exchange.Sell, "closebuy")) {
state = IDLE
holdPrice = 0
$.PlotFlag(r[l - 1].Time, 'coverLong', 'CL')
} else if (state == SHORT && holdPrice - r[l - 1].Close > profitTarget && cover(exchange.Buy, "closesell")) {
state = IDLE
holdPrice = 0
$.PlotFlag(r[l - 1].Time, 'coverShort', 'CS')
}
// display the time on the status bar
LogStatus(_D())
Sleep(500)
}
}
戦略のソースコード:https://www.fmz.com/strategy/333269
この戦略は プログラムデザインの教えに過ぎません だからボットでは 使わないでください