Научить писать стратегии - пересадить стратегию MyLanguage

Автор:Лидия., Создано: 2022-12-26 15:23:08, Обновлено: 2023-09-13 19:44:28

img

Научить писать стратегии пересадить стратегию MyLanguage

Недавно, когда я говорил о стратегиях со своими друзьями, я узнал, что многие стратегии, написанные в MyLanguage, страдают от гибкости. Во многих случаях необходимо использовать стандартный период K-линии, который не предоставляется системой. Например, максимальное требование - использовать K-линию в течение 4 часов. Эта проблема была решена в статье. Если вы заинтересованы, пожалуйста, посмотрите:СсылкаОднако в стратегии MyLanguage, из-за высокой функции инкапсулирования MyLanguage, она не является гибкой для обработки данных самостоятельно.

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

Код образца для многоразового использования:

Взять стратегию фьючерсов OKX в качестве примера.

// Global variables
var IDLE = 0
var LONG = 1
var SHORT = 2
var OPENLONG = 3
var OPENSHORT = 4
var COVERLONG = 5
var COVERSHORT = 6  

var BREAK = 9
var SHOCK = 10  

var _State = IDLE
var Amount = 0                 // Record the number of positions
var TradeInterval = 500        // Polling intervals
var PriceTick = 1              // Price per jump
var Symbol = "this_week"  

function OnTick(){
    // Ticker processing part of the driving strategy
    // To be filled...
     
    // Trading signal trigger processing section
    // To be filled...  

    // Execution of trading logic
    var pos = null
    var price = null
    var currBar = records[records.length - 1]
    if(_State == OPENLONG){
        pos = GetPosition(PD_LONG)
        // Determine whether the state is satisfied, and if so, modify the state.
        if(pos[1] >= Amount){
            _State = LONG
            Amount = pos[1]   // Update the actual volume.
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2
        Trade(OPENLONG, price, Amount - pos[1], pos, PriceTick)                // (Type, Price, Amount, CurrPos, PriceTick)
    }  

    if(_State == OPENSHORT){
        pos = GetPosition(PD_SHORT)
        if(pos[1] >= Amount){
            _State = SHORT
            Amount = pos[1]   // Update the actual volume.
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2
        Trade(OPENSHORT, price, Amount - pos[1], pos, PriceTick)
    }  

    if(_State == COVERLONG){
        pos = GetPosition(PD_LONG)
        if(pos[1] == 0){
            _State = IDLE
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2
        Trade(COVERLONG, price, pos[1], pos, PriceTick)
    }
    
    if(_State == COVERSHORT){
        pos = GetPosition(PD_SHORT)
        if(pos[1] == 0){
            _State = IDLE
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2
        Trade(COVERSHORT, price, pos[1], pos, PriceTick)
    }
}  

// Trading logic section
function GetPosition(posType) {
    var positions = _C(exchange.GetPosition)
    var count = 0
    for(var j = 0; j < positions.length; j++){
        if(positions[j].ContractType == Symbol){
            count++
        }
    }  

    if(count > 1){
        throw "positions error:" + JSON.stringify(positions)
    }  

    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType == Symbol && positions[i].Type === posType) {
            return [positions[i].Price, positions[i].Amount];
        }
    }
    Sleep(TradeInterval);
    return [0, 0];
}  

function CancelPendingOrders() {
    while (true) {
        var orders = _C(exchange.GetOrders)
        for (var i = 0; i < orders.length; i++) {
            exchange.CancelOrder(orders[i].Id);
            Sleep(TradeInterval);
        }
        if (orders.length === 0) {
            break;
        }
    }
}  

function Trade(Type, Price, Amount, CurrPos, OnePriceTick){    // Processing transactions
    if(Type == OPENLONG || Type == OPENSHORT){                 // Processing of opening positions
        exchange.SetDirection(Type == OPENLONG ? "buy" : "sell")
        var pfnOpen = Type == OPENLONG ? exchange.Buy : exchange.Sell
        var idOpen = pfnOpen(Price, Amount, CurrPos, OnePriceTick, Type)
        Sleep(TradeInterval)
        if(idOpen) {
            exchange.CancelOrder(idOpen)
        } else {
            CancelPendingOrders()
        }
    } else if(Type == COVERLONG || Type == COVERSHORT){        // Processing of closing positions
        exchange.SetDirection(Type == COVERLONG ? "closebuy" : "closesell")
        var pfnCover = Type == COVERLONG ? exchange.Sell : exchange.Buy
        var idCover = pfnCover(Price, Amount, CurrPos, OnePriceTick, Type)
        Sleep(TradeInterval)
        if(idCover){
            exchange.CancelOrder(idCover)
        } else {
            CancelPendingOrders()
        }
    } else {
        throw "Type error:" + Type
    }
}  

function main() { 
    // Set up the contract
    exchange.SetContractType(Symbol)  

    while(1){
        OnTick()
        Sleep(1000)
    }
}

Пример: Трансплантация двойной стратегии EMA

Проверка MyLanguage:

img

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

MA5^^MA(C,5);
MA15^^MA(C,15);
CROSSUP(MA5,MA15),BPK;
CROSSDOWN(MA5,MA15),SPK;

Трансплантация на стратегию JavaScript

Во-первых, заполните части сбора тикеров и расчета показателей для кода многоразового образца:

// The ticker processing part of the driving strategy
var records = _C(exchange.GetRecords)  

if (records.length < 15) {
    return 
}  

var ma5 = TA.MA(records, 5)
var ma15 = TA.MA(records, 15)
var ma5_pre = ma5[ma5.length - 3]
var ma15_pre = ma15[ma15.length - 3]
var ma5_curr = ma5[ma5.length - 2]
var ma15_curr = ma15[ma15.length - 2]

Как видите, стратегия двойной EMA очень проста.records, а затем использовать функцию EMATA.MAизTA function libraryдля расчета 5-дневной EMA и 15-дневной EMA (как мы можем видеть в интерфейсе обратного теста, период K-линии установлен на ежедневную K-линию, так чтоTA.MA(records, 5)рассчитывать 5-дневную ЭМА,TA.MA(records, 15)для расчета 15-дневной ЭМА). Тогда получите предпоследнюю точку.ma5_curr(значение показателя), последняя третья точкаma5_pre(значение показателя) данных показателяma5, и то же самое дляma15Затем мы можем использовать эти данные показателей, чтобы судить о Золотом кресте и медвежьем кроссовере, как показано на рисунке:

img

Всякий раз, когда такое состояние формируется, это определенный Золотой крест или медвежий перекресток.

Затем часть оценки сигнала может быть написана следующим образом:

if(_State == IDLE && ma5_pre < ma15_pre && ma5_curr > ma15_curr){     
    _State = OPENLONG
    Amount = 1
}  

if(_State == IDLE && ma5_pre > ma15_pre && ma5_curr < ma15_curr){     
    _State = OPENSHORT
    Amount = 1
}  

if(_State == LONG && ma5_pre > ma15_pre && ma5_curr < ma15_curr){     
    _State = COVERLONG
    Amount = 1
}  

if(_State == SHORT && ma5_pre < ma15_pre && ma5_curr > ma15_curr){     
    _State = COVERSHORT
    Amount = 1
}

Таким образом, трансплантация будет нормальной. Обратное тестирование стратегии JavaScript Конфигурация обратного тестирования:

img

Результат обратного тестирования:

img

Обратное тестирование MyLanguage

img

Таким образом, если вы хотите продолжать добавлять интерактивные функции, обработку данных (например, синтез K-линии) и настраиваемое отображение диаграммы к стратегии, вы можете достичь этого.

Если вам интересно, попробуйте.


Связанные

Больше