Baru-baru ini, ketika bercakap tentang strategi dengan rakan-rakan saya, saya belajar bahawa banyak strategi yang ditulis dalam MyLanguage mengalami fleksibiliti. Dalam banyak kes, adalah perlu untuk menggunakan tempoh K-line standard yang tidak disediakan oleh sistem. Sebagai contoh, keperluan maksimum adalah untuk menggunakan K-line selama 4 jam. Masalah ini telah diselesaikan dalam satu artikel. Jika anda berminat, sila lihat:Pautan. Walau bagaimanapun, dalam strategi MyLanguage, kerana ciri encapsulation tinggi MyLanguage, ia tidak fleksibel untuk memproses data sendiri. Pada masa ini, adalah perlu untuk memindahkan idea strategi ke bahasa lain.
Ia adalah sangat mudah untuk pemindahan strategi trend. kita boleh menggunakan kod contoh untuk mengisi dalam bahagian pengiraan data kod yang memandu strategi, dan mengisi dalam keadaan pencetus isyarat perdagangan.
Ambil strategi untuk masa hadapan OKX sebagai contoh.
// 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)
}
}
Ujian belakang MyLanguage:
Kod strategi MyLanguage:
MA5^^MA(C,5);
MA15^^MA(C,15);
CROSSUP(MA5,MA15),BPK;
CROSSDOWN(MA5,MA15),SPK;
Pertama, isi bahagian pemerolehan ticker dan pengiraan penunjuk untuk kod sampel yang boleh digunakan semula:
// 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]
Seperti yang anda lihat, strategi EMA berganda adalah sangat mudah.records
, dan kemudian gunakan fungsi EMATA.MA
daripadaTA function library
untuk mengira 5-hari EMA dan 15-hari EMA (seperti yang kita boleh lihat dalam antara muka backtest, tempoh K-garis ditetapkan kepada harian K-garis, jadiTA.MA(records, 5)
adalah untuk mengira EMA 5 hari,TA.MA(records, 15)
adalah untuk mengira EMA 15 hari).
Kemudian mendapatkan titik penutupma5_curr
(nilai penunjuk), titik ketiga terakhirma5_pre
(nilai petunjuk) data petunjukma5
, dan sama juga untukma15
Kemudian kita boleh menggunakan data penunjuk ini untuk menilai Golden Cross dan Bearish Crossover, seperti yang ditunjukkan dalam gambar:
Setiap kali keadaan seperti itu terbentuk, ia adalah Golden Cross atau Bearish Crossover yang pasti.
Kemudian bahagian menilai isyarat boleh ditulis seperti berikut:
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
}
Dengan cara ini, pemindahan OK. Ujian balik strategi JavaScript Konfigurasi pengujian balik:
Hasil ujian semula:
Ujian balik MyLanguage
Ia dapat dilihat bahawa hasil backtest hampir sama. Dengan cara ini, jika anda ingin terus menambah fungsi interaktif, pemprosesan data (seperti sintesis K-line), dan paparan carta tersuai kepada strategi, anda boleh mencapai ini.
Jika anda berminat, sila cuba.