FMZ.COM, en tant que plateforme de trading quantitative, est principalement destinée à servir les traders programmatiques. Mais elle fournit également un terminal de trading de base. Bien que la fonction soit simple, elle peut parfois être utile. Par exemple, si l'échange est occupé et ne peut pas être exploité, mais l'API fonctionne toujours. À ce moment-là, vous pouvez retirer des ordres, passer des ordres et les afficher via le terminal. Afin d'améliorer l'expérience du terminal de trading, des plug-ins sont maintenant ajoutés.
Il existe deux modes d'opération du plug-in, opération immédiate et opération en arrière-plan. L'exécution en arrière-plan est équivalente à la création d'un robot (charges normales). Le principe de l'opération immédiate est le même que celui de l'outil de débogage: envoyer un morceau de code au docker 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), le même ne peut être exécuté que pendant 5 minutes, sans frais, sans restrictions Langue. Les plug-ins avec un temps d'exécution court peuvent utiliser le mode d'exécution immédiate, tandis que les stratégies complexes et à long terme doivent encore exécuter des robots.
Lorsque vous écrivez une stratégie, vous devez sélectionner le type de stratégie en tant que plug-in.main
fonctionreturn
de l'exécution du plug-in apparaîtra dans le terminal après l'opération est terminée, soutenant les chaînes, dessins et tables.return
le résultat de l'exécution du plug-in.
Cherchez directement dans la zone de recherche comme indiqué sur la figure. Notez que seules les stratégies de type plugin de trading peuvent être exécutées, puis cliquez sur Ajouter. Les plugins publics se trouvent dans Strategy Square:https://www.fmz.com/square/21/1
Cliquez sur la stratégie pour entrer dans l'interface de réglage des paramètres. S'il n'y a pas de paramètres, il s'exécutera directement. Le docker, la paire de négociation et la période de ligne K sélectionnés par le terminal de négociation sont les paramètres correspondants par défaut. Cliquez sur la stratégie d'exécution pour commencer l'exécution et sélectionnez le mode
Cliquez sur la position de l'icône pour arrêter le plug-in. Puisque 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 plug-ins peuvent exécuter du code pendant une période de temps et effectuer certaines opérations simples. Dans de nombreux cas, les opérations manuelles nécessitant des opérations répétées peuvent être implémentées avec des plug-ins pour faciliter les transactions.
Le trading de hedge intertemporel est une stratégie très courante. Parce que la fréquence n'est pas très élevée, beaucoup de gens l'opéreront manuellement. Il est nécessaire de faire un contrat long et un contrat court, il est donc préférable d'analyser la tendance de propagation. L'utilisation de plug-ins dans le terminal de trading vous permettra d'économiser de l'énergie.
La première introduction consiste à dessiner le plug-in de la différence de prix entre les périodes:
var chart = {
__isStock: true,
title : { text : 'Spread analysis chart'},
xAxis: { type: 'datetime'},
yAxis : {
title: {text: 'Spread'},
opposite: false,
},
series : [
{name : "diff", data : []},
]
}
function main() {
exchange.SetContractType('quarter')
var recordsA = exchange.GetRecords(PERIOD_M5) //Cycle can be customized
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
}
Cliquez une fois, la récente différence de prix entre les périodes est claire en un coup d'œil, l'adresse de copie du code source du plugin:https://www.fmz.com/strategy/187755
Avec l'analyse des spreads, on constate que le spread converge. C'est l'occasion de raccourcir le contrat trimestriel et d'aller long pour la semaine en cours. C'est l'occasion d'utiliser le plug-in de couverture en un clic, un clic vous aidera automatiquement à raccourcir le trimestriel et le long hebdomadaire, ce qui est plus rapide que l'opération manuelle. Le principe de mise en œuvre de la stratégie est d'ouvrir le même nombre de positions avec un prix glissant. Vous pouvez courir plusieurs fois de plus pour atteindre lentement votre position souhaitée afin d'éviter d'avoir un impact sur le marché. Vous pouvez modifier les paramètres par défaut pour passer des commandes plus rapidement. Adresse de 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 et que vous ayez besoin de fermer la position, vous pouvez exécuter le plugin de fermeture en un clic pour fermer la position le plus rapidement possible.
function main(){
while(ture){
var pos = exchange.GetPosition()
var ticker = exchange.GetTicekr()
if(!ticker){return 'Unable to get ticker'}
if(!pos || pos.length == 0 ){return 'No holding position'}
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 la commission de l'iceberg, qui divise les gros ordres en petits ordres. Bien qu'il puisse être exécuté comme un robot, un plug-in de 5 minutes est en fait suffisant. Il existe deux types d'ordres d'iceberg, l'un est de prendre des ordres et l'autre est en attente d'ordres. S'il y a un frais préférentiel, vous pouvez choisir les ordres en attente, ce qui signifie que le temps d'exécution est plus long.
Le code suivant est le code source du plug-in commandé par iceberg:https://www.fmz.com/strategy/191771À vendre: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
}
}
}
Il s'agit également d'une façon de lentement
À 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 'Unable to get account information'}
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 d'expédition ou d'attendre une commande en attente, plusieurs commandes peuvent être passées à un certain intervalle.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 de contrats à terme couramment utilisés ont souvent de nombreuses fonctions avancées d'ordre en attente, telles que les ordres d'arrêt-perte en attente, les ordres de condition en attente, etc., qui peuvent facilement être écrits sous forme de plug-ins. Voici un plugin pour fermer un ordre en attente immédiatement après la négociation de l'ordre en attente.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 is not connected!")
Sleep(10000)
}
if(trade_amount >= Amount){
Log('mission completed')
return
}
Sleep(1000)
}
}
Après avoir lu tant de petites fonctions, vous devriez également avoir vos propres idées.