In diesem Artikel werden wir erklären, wie man eine einfache Trending-Strategie entwirft, nur auf der Strategie-Design-Ebene, um Anfängern zu helfen zu lernen, wie man eine einfache Strategie entwirft und den Strategieausführungsprozess versteht.
Wir verwenden zwei EMA-Indikatoren, wenn beide EMA-Durchschnitte Wendepunkte haben. Der Wendepunkt wird als Signal zur Eröffnung von Positionen (oder zum Verkauf der Eröffnungsposition) für die Eröffnung von Long, Eröffnung von Short-Positionen verwendet, und eine feste Ziel-Gewinndifferenz-Positionsschließung ist entworfen. Die Kommentare werden direkt im Strategiecode für bequemes Lesen geschrieben. Der Strategiecode ist im Allgemeinen sehr kurz und für Anfänger geeignet.
/*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"}]
*/
// The above /**/ is the default setting for backtesting, you can reset it on the backtesting page by using the relevant controls
var LONG = 1 // Markers for holding long positions, enum constant
var SHORT = -1 // Markers for holding short positions, enum constant
var IDLE = 0 // Markers without holding positions, enum constant
// Obtain positions in the specified direction. Positions is the position data, and direction is the position direction to be obtained
function getPosition(positions, direction) {
var ret = {Price : 0, Amount : 0, Type : ""} // Define a structure when no position is held
// Iterate through the positions and find the positions that match the direction
_.each(positions, function(pos) {
if (pos.Type == direction) {
ret = pos
}
})
// Return to found positions
return ret
}
// Cancel all makers of current trading pairs and contracts
function cancellAll() {
// Dead loop, keep detecting until break is triggered
while (true) {
// Obtain the makers' data of the current trading pair and contract, i.e. orders
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
// When orders is an empty array, i.e. orders.length == 0, break is executed to exit the while loop
break
} else {
// Iterate through all current makers and cancel them one by one
for (var i = 0 ; i < orders.length ; i++) {
// The function to cancel the specific order, cancel the order with ID: orders[i].Id
exchange.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
}
Sleep(500)
}
}
// The closing function, used for closing positions according to the trading function-tradeFunc and direction passed in
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 in the specified closing position direction
// When the position is greater than 0 (the position can be closed only when there is a position)
if (pos.Amount > 0) {
// Cancel all possible makers
cancellAll()
// Set the trading direction
exchange.SetDirection(direction)
// Execute closing position trade functions
if (tradeFunc(-1, pos.Amount)) {
// Return to true if the order is placed
return true
} else {
// Return to false if the order is failed to place
return false
}
}
// Return to true if there is no position
return true
}
// Strategy main functions
function main() {
// For switching to OKEX V5 Demo
if (okexSimulate) {
exchange.IO("simulate", true) // Switch to OKEX V5 Demo for a test
Log("Switch to OKEX V5 Demo")
}
// Set the contract code, if ct is swap, set the current contract to be a perpetual contract
exchange.SetContractType(ct)
// Initialization status is open position
var state = IDLE
// The initialized position price is 0
var holdPrice = 0
// Timestamp for initialization comparison, used to compare whether the current K-Line BAR has changed
var preTime = 0
// Strategy main loop
while (true) {
// Obtain the K-line data for current trading pairs and contracts
var r = _C(exchange.GetRecords)
// Obtain the length of the K-line data, i.e. l
var l = r.length
// Judge the K-line length that l must be greater than the indicator period (if not, the indicator function cannot calculate valid indicator data), or it will be recycled
if (l < Math.max(ema1Period, ema2Period)) {
// Wait for 1,000 milliseconds, i.e. 1 second, to avoid rotating too fast
Sleep(1000)
// Ignore the code after the current if, and execute while loop again
continue
}
// Calculate ema indicator data
var ema1 = TA.EMA(r, ema1Period)
var ema2 = TA.EMA(r, ema2Period)
// Drawing chart
$.PlotRecords(r, 'K-Line') // Drawing the K-line chart
// When the last BAR timestamp changes, i.e. when a new K-line BAR is created
if(preTime !== r[l - 1].Time){
// The last update of the last BAR before the new BAR appears
$.PlotLine('ema1', ema1[l - 2], r[l - 2].Time)
$.PlotLine('ema2', ema2[l - 2], r[l - 2].Time)
// Draw the indicator line of the new BAR, i.e. the 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 used for comparison
preTime = r[l - 1].Time
} else {
// When no new BARs are generated, only the indicator data of the last BAR on the chart is updated
$.PlotLine('ema1', ema1[l - 1], r[l - 1].Time)
$.PlotLine('ema2', ema2[l - 1], r[l - 1].Time)
}
// Conditions for opening long positions, turning points
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])
// Conditions for opening short positions, turning points
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])
// The condition of opening a long position is triggered and the current short position is held, or the condition of opening a long position is triggered and no position is held
if (up && (state == SHORT || state == IDLE)) {
// If you have a short position, close it first
if (state == SHORT && cover(exchange.Buy, "closesell")) {
// Mark open positions after closing them
state = IDLE
// The price of reset position is 0
holdPrice = 0
// Mark on the chart
$.PlotFlag(r[l - 1].Time, 'coverShort', 'CS')
}
// Open a long position after closing the position
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)) {
// The same as the judgment 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 profits
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 time on the status bar
LogStatus(_D())
Sleep(500)
}
}
Strategie-Quellcode:https://www.fmz.com/strategy/333269
Die Strategie ist nur für Programmdesign-Tutorial, bitte benutzen Sie sie nicht im echten Bot.