ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

商品期货资金管理策略(教学)

2021-12-20 12:01:50  阅读:216  来源: 互联网

标签:longPos exchange 管理策略 orders var amount 期货 教学 symbol


商品期货资金管理策略(教学)

分享一个用于商品期货震荡行情的策略,策略原理十分简单。类似于网格策略,适用于震荡行情。策略参数不多,非常适合入门学习策略设计。当然小编会把注释在策略代码上写的满满的,方便各位读者大佬阅读。

策略逻辑十分简单,所以策略代码也并不多。在未持仓的状态下策略会基于当前价格向上、向下一定距离挂卖出(开空)、买入(开多)单。当持仓时基于当前价格一定距离挂加仓单、基于持仓均价一定距离挂平仓单。

逻辑流程图

策略代码(附带注释)

/*backtest
start: 2021-07-01 09:00:00
end: 2021-12-14 15:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/

// 全局变量
// 每个策略都自带「商品期货交易类库」,$.NewPositionManager()接口函数创建的对象p,实现了一些方法方便获取持仓、下单等,可以参看API文档上模板类库概念的介绍:https://www.fmz.cn/api#模板类库
var p = $.NewPositionManager()      
var n = 1                           // 可调整的系数,影响挂单价格

// 从挂单数组中找出指定的symbol值代表的合约挂单(未成交的订单)信息,例如symbol为rb2201,即找出所有rb2201合约的挂单
function GetOrders(symbol, orders) {
    var ret = []
    // 遍历orders
    for (var i = 0 ; i < orders.length ; i++) {
        if (orders[i].ContractType == symbol) {
            // 发现订单的合约代码与symbol的值相等,即放入ret数组
            ret.push(orders[i])
        }
    }
    // 返回ret数组
    return ret 
}

// 撤销指定的合约代码为symbol的所有挂单(未成交的订单)
function CancelOrders(symbol, orders) {
    // 遍历orders
    for (var i = 0 ; i < orders.length ; i++) {
        if (orders[i].ContractType == symbol) {
            // 撤销订单
            exchange.CancelOrder(orders[i].Id, orders[i])
            Sleep(500)
        }
    }
}

// 下单函数,distance为下单方向。price为下单价格。amount为下单数量(合约张数)
function trade(distance, price, amount) {
    var tradeFunc = null 
    // 根据参数distance给tradeFunc赋值具体的下单函数引用
    if (distance == "buy") {
        tradeFunc = exchange.Buy
    } else if (distance == "sell") {
        tradeFunc = exchange.Sell
    } else if (distance == "closebuy") {
        tradeFunc = exchange.Sell
    } else {
        tradeFunc = exchange.Buy
    }
    // 设置下单方向
    exchange.SetDirection(distance)
    // 执行下单函数并返回
    return tradeFunc(price, amount)
}

// 开多头仓位
function openLong(price, amount) {
    return trade("buy", price, amount)
}

// 开空头仓位
function openShort(price, amount) {
    return trade("sell", price, amount)
}

// 平多头仓位
function coverLong(price, amount, pos) {
    var direction = pos.Type == PD_LONG ? "closebuy_today" : "closebuy"
    return trade("closebuy", price, amount)
}

// 平空头仓位
function coverShort(price, amount, pos) {
    var direction = pos.Type == PD_LONG ? "closebuy_today" : "closebuy"
    return trade("closesell", price, amount)
}

// 策略主逻辑
function onTick() {
    // 首先设置当前操作的合约为symbol,如果symbol的值为rb2201,即当前行情、交易等都是操作rb2201合约
    var info = exchange.SetContractType(symbol)
    if (!info) {
        // 如果设置、订阅合约失败,直接返回
        return 
    }
    
    // 获取K线数据,用于策略画图
    var r = exchange.GetRecords()
    if (!r) {
        // K线数据获取失败,直接返回
        return 
    }
    $.PlotRecords(r, symbol)    // 使用「画线类库」模板画图,画线类库可以在FMZ平台策略广场搜索、复制到自己的策略库,使用
    // 获取当前所有挂单
    var allOrders = exchange.GetOrders()
    if (!allOrders) {
        // 获取失败直接返回
        return 
    }
    var orders = GetOrders(symbol, allOrders)    // 使用上面实现的GetOrders函数筛选出合约为symbol的值的挂单
    
    // 检测挂单
    var buyOrder = null             // 买入的订单
    var sellOrder = null            // 卖出的订单
    if (orders.length == 2) {       // 当symbol的值的合约,挂单数量是2时
        for (var i = 0 ; i < orders.length ; i++) {      // 遍历orders查找出买单、卖单
            if (orders[i].Type == ORDER_TYPE_BUY) {
                buyOrder = orders[i]
            } else if (orders[i].Type == ORDER_TYPE_SELL) {
                sellOrder = orders[i]
            }
        }
        if (!buyOrder || !sellOrder) {        // 买单、卖单有任意一个不存在时(成交了),撤销其它挂单,返回
            CancelOrders(symbol, GetOrders(symbol, _C(exchange.GetOrders)))
            return 
        }
    } else if (orders.length == 1) {          // 当挂单只有一个时,撤销所有挂单,返回
        CancelOrders(symbol, GetOrders(symbol, _C(exchange.GetOrders)))
        return 
    }
    
    // 获取当前行情数据ticker
    var ticker = exchange.GetTicker()
    if (!ticker) {
        // 获取失败,直接返回
        return 
    }
    
    // 获取当前持仓
    var pos = exchange.GetPosition()
    if (!pos) {
        // 获取失败时直接返回
        return 
    }
    var longPos = p.GetPosition(symbol, PD_LONG, pos)      // 筛选出 多头持仓数据
    var shortPos = p.GetPosition(symbol, PD_SHORT, pos)    // 筛选出 空头持仓数据

    var sellId = null   // 用于记录卖单订单ID
    var buyId = null    // 用于记录买单订单ID
    
    if (longPos && shortPos) {             // 同时持有多空仓位
        throw "同时持有多空仓位"             // 同时有多空持仓为异常情况,抛出错误,停止策略
    } else if (orders.length == 0 && !longPos && !shortPos) {    // 无持仓,挂开仓的买卖单,等待成交
        buyId = openLong(parseInt(ticker.Last - openTarget * n - info.PriceTick), amount)  // 下单,开多 
        $.PlotHLine(parseInt(ticker.Last - openTarget * n - info.PriceTick), "buy", "red") // 在图表上标记出水平线,表示挂单位置
        sellId = openShort(parseInt(ticker.Last + openTarget * n + info.PriceTick), amount)     // 下单,开空
        $.PlotHLine(parseInt(ticker.Last + openTarget * n + info.PriceTick), "sell", "green")   // 在图表上标记水平线,表示挂单位置
    } else if (orders.length == 0 && longPos && !shortPos) {     // 只持有多头持仓
        buyId = openLong(parseInt(ticker.Last - openTarget * n - info.PriceTick), amount)       // 下单,开多,加仓
        $.PlotHLine(parseInt(ticker.Last - openTarget * n - info.PriceTick), "buy", "red")
        sellId = coverLong(parseInt(longPos.Price + closeTarget * Math.min(amount / longPos.Amount, 1) + info.PriceTick), longPos.Amount, longPos)    // 下单,平多仓
        $.PlotHLine(parseInt(longPos.Price + closeTarget * Math.min(amount / longPos.Amount, 1) + info.PriceTick), "sell", "green")
    } else if (orders.length == 0 && !longPos && shortPos) {     // 只持有空头持仓
        buyId = coverShort(parseInt(shortPos.Price - closeTarget * Math.min(amount / shortPos.Amount, 1) - info.PriceTick), shortPos.Amount, shortPos)     // 下单,平空仓
        $.PlotHLine(parseInt(shortPos.Price - closeTarget * Math.min(amount / shortPos.Amount, 1) - info.PriceTick), "buy", "red")
        sellId = openShort(parseInt(ticker.Last + openTarget * n + info.PriceTick), amount)    // 下单,开空,加仓
        $.PlotHLine(parseInt(ticker.Last + openTarget * n + info.PriceTick), "sell", "green")
    }
    
    if (orders.length == 0 && (!sellId || !buyId)) {    // 有任意挂单失败,撤销所有挂单,直接返回
        CancelOrders(symbol, GetOrders(symbol, _C(exchange.GetOrders)))
        return 
    }
    
    // 用于显示,状态栏持仓表格
    var tblPos = {
        "type" : "table",
        "title" : "持仓",
        "cols" : ["持仓品种", "数量", "价格", "方向", "浮动盈亏"],
        "rows" : []
    }
    // 写入数据
    if (longPos) {
        tblPos.rows.push([longPos.ContractType, longPos.Amount, longPos.Price, longPos.Type == PD_LONG ? "多" : "空", longPos.Profit])
    }
    if (shortPos) {
        tblPos.rows.push([shortPos.ContractType, shortPos.Amount, shortPos.Price, shortPos.Type == PD_LONG ? "多" : "空", shortPos.Profit])
    }
    
    // 用于显示状态栏挂单表格
    var tblOrders = {
        "type" : "table",
        "title" : "挂单",
        "cols" : ["订单品种", "数量", "价格", "方向"],
        "rows" : []
    }
    // 写入数据
    if (buyOrder) {
        tblOrders.rows.push([buyOrder.ContractType, buyOrder.Amount, buyOrder.Price, buyOrder.Type == ORDER_TYPE_BUY ? "买" : "卖"])
    }
    if (sellOrder) {
        tblOrders.rows.push([sellOrder.ContractType, sellOrder.Amount, sellOrder.Price, sellOrder.Type == ORDER_TYPE_BUY ? "买" : "卖"])
    }    

    // 获取账户资产信息
    var acc = exchange.GetAccount()
    if (!acc) {
        return 
    }
    var tblAccount = $.AccountToTable(exchange.GetRawJSON(), "资金信息")   // 使用商品期货交易类库的模板接口函数$.AccountToTable返回一个表格结构,用于在状态栏上显示资产信息表格
    
    // 返回这些tbl结构的数组
    return [tblPos, tblOrders, tblAccount]
}

function main() {
    var msg = null    // 用于接收表示连接状态的字符串
    var tbls = null   // 用于接收tbl结构数组
    while (true) {
        if (exchange.IO("status")) {      // 判断是否和期货公司前置机连接
            if ($.IsTrading(symbol)) {    // 判断合约代码为symbol值的合约,当前是否是交易时段
                var ret = onTick()        // 执行策略主逻辑
                if (ret) {                // 如果返回了表格数据,而不是空
                    tbls = ret            // 更新tbls
                }
                msg = "已连接"             // 更新msg
            }            
        } else {
            msg = "未连接"                 // 更新msg
        }
        // 使用LogStatus在FMZ平台策略页面,状态栏上显示,时间、连接状态、表格
        LogStatus("时间:", _D(), "连接状态:", msg, "\n", "`" + JSON.stringify(tbls) + "`")
        Sleep(5000)    // 每次循环,暂停5000毫秒即5秒,该策略不用频繁检测,所以设置5000毫秒
    }
}

回测设置

策略地址:https://www.fmz.cn/strategy/335378

策略为教学策略,学习策略设计为主,实盘慎用,策略公开可以自行优化、修改。

标签:longPos,exchange,管理策略,orders,var,amount,期货,教学,symbol
来源: https://www.cnblogs.com/fmz-quant/p/15710315.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有