Récemment, en discutant avec des amis sur les stratégies, j'ai découvert qu'il y avait beaucoup de problèmes de flexibilité avec les stratégies de rédaction de my language. Dans de nombreux cas, il est nécessaire d'utiliser des cycles de lignes K standard fournis par des non-systèmes, par exemple, le plus souvent demandé est d'utiliser des lignes K de 4 heures. Ce problème a été résolu dans un article.Les liensMais le problème avec les stratégies my est que les données ne peuvent pas être traitées de manière flexible par les stratégies my, car elles sont hautement condensées.
Pour le portage de la stratégie de tendance, il est très simple d'utiliser un code d'exemple pour remplir une partie du code de calcul des données qui conduit à la stratégie, remplissant les conditions de déclenchement du signal de transaction.
Les stratégies utilisées pour les contrats à terme sur l'OKEX sont des exemples.
// 全局变量
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 // 记录持仓数量
var TradeInterval = 500 // 轮询间隔
var PriceTick = 1 // 价格一跳
var Symbol = "this_week"
function OnTick(){
// 驱动策略的行情处理部分
// 待填充...
// 交易信号触发处理部分
// 待填充...
// 执行交易逻辑
var pos = null
var price = null
var currBar = records[records.length - 1]
if(_State == OPENLONG){
pos = GetPosition(PD_LONG)
// 判断是不是 满足状态,如果满足 修改状态
if(pos[1] >= Amount){
_State = LONG
Amount = pos[1] // 更新实际量
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] // 更新实际量
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)
}
}
// 交易逻辑部分
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){ // 处理交易
if(Type == OPENLONG || Type == OPENSHORT){ // 处理开仓
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){ // 处理平仓
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() {
// 设置合约
exchange.SetContractType(Symbol)
while(1){
OnTick()
Sleep(1000)
}
}
Il y a aussi des gens qui ont été victimes de violences.
Le code stratégique de la langue Ma:
MA5^^MA(C,5);
MA15^^MA(C,15);
CROSSUP(MA5,MA15),BPK;
CROSSDOWN(MA5,MA15),SPK;
Tout d'abord, remplissez la section d'accès au marché et de calcul des indicateurs pour le code de l'exemple réutilisable:
// 驱动策略的行情处理部分
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]
Vous pouvez voir que la stratégie de la double ligne droite est très simple, il suffit d'obtenir les données de la ligne K.records
et utilisezTA函数库
La fonction homogène deTA.MA
On peut calculer la ligne moyenne de 5 jours, la ligne moyenne de 15 jours (vous pouvez voir sur l'interface de retouche que la période de la ligne K est définie par la ligne K du jour, doncTA.MA(records, 5)
Les chiffres sont calculés sur la moyenne de cinq jours.TA.MA(records, 15)
Il y a aussi des gens qui ont été victimes de violences.
et puis obtenirma5
Le deuxième point négatif de l'indicateurma5_curr
(valeur de l'indicateur), le troisième point du compteurma5_pre
Le nombre de personnes atteintes de cette maladie est en hausse.ma15
Les données de l'indicateur sont analogues. On peut ensuite utiliser ces données pour juger de la fourchette morte, comme le montre le graphique:Il y a une sorte de "forc à mort" qui se forme dès qu'il y a un tel état.
La partie qui juge le signal peut être écrite comme suit:
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
}
Il y a un problème avec le transfert de sang, et il est normal de le refaire: Réévaluation de la stratégie JavaScript Les paramètres de détection:
回测结果:
![img](/upload/asset/16baa65d35e034e06a58.png)
Mon langage est en train de changer
On peut voir les résultats de la retouche essentiellement les mêmes, ce qui est possible si l'on souhaite continuer à ajouter des fonctionnalités d'interaction pour les stratégies, ajouter du traitement de données (par exemple la synthèse de lignes K), ajouter des graphiques graphiques personnalisés.
Les élèves intéressés peuvent essayer.
Le petitEn apprentissage