Teach you how to implement a commodity futures plan delegation tool

Keywords: less

When dealing with commodity futures, not all of them are fully automatic trading strategies. There are many semi-automatic and programmed trading tools to replace manual marking.Although this kind of tool is not a complete strategy, it is also based on the user's trading intent, and it is the simplest trading strategy to conduct transactions in a structured manner.Let's work together to implement a trading tool.

There may be a lot of demand for semi-automatic trading tools, we can simply sort out some requirements to achieve, for more advanced, complex requirements can be subsequently optimized and upgraded.

Commodity Futures Program Delegation Tool (Teaching)

  • Planning delegation:
    Develop delegated tasks, price lines set by policy parameters, number of single-handed, multi-empty directions, trigger methods, and determine tasks.

  • target profit
    After the planned entrusted order is completed, a planned profit stop task is created according to the set profit stop price.

  • Stop Loss
    After the planned Commission order is completed, a planned stop task is created based on the stop price set.

  • Stop Loss Backhand
    Develop backhand tasks when triggered based on stop-loss tasks.

With the above requirements, we can achieve the functions one by one. First of all, analyze that the stop-profit and stop-loss actions are established after the initial planned Commission order is completed, and then the actions are generated after the position is held. Therefore, stop-profit and stop-loss are based on the first planned Commission order is created after it is completed.Stop Loss Backhand is also based on actions that occur after the stop loss has been completed.

This is roughly the same process.

So here's the first question, how do we design to automatically create another successor task when one is completed?
The solution to this problem is very simple. FMZ Quantitative Trading Platform provides a powerful template class library, which can be easily solved with its own commodity futures trading class library.

Each policy is created with its own class library in the template bar. Check it to save the policy for reference.

Returning to our question of how to automatically create another pre-set task after one task has been completed, we can create transaction queue control objects using the $.NewTaskQueue() function in the Commodity Futures Trading Class Library.

Global variables defined in policies

// global variable
var _TaskQueue = []    // Task queue, data structure is an array.
var ENTRUST = 0        // Defined task type, ENTRUST represents planned delegation
var STOPLOSS = 1       // Delegate Stop Loss Delegation
var STOPPROFIT = 2     // Delegate profitability Commission
var BACKHAND = 3       // Delegate Backhand Delegation
var dictTaskType = ["Delegate Tasks", "Stop Loss Task", "Earnings Task", "Backhand Task"]     // Chinese reference for delegate types used to display these names in programs

var q = $.NewTaskQueue()   // Create queue control objects for commodity futures trading libraries.

How do I use this object q?It's simple, as follows.task.taskSymbol is the contract code for the current task, task.taskDirection is the transaction direction for the current task, and task.taskAmount is the number of orders placed for the current task.The last function(tradeTask, ret) {... is the callback function that solves our problem.This callback function can be triggered to execute after the current task is completed, so that we can easily write the creation of subsequent tasks in this callback function.

q.pushTask(exchange, task.taskSymbol, task.taskDirection, task.taskAmount, function(tradeTask, ret) {
    Log(tradeTask.desc, ret, "XX Delegated Completion")
    if (ret) {
        // Callback, create follow-up task
        // ...
        // ..
        // .
    }
})

Let's first look at the complete policy code:

// global variable
var _TaskQueue = []
var ENTRUST = 0
var STOPLOSS = 1
var STOPPROFIT = 2 
var BACKHAND = 3
var dictTaskType = ["Delegate Tasks", "Stop Loss Task", "Earnings Task", "Backhand Task"]

var q = $.NewTaskQueue()


function closeTask (taskType) {
    for (var i = 0; i < _TaskQueue.length; i++) {
        if (taskType == _TaskQueue[i].taskType) {
            _TaskQueue[i].taskFinished = true
            Log("Close Task:", dictTaskType[taskType])
        }
    }
}

// Task Processing Objects
function TaskQueueProcess () {
    // Get Quotes
    exchange.SetContractType(_EntrustSymbol)
    var ticker = _C(exchange.GetTicker)

    for (var i = 0; i < _TaskQueue.length; i++) {
        var task = _TaskQueue[i]
        if (task.taskFinished == false && task.taskType == ENTRUST && task.taskTrigger * ticker.Last >= task.taskTrigger * task.taskPrice) {
            q.pushTask(exchange, task.taskSymbol, task.taskDirection, task.taskAmount, function(tradeTask, ret) {
                Log(tradeTask.desc, ret, "Delegated Completion")
                if (ret) {
                    // Callback, create follow-up task
                    if (_EntrustStopLossPrice != -1) {     // Create Stop Loss Task
                        var newTask = {
                            taskType : STOPLOSS,
                            taskSymbol : task.taskSymbol,
                            taskPrice : _EntrustStopLossPrice, 
                            taskAmount : task.taskAmount,
                            taskDirection : task.taskDirection == "buy" ? "closebuy" : "closesell",                    
                            taskTrigger : -1,              // Below price trigger
                            taskFinished : false
                        }
                        _TaskQueue.push(newTask)
                        Log("Create Stop Loss Task", newTask, "#FF0000")
                    }
                    if (_EntrustStopProfitPrice != -1) {   // Create Earnings Task
                        var newTask = {
                            taskType : STOPPROFIT,
                            taskSymbol : task.taskSymbol,
                            taskPrice : _EntrustStopProfitPrice, 
                            taskAmount : task.taskAmount,
                            taskDirection : task.taskDirection == "buy" ? "closebuy" : "closesell",                    
                            taskTrigger : 1,               // Above Price Trigger
                            taskFinished : false
                        }
                        _TaskQueue.push(newTask)
                        Log("Create Earnings Task", newTask, "#FF0000")
                    }
                }
            })
            task.taskFinished = true
            break        
        } else if (task.taskFinished == false && task.taskType == STOPLOSS && ticker.Last * task.taskTrigger >= task.taskPrice * task.taskTrigger) {    
            q.pushTask(exchange, task.taskSymbol, task.taskDirection, task.taskAmount, function(tradeTask, ret) {
                Log(tradeTask.desc, ret, "Stop Loss Completion")
                // Close Earnings Task
                closeTask(STOPPROFIT)
                if (ret) {
                    // Callback, create follow-up task
                    if (_EntrustStopLossBackhandPrice != -1) {
                        var newTask = {
                            taskType : BACKHAND,
                            taskSymbol : task.taskSymbol,
                            taskPrice : _EntrustStopLossBackhandPrice, 
                            taskAmount : task.taskAmount,
                            taskDirection : task.taskDirection == "closebuy" ? "sell" : "buy",                    
                            taskTrigger : task.taskDirection == "closebuy" ? -1 : 1,   // Trigger when -1 is less than, trigger when 1 is greater
                            taskFinished : false
                        }
                        _TaskQueue.push(newTask)
                        Log("Create Backhand Task", newTask, "#FF0000")
                    }
                }
            })
            task.taskFinished = true
            break
        } else if (task.taskFinished == false && task.taskType == STOPPROFIT && ticker.Last * task.taskTrigger >= task.taskPrice * task.taskTrigger) {    
            q.pushTask(exchange, task.taskSymbol, task.taskDirection, task.taskAmount, function(tradeTask, ret) {
                Log(tradeTask.desc, ret, "Stop Profit Complete")
                // Close Stop Loss Task
                closeTask(STOPLOSS)
            })
            task.taskFinished = true
            break
        } else if (task.taskFinished == false && task.taskType == BACKHAND && ticker.Last * task.taskTrigger >= task.taskPrice * task.taskTrigger) {    
            q.pushTask(exchange, task.taskSymbol, task.taskDirection, task.taskAmount, function(tradeTask, ret) {
                Log(tradeTask.desc, ret, "Backhand Finish")
            })
            task.taskFinished = true
            break
        }
    }
    q.poll()
}

function main() {
    if (_IsRecovery) {
        recoveryData = _G("_TaskQueue")
        if (!recoveryData) {
            _TaskQueue = recoveryData
        } else {
            Log("No data available for recovery")
        }
    }

    // Generate tasks from parameters
    if (_EntrustSymbol == "null" || _EntrustPrice <= 0 || _EntrustAmount <= 0) {
        throw "There is no commission contract set up or the commission price is invalid or the number of commissions is invalid"
    } else {
        var task = {
            taskType : ENTRUST,
            taskSymbol : _EntrustSymbol,
            taskPrice : _EntrustPrice, 
            taskAmount : _EntrustAmount,
            taskDirection : _EntrustMode == 0 ? "buy" : "sell",                     
            taskTrigger : _EntrustTriggerType == 0 ? 1 : -1,                        
            taskFinished : false
        }

        Log("Notice that the delegate task is created", task, "#FF0000")
        _TaskQueue.push(task)
    }
    

    while (true) {
        if (exchange.IO("status")) {
            TaskQueueProcess()
            // Status bar display
            LogStatus(_D(), "Connected")
        } else {
            LogStatus(_D(), "Not connected")
        }
        Sleep(500)
    }
}

// Sweep the tail to cancel all hanging slips
function onexit(){
    Log("Policy Stop,Save data:", _TaskQueue)
    _G("_TaskQueue", _TaskQueue)
}

function onerror(){
    Log("Policy Abnormal Stop,Save data:", _TaskQueue)
    _G("_TaskQueue", _TaskQueue)
}

Looking at the policy code, in fact, the core of the function is TaskQueueProcess, in which the tasks stored in the _TaskQueue array are judged one by one, whether the task is effective or not, whether the current quotation conditions, combined with specific task parameters, meet our delegated trigger conditions.The trigger condition is met, then the q object of the template is used to execute the task, according to the pre-set callback function, when the task is completed, subsequent tasks are created to complete the delegation process.

Test Back:

When setting parameters:

Parameters default to invalid parameters, such as no delegation when Delegate Price is -1.Similarly, Stop Loss, Stop Profit and Backhand Price are also the same. Setting-1 does not enable this feature.You can see in the code:

Judging that a set parameter of -1 will not create subsequent tasks in the callback function.

Links to teaching strategies: https://www.fmz.com/strategy/175150

Strategies are for teaching purposes only and should be used with caution.

Posted by Pudgemeister on Mon, 24 Feb 2020 19:17:14 -0800