FMZ.COM, como plataforma de negociación cuantitativa, es principalmente para servir a los comerciantes programáticos. Pero también proporciona un terminal de negociación básico. Aunque la función es simple, a veces puede ser útil. Por ejemplo, si el intercambio está ocupado y no se puede operar, pero la API todavía funciona. En este momento, puede retirar pedidos, realizar pedidos y verlos a través del terminal. Para mejorar la experiencia del terminal de negociación, ahora se agregan complementos. A veces, necesitamos una pequeña función para ayudar a la transacción, como pedidos pendientes de escalera, pedidos de iceberg, cobertura de un clic, posiciones de cierre de un clic necesarias y otras operaciones. No es necesario mirar la ejecución. Es un poco engorroso crear un nuevo robot. Simplemente haga clic en el plugin en el terminal, Las funciones correspondientes del plug-in se pueden realizar de inmediato, lo que puede facilitar enormemente las transacciones manualmente.
Hay dos modos de operación del plug-in, operación inmediata y operación en segundo plano. Ejecutar en segundo plano es equivalente a crear un robot (cargos normales). El principio de operación inmediata es el mismo que la herramienta de depuración: enviar un pedazo de código al docker de la página de la terminal de negociación para su ejecución, y soporte para devolver gráficos y tablas (la herramienta de depuración también está actualmente actualizada para soporte), lo mismo solo se puede ejecutar durante 5 minutos, sin cargos, sin restricciones Lenguaje. Los plug-ins con un corto tiempo de ejecución pueden usar el modo de ejecución inmediata, mientras que las estrategias complejas y de larga duración aún necesitan ejecutar robots.
Al escribir una estrategia, usted necesita seleccionar el tipo de estrategia como un plug-in.main
Funciónreturn
del plug-in aparecerá en el terminal después de que la operación haya terminado, soportando cadenas, dibujos y tablas.return
el resultado de la ejecución del plug-in.
Busque directamente en el cuadro de búsqueda como se muestra en la figura. Tenga en cuenta que solo se pueden ejecutar estrategias de tipo de complemento comercial, y luego haga clic en Agregar. Los plugins públicos se pueden encontrar en Strategy Square:https://www.fmz.com/square/21/1
Haga clic en la estrategia para ingresar a la interfaz de configuración de parámetros. Si no hay parámetros, se ejecutará directamente. El docker, el par de operaciones y el período de línea K seleccionados por la terminal de operaciones son los parámetros correspondientes por defecto. Haga clic en la estrategia de ejecución para iniciar la ejecución y seleccione el modo
Haga clic en la posición del icono para detener el plug-in.
Los plug-ins pueden ejecutar código durante un período de tiempo y realizar algunas operaciones simples. En muchos casos, las operaciones manuales que requieren operaciones repetidas se pueden implementar con plug-ins para facilitar las transacciones.
El comercio de hedge intertemporal de futuros es una estrategia muy común. Debido a que la frecuencia no es muy alta, muchas personas lo operarán manualmente. Es necesario hacer un contrato largo y un contrato corto, por lo que es mejor analizar la tendencia de propagación. El uso de plugins en la terminal de negociación ahorrará su energía.
La primera introducción es dibujar el complemento de la diferencia de precios interperíodo:
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
}
Haga clic una vez, la diferencia de precio entre períodos recientes es clara a simple vista, la dirección de copia del código fuente del plug-in:https://www.fmz.com/strategy/187755
Con el análisis de la propagación, se encuentra que la propagación está convergiendo. Es una oportunidad para acortar el contrato trimestral y ir largo para la semana actual. Esta es una oportunidad para usar el plug-in de cobertura de un solo clic, un clic te ayudará automáticamente a acortar el trimestral y el largo el semanal, lo que es más rápido que la operación manual. El principio de implementación de la estrategia es abrir el mismo número de posiciones con un precio deslizante. Puedes correr varias veces más para llegar lentamente a tu posición deseada para evitar afectar al mercado. Puedes cambiar los parámetros predeterminados para realizar pedidos más rápido. Dirección de copia de la estrategia: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())
}
Esperando a que la diferencia de precio converja y necesite cerrar la posición, puede ejecutar el complemento de cierre de un solo clic para cerrar la posición lo más rápido posible.
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)
}
}
}
}
El más común es la comisión del iceberg, que divide los pedidos grandes en pedidos pequeños. Aunque se puede ejecutar como un robot, un plug-in de 5 minutos es en realidad suficiente. Hay dos tipos de pedidos del iceberg, uno está tomando pedidos y el otro está pendiente de pedidos. Si hay una tarifa preferencial, puede elegir pedidos pendientes, lo que significa que el tiempo de ejecución es más largo.
El siguiente código es el código fuente del plug-in encargado por iceberg:https://www.fmz.com/strategy/191771Para la venta: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
}
}
}
También es una forma de lentamente
Comprar:https://www.fmz.com/strategy/191582
Se vende: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)
}
}
A veces, con el fin de vender un mejor
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'
}
El software de comercio de futuros comúnmente utilizado a menudo tiene muchas funciones avanzadas de órdenes pendientes, como órdenes pendientes de stop-loss, órdenes pendientes de condición, etc., que pueden escribirse fácilmente como plug-ins.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)
}
}
Después de leer tantas pequeñas funciones, también deberías tener tus propias ideas.