В процессе загрузки ресурсов... загрузка...

Цифровые валютные фьючерсы Стратегия поворотного момента двойной EMA (учебное пособие)

Автор:FMZ~Lydia, Создано: 2022-11-09 09:44:38, Обновлено: 2023-09-20 10:25:53

img

В этой статье мы объясним, как разработать простую стратегию тренда, только на уровне разработки стратегии, чтобы помочь новичкам узнать, как разработать простую стратегию и понять процесс исполнения стратегии.

Разработка стратегии

Мы используем два индикатора EMA, когда у обеих средних EMA есть поворотные точки. Поворотная точка используется в качестве сигнала для открытия позиций (или продажи открывающей позиции) для открытия длинных, открытия коротких позиций, и фиксированная целевая дифференциальная прибыль позиции закрытия разработана. Комментарии написаны непосредственно в коде стратегии для удобного чтения. Код стратегии, как правило, очень короткий и подходит для обучения новичков.

Код стратегии

/*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)        
    }
}

img

img

Источник стратегии:https://www.fmz.com/strategy/333269

Стратегия предназначена только для обучения программированию, пожалуйста, не используйте ее в реальном боте.


Связанные

Больше