[TOC]

En tant que plateforme de trading quantitative, FMZ est principalement conçue pour servir les traders programmatiques. Mais il fournit également un terminal de trading de base. Bien que la fonction soit simple, elle peut parfois être très utile. Par exemple, si la bourse est occupée et ne peut pas être ouverte, mais que l’API peut toujours fonctionner, vous pouvez utiliser le terminal pour annuler les commandes , passer des commandes et consulter les comptes de devis, etc. Afin d’améliorer l’expérience du terminal de trading, une fonctionnalité de plug-in a été ajoutée. Parfois, nous avons besoin d’une petite fonction pour faciliter le trading, comme les ordres en attente, les ordres iceberg, la couverture en un clic, la clôture en un clic, etc. Nous n’avons pas vraiment besoin de consulter le journal d’exécution. C’est un peu fastidieux pour créer un nouveau robot. Cliquez simplement sur le plug-in dans le terminal. , vous pouvez immédiatement réaliser les fonctions correspondantes, ce qui peut grandement faciliter le trading manuel. L’emplacement du plugin est le suivant :

Il existe deux modes de fonctionnement du plug-in : le fonctionnement immédiat et le fonctionnement en arrière-plan. L’exécution en arrière-plan équivaut à la création d’un robot (des frais normaux s’appliquent). Le principe de fonctionnement immédiat est le même que celui de l’outil de débogage : envoyer un morceau de code au dépositaire de la page du terminal de trading pour exécution, et prendre en charge le retour de graphiques et de tableaux (l’outil de débogage est actuellement également mis à niveau pour prendre en charge cela ). De même, il ne peut être exécuté que pendant 5 minutes, gratuitement et dans un nombre illimité de langues. Les plugins avec des temps d’exécution très courts peuvent utiliser le mode d’exécution immédiate, tandis que les stratégies complexes qui nécessitent beaucoup de temps pour s’exécuter nécessitent toujours l’exécution de robots.
Lors de la rédaction d’une politique, vous devez sélectionner le type de politique en tant que plug-in. Le résultat de la fonction principale du plugin apparaîtra dans le terminal après l’exécution, prenant en charge les chaînes, les dessins et les tableaux. Étant donné que les journaux ne peuvent pas être vus pendant l’exécution du plugin, le résultat de l’exécution du plugin peut être renvoyé.
Recherchez directement dans la zone de recherche comme indiqué.Notez que seules les stratégies de type plugin de trading peuvent être exécutées, puis cliquez sur Ajouter. Les plugins publics sont disponibles sur Strategy Square : https://www.fmz.com/square/21/1

Cliquez sur la stratégie pour accéder à l’interface de paramétrage. S’il n’y a pas de paramètres, l’exécution se fera directement. Le dépositaire, la paire de trading et la période K-line sélectionnés par le terminal de trading sont les paramètres correspondants par défaut. Cliquez sur la politique d’exécution pour démarrer l’exécution et sélectionnez le mode « Exécuter maintenant » (vous pouvez vous souvenir du mode d’exécution par défaut). Le plugin n’affichera pas les journaux.

Cliquez sur l’icône pour arrêter le plug-in. Étant donné que tous les plug-ins sont exécutés dans un processus d’outil de débogage, tous les plug-ins seront arrêtés.

Les plugins peuvent exécuter du code pendant une période donnée et effectuer certaines opérations simples. Souvent, les opérations qui doivent être répétées manuellement peuvent être implémentées à l’aide de plugins, ce qui rend les transactions plus pratiques. Ce qui suit le présentera avec des exemples spécifiques, et le code source fourni peut être utilisé comme référence pour personnaliser votre propre stratégie.
La couverture inter-périodes des contrats à terme est une stratégie très courante. Comme la fréquence n’est pas très élevée, de nombreuses personnes l’utilisent manuellement, en demandant à un contrat de passer à l’achat et à un contrat de passer à la vente, et elles peuvent ainsi analyser la tendance de la différence de prix. L’utilisation de plugins dans votre terminal de trading vous fera économiser de l’énergie.
La première chose que je souhaite présenter est le plug-in de différence de prix entre périodes :
var chart = {
__isStock: true,
title : { text : '差价分析图'},
xAxis: { type: 'datetime'},
yAxis : {
title: {text: '差价'},
opposite: false,
},
series : [
{name : "diff", data : []},
]
}
function main() {
exchange.SetContractType('quarter')
var recordsA = exchange.GetRecords(PERIOD_M5) //周期可以自行定制
exchange.SetContractType('this_week')
var recordsB = exchange.GetRecords(PERIOD_M5)
for(var i=0;i<Math.min(recordsA.length,recordsB.length);i++){
var diff = recordsA[recordsA.length-Math.min(recordsA.length,recordsB.length)+i].Close - recordsB[recordsB.length-Math.min(recordsA.length,recordsB.length)+i].Close
chart.series[0].data.push([recordsA[recordsA.length-Math.min(recordsA.length,recordsB.length)+i].Time, diff])
}
return chart
}
En un clic, vous pouvez voir en un coup d’œil les écarts inter-périodes récents. Adresse de copie du code source du plugin : https://www.fmz.com/strategy/187755

Avec l’analyse du spread, vous constatez que le spread converge, ce qui constitue une opportunité de vendre à découvert le contrat trimestriel et d’acheter à long terme la semaine en cours. À ce stade, vous pouvez utiliser le plug-in de couverture en un clic. En un seul clic, il sera vous aide automatiquement à vendre à découvert le contrat trimestriel et à acheter la semaine en cours, ce qui est plus rapide que l’opération manuelle. Un bon nombre. Le principe de mise en œuvre de la stratégie consiste à ouvrir le même nombre de positions avec glissement. Vous pouvez l’exécuter plusieurs fois pour atteindre lentement la position requise et éviter d’impacter le marché. Vous pouvez modifier les paramètres par défaut pour passer des commandes plus rapidement. Adresse de la copie de la stratégie : https://www.fmz.com/strategy/191348
function main(){
exchange.SetContractType(Reverse ? Contract_B : Contract_A)
var ticker_A = exchange.GetTicker()
if(!ticker_A){return 'Unable to get quotes'}
exchange.SetDirection('buy')
var id_A = exchange.Buy(ticker_A.Sell+Slip, Amount)
exchange.SetContractType(Reverse ? Contract_B : Contract_A)
var ticker_B = exchange.GetTicker()
if(!ticker_B){return 'Unable to get quotes'}
exchange.SetDirection('sell')
var id_B = exchange.Sell(ticker_B.Buy-Slip, Amount)
if(id_A){
exchange.SetContractType(Reverse ? Contract_B : Contract_A)
exchange.CancelOrder(id_A)
}
if(id_B){
exchange.SetContractType(Reverse ? Contract_B : Contract_A)
exchange.CancelOrder(id_B)
}
return 'Position: ' + JSON.stringify(exchange.GetPosition())
}
En attendant que la différence de prix converge, si vous devez fermer la position, vous pouvez exécuter le plug-in de fermeture en un clic pour fermer la position à la vitesse la plus rapide.
function main(){
while(ture){
var pos = exchange.GetPosition()
var ticker = exchange.GetTicekr()
if(!ticker){return '无法获取ticker'}
if(!pos || pos.length == 0 ){return '已无持仓'}
for(var i=0;i<pos.length;i++){
if(pos[i].Type == PD_LONG){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closebuy')
exchange.Sell(ticker.Buy, pos[i].Amount - pos[i].FrozenAmount)
}
if(pos[i].Type == PD_SHORT){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closesell')
exchange.Buy(ticker.Sell, pos[i].Amount - pos[i].FrozenAmount)
}
}
var orders = exchange.Getorders()
Sleep(500)
for(var j=0;j<orders.length;j++){
if(orders[i].Status == ORDER_STATE_PENDING){
exchange.CancelOrder(orders[i].Id)
}
}
}
}
Le plus courant est l’ordre iceberg, qui divise les grosses commandes en petites commandes. Bien qu’il puisse être exécuté comme un robot, un plug-in de 5 minutes suffit en réalité. Il existe deux types d’ordres iceberg, l’un consiste à prendre la commande et l’autre à la passer. S’il existe une réduction sur les frais de traitement, vous pouvez choisir de passer la commande, ce qui signifie que le temps d’exécution sera plus long.
Le code suivant est le code source du plug-in d’achat d’ordres Iceberg : https://www.fmz.com/strategy/191771. Vendre le code source : https://www.fmz.com/strategy/191772
function main(){
var initAccount = _C(exchange.GetAccount)
while(true){
var account = _C(exchange.GetAccount)
var dealAmount = account.Stocks - initAccount.Stocks
var ticker = _C(exchange.GetTicker)
if(BUYAMOUNT - dealAmount >= BUYSIZE){
var id = exchange.Buy(ticker.Sell, BUYSIZE)
Sleep(INTERVAL*1000)
if(id){
exchange.CancelOrder(id) // May cause error log when the order is completed, which is all right.
}else{
throw 'buy error'
}
}else{
account = _C(exchange.GetAccount)
var avgCost = (initAccount.Balance - account.Balance)/(account.Stocks - initAccount.Stocks)
return 'Iceberg order to buy is done, avg cost is '+avgCost
}
}
}
Le fait d’occuper systématiquement le prix d’achat ou de vente est également un moyen d’expédier lentement les marchandises, ce qui a un impact relativement faible sur le marché. Il existe encore quelques points à améliorer dans cette stratégie. Vous pouvez modifier manuellement le volume minimum de transaction ou la précision. Acheter : https://www.fmz.com/strategy/191582 Vendre : https://www.fmz.com/strategy/191730
function GetPrecision(){
var precision = {price:0, amount:0}
var depth = exchange.GetDepth()
for(var i=0;i<exchange.GetDepth().Asks.length;i++){
var amountPrecision = exchange.GetDepth().Asks[i].Amount.toString().indexOf('.') > -1 ? exchange.GetDepth().Asks[i].Amount.toString().split('.')[1].length : 0
precision.amount = Math.max(precision.amount,amountPrecision)
var pricePrecision = exchange.GetDepth().Asks[i].Price.toString().indexOf('.') > -1 ? exchange.GetDepth().Asks[i].Price.toString().split('.')[1].length : 0
precision.price = Math.max(precision.price,pricePrecision)
}
return precision
}
function main(){
var initAccount = exchange.GetAccount()
if(!initAccount){return '无法获取账户信息'}
var precision = GetPrecision()
var buyPrice = 0
var lastId = 0
var done = false
while(true){
var account = _C(exchange.GetAccount)
var dealAmount = account.Stocks - initAccount.Stocks
var ticker = _C(exchange.GetTicker)
if(BuyAmount - dealAmount > 1/Math.pow(10,precision.amount) && ticker.Buy > buyPrice){
if(lastId){exchange.CancelOrder(lastId)}
var id = exchange.Buy(ticker.Buy, _N(BuyAmount - dealAmount,precision.amount))
if(id){
lastId = id
}else{
done = true
}
}
if(BuyAmount - dealAmount <= 1/Math.pow(10,precision.amount)){done = true}
if(done){
var avgCost = (initAccount.Balance - account.Balance)/dealAmount
return 'order is done, avg cost is ' + avgCost // including fee cost
}
Sleep(Intervel*1000)
}
}
Parfois, afin de vendre à un meilleur prix ou d’attendre une bonne affaire, vous pouvez passer plusieurs commandes à un certain intervalle. Ce plugin peut également être utilisé pour les commandes futures en attente. Adresse de copie du code source : https://www.fmz.com/strategy/190017
function main() {
var ticker = exchange.GetTicker()
if(!ticker){
return 'Unable to get price'
}
for(var i=0;i<N;i++){
if(Type == 0){
if(exchange.GetName().startsWith('Futures')){
exchange.SetDirection('buy')
}
exchange.Buy(Start_Price-i*Spread,Amount+i*Amount_Step)
}else if(Type == 1){
if(exchange.GetName().startsWith('Futures')){
exchange.SetDirection('sell')
}
exchange.Sell(Start_Price+i*Spread,Amount+i*Amount_Step)
}else if(Type == 2){
exchange.SetDirection('closesell')
exchange.Buy(Start_Price-i*Spread,Amount+i*Amount_Step)
}
else if(Type == 3){
exchange.SetDirection('closebuy')
exchange.Sell(Start_Price+i*Spread,Amount+i*Amount_Step)
}
Sleep(500)
}
return 'order complete'
}
Les logiciels de trading à terme couramment utilisés disposent souvent de nombreuses fonctions avancées de placement d’ordres, telles que le placement d’ordres stop-loss, le placement d’ordres conditionnels, etc., qui peuvent être facilement écrites dans des plug-ins. Voici un plug-in qui vous permet de fermer un ordre en attente immédiatement après son exécution. Copier l’adresse : https://www.fmz.com/strategy/187736
var buy = false
var trade_amount = 0
function main(){
while(true){
if(exchange.IO("status")){
exchange.SetContractType(Contract)
if(!buy){
buy = true
if(Direction == 0){
exchange.SetDirection('buy')
exchange.Buy(Open_Price, Amount)
}else{
exchange.SetDirection('sell')
exchange.Sell(Open_Price, Amount)
}
}
var pos = exchange.GetPosition()
if(pos && pos.length > 0){
for(var i=0;i<pos.length;i++){
if(pos[i].ContractType == Contract && pos[i].Type == Direction && pos[i].Amount-pos[i].FrozenAmount>0){
var cover_amount = math.min(Amount-trade_amount, pos[i].Amount-pos[i].FrozenAmount)
if(cover_amount >= 1){
trade_amount += cover_amount
if(Direction == 0){
exchange.SetDirection('closebuy_today')
exchange.Sell(Close_Price, cover_amount)
}else{
exchange.SetDirection('closesell_today')
exchange.Buy(Close_Price, cover_amount)
}
}
}
}
}
} else {
LogStatus(_D(), "未连接CTP !")
Sleep(10000)
}
if(trade_amount >= Amount){
Log('任务完成')
return
}
Sleep(1000)
}
}
Après avoir vu autant de petites fonctions, vous devriez avoir vos propres idées. Vous pouvez aussi les écrire dans des plug-ins pour faciliter votre trading manuel.