[TOC]
FMZ is a quantitative trading platform, mainly to serve the programmatic traders. But it also provides a basic trading terminal, although the functionality is simple, sometimes it can also be very useful, such as the exchange is busy and can not be opened, but the API can still work, at which time you can withdraw, place orders, view the current account, etc. In order to improve the experience of the trading terminal, plug-in functions are now added. Sometimes we need a small function to assist trading, such as staircase hanging iceberg assignment, one-key hedging, one-key placement, etc.
Plug-ins run in two modes, instant and background run. Background run is equivalent to creating a bot (normal charge). The principle of instant run is the same as that of the debugger: it is executed by the host that sends a piece of code to the transaction terminal page, and it supports return charts and tables (debugger is currently also upgraded), the same can be executed in only 5 minutes, without charge, without language limitations.
When writing a policy, it is necessary to select the policy type as a plugin.The result of the plugin's main function return will pop up at the end of the run, supporting strings, diagrams and tables. Since the plugin execution cannot be seen in the log, the plugin's execution result return can be returned.
If you search directly in the search box, you will find a list of the most popular search engines in the world.Note that only the transaction plug-in type policy can be run, then click Add. Public plugins can be found at Strategy Square:https://www.fmz.com/square/21/1
Clicking on the policy will enter the parameter settings interface, if there are no parameters, the transaction terminal will run directly, the selected host, transaction pair, K line cycle is the default corresponding parameter. Clicking on the execution policy will start the execution, and the plugin will not display the log.
Clicking on the display location stops the plug-in, which stops all plug-ins because all plug-ins are executed in a debug tool process.
Plugins can execute a period of time of code, can execute some simple operations, many times manual operations that require repeated execution of operations can be implemented with plugins, easy to trade.
Futures cross-period hedging is a very common strategy, since the frequency is not very high, many people will operate manually, requiring one contract to do more, one contract to empty, and also analyze the movement of the spread. Using a plug-in at the trading terminal will save you energy.
The first thing to do is to introduce a cross-period pricing plug-in:
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
}
Click on the link below to see the most recent cross-period spread and the source code copy address of the plugin:https://www.fmz.com/strategy/187755
With the difference analysis, finds the difference is converging, is a do-nothing quarter contract, do-multi-week opportunity, which can be used with a key hedging plug-in, click, automatically help you to do-nothing quarter, faster than the manual operation. The implementation principle of the strategy is to slide the price open the same number of positions, can run several times, slowly reach the position you need, avoid impacting the market, you can change the default parameters, reach a faster speed.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())
}
Waiting for the spread to converge, you need a levelling, you can run a one-button levelling plugin, the fastest speed levelling.
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)
}
}
}
}
The most common is Ice Mountain commissioning, to break up the large file into small files, although it can be run as a robot, but 5 minutes of plug-in is actually enough. Ice Mountain commissioning has two types, one is to eat a single, one is to hang a single, if there is a fee discount, you can choose to hang a single, or execution time is longer.
The following code is for Iceberg to buy the source code of the plugin:https://www.fmz.com/strategy/191771◦ Selling the source code: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
}
}
}
Holding the buy or sell position is also a way to move slowly, with less impact on the market. This strategy has some improvements, such as manually changing the minimum volume or precision of the trade. I'm going to buy it.https://www.fmz.com/strategy/191582It was sold: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)
}
}
Sometimes, in order to sell a better shipping price or to wait for a pending order to be leaked, multiple orders can be hung at a certain interval. This plugin can also be used for futures pending orders. Source copy address: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'
}
Commonly used futures trading software often has many advanced pending order features, such as pending stop loss order, pending condition list, etc., which can be conveniently written into a plugin.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)
}
}
After seeing so many small features, you should have your own ideas, maybe write a plugin to facilitate your own manual transactions.
shiyimjjcnWhat is the reason for reporting errors? Error: Futures_OP 0: 400: {"error_message":"Open orders exist","code":35017,"error_code":"35017","message":"Open orders exist"} Buy ((5000, 0.1): 400: {"error_message":"order_size error","result":"true","error_code":"35063","order_id":"-1"}
The grassCheck the documentation of the exchange or consult the exchange's customer service