हाल ही में, अपने दोस्तों के साथ रणनीतियों के बारे में बात करते हुए, मुझे पता चला कि MyLanguage में लिखी गई कई रणनीतियों में लचीलापन का सामना करना पड़ता है। कई मामलों में, मानक K-लाइन अवधि का उपयोग करना आवश्यक है जो सिस्टम द्वारा प्रदान नहीं की जाती है। उदाहरण के लिए, अधिकतम आवश्यकता 4 घंटे के लिए K-लाइन का उपयोग करना है। इस समस्या को एक लेख में हल किया गया है। यदि आप रुचि रखते हैं, तो कृपया एक नज़र डालेंःलिंकहालाँकि, MyLanguage रणनीति में, MyLanguage की उच्च encapsulation सुविधा के कारण, यह अपने आप में डेटा को संसाधित करने के लिए लचीला नहीं है। इस समय, रणनीति विचार को अन्य भाषाओं में प्रत्यारोपित करना आवश्यक है।
यह ट्रेंड रणनीति प्रत्यारोपण के लिए बहुत सरल है. हम एक नमूना कोड का उपयोग करने के लिए कोड के डेटा गणना भाग है कि रणनीति ड्राइव में भरने के लिए, और व्यापार संकेत ट्रिगर शर्तों में भरने के लिए कर सकते हैं.
एक उदाहरण के रूप में ओकेएक्स वायदा के लिए रणनीति लें।
// 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)
}
}
MyLanguage बैकटेस्टः
MyLanguage रणनीति कोडः
MA5^^MA(C,5);
MA15^^MA(C,15);
CROSSUP(MA5,MA15),BPK;
CROSSDOWN(MA5,MA15),SPK;
सबसे पहले, पुनः प्रयोज्य नमूना कोड के लिए टिकर अधिग्रहण और संकेतक गणना भागों को भरेंः
// 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]
जैसा कि आप देख सकते हैं, डबल ईएमए रणनीति बहुत सरल है. पहले, के-लाइन डेटा प्राप्तrecords
, और फिर ईएमए फ़ंक्शन का उपयोग करेंTA.MA
काTA function library
5-दिवसीय ईएमए और 15-दिवसीय ईएमए की गणना करने के लिए (जैसा कि हम बैकटेस्ट इंटरफ़ेस में देख सकते हैं, के-लाइन अवधि दैनिक के-लाइन पर सेट है, इसलिएTA.MA(records, 5)
पांच दिवसीय ईएमए की गणना करना है।TA.MA(records, 15)
15 दिवसीय ईएमए की गणना करना है) ।
फिर अंतिम बिंदु प्राप्त करेंma5_curr
(संकेतक मूल्य), अंतिम तीसरा बिंदुma5_pre
सूचक डेटा का (सूचक मूल्य)ma5
, और उसी के लिएma15
फिर हम इन संकेतक डेटा का उपयोग कर सकते हैं स्वर्ण क्रॉस और मंदी क्रॉसओवर का न्याय करने के लिए, जैसा कि चित्र में दिखाया गया हैः
जब भी ऐसी स्थिति बनती है, यह निश्चित रूप से स्वर्ण क्रॉस या मंदी क्रॉसओवर होती है।
फिर संकेत का न्याय करने का भाग इस प्रकार लिखा जा सकता हैः
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
}
इस तरह, प्रत्यारोपण ठीक है. हम बैकटेस्ट कर सकते हैंः जावास्क्रिप्ट रणनीति का बैकटेस्टिंग बैकटेस्टिंग कॉन्फ़िगरेशनः
बैकटेस्टिंग का परिणाम:
MyLanguage का बैकटेस्टिंग
यह देखा जा सकता है कि बैकटेस्ट के परिणाम लगभग समान हैं। इस तरह, यदि आप रणनीति में इंटरैक्टिव फ़ंक्शन, डेटा प्रोसेसिंग (जैसे कि के-लाइन संश्लेषण), और अनुकूलित चार्ट डिस्प्ले जोड़ना जारी रखना चाहते हैं, तो आप इसे प्राप्त कर सकते हैं।
यदि आप रुचि रखते हैं, तो कृपया प्रयास करें।