Chiến lược lệch lạc

Tác giả:Giấc mơ nhỏ, Tạo: 2016-12-10 12:53:45, Cập nhật: 2016-12-10 12:57:30

Phương pháp Aberration để kiếm tiền từ xu hướng


  • Thông tin chi tiết

Nhiều người trong số các bạn chơi tương lai trực giác có thể hơi lạ với chiến lược Aberration, một hệ thống giao dịch huyền thoại được phát minh bởi Keith Fitschen vào năm 1986 với lợi nhuận hàng năm hơn 100%. Ông đã công bố hệ thống này trong tạp chí Future Truth của Mỹ vào năm 1993. Đây là một hệ thống giao dịch đường dài trung bình, thuộc chiến lược theo dõi xu hướng, nó hoạt động linh hoạt giữa 8 giống giống như ngũ cốc, thịt, kim loại, năng lượng, ngoại hối, tương lai chỉ số chứng khoán và thu được lợi nhuận bằng cách theo dõi xu hướng đường dài. Và vì nó giao dịch cùng một lúc trong nhiều thị trường không liên quan hoặc ít liên quan, do đó chỉ cần thu được lợi nhuận cao từ xu hướng trong một hoặc một vài thị trường, nó bù đắp cho những lỗ trong các thị trường bất ổn khác. Tần suất giao dịch của nó thường là giao dịch một giống 3-4 lần mỗi năm, 60% thời gian được giữ, trung bình mỗi giao dịch được giữ 60 ngày. Chiến lược mở sàn là: đầu tiên sử dụng đường trung bình di chuyển 35 ngày và chênh lệch tiêu chuẩn giá đóng cửa trong 35 ngày, tạo ra ba đường dẫn, khi giá đóng cửa của một Bar đi trên đường dẫn nhiều hơn khi đi trên đường dẫn, phía dưới đi trên đường dẫn trống, phía dưới đi qua đường dẫn trung bình nhiều hơn, phía trên đi qua đường dẫn trung bình và phía trên đi trên đường dẫn trung bình. Ý tưởng của chiến lược này rất đơn giản: sử dụng đường trung bình chuyển động và đường chuẩn khác biệt để đánh giá bất cứ lúc nào nếu đường đã được phá vỡ và bắt được xu hướng. Khi xu hướng dần suy yếu, đường trung tâm sẽ giảm dần, do đó, khi đường K đi ngược qua đường trung tâm, xu hướng có thể được coi là kết thúc và dừng ra khỏi đường trung tâm. Chiến lược này được phát hành sớm hơn và có thể không phù hợp với thị trường giao dịch hiện nay, nhưng ý tưởng nắm bắt xu hướng là lâu dài.

  • Thông tin chi tiết

    Hệ thống giao dịch Abberation được phát minh bởi Keith Fitschen vào năm 1986 và được công bố trên tạp chí Future Trust vào năm 1993. Điều thú vị là Keith không phải là một nhà giao dịch sinh ra, ông đã phục vụ trong Không quân Hoa Kỳ hơn 20 năm, chuyên về hệ thống định hướng vũ khí, có sức mạnh sâu sắc trong việc xử lý dữ liệu chuỗi thời gian. Hệ thống giao dịch Abberation được đặc trưng là theo xu hướng thụ động, sử dụng tín hiệu dài hạn, giao dịch 3-4 lần mỗi năm trên một loại, giữ thời gian hơn 60% tổng thời gian giao dịch và có thể phân bổ số lượng loại khác nhau theo quy mô vốn khác nhau. Nó thu được lợi nhuận lớn bằng cách giao dịch dài để nắm bắt xu hướng, đồng thời giao dịch trên nhiều thị trường không liên quan, khi một loại rút lui, loại khác có thể thu được lợi nhuận. Trong một năm, luôn có một hoặc nhiều loại có thể thu được lợi nhuận lớn. Cụ thể, hệ thống Abberation sử dụng 3 quỹ đạo để giao dịch. Đầu tiên, tính toán trung bình toán học MA (close) của giá đóng cửa N ngày trước đây của giống như MID, và tính toán MID + m theo quỹ đạo bằng cách đo lường sự biến động của giá đóng cửa theo tiêu chuẩn sai std (close).std ((close) và MID-m dưới đường raystd ((close) ); làm nhiều khi giá phá vỡ đường ray, hòa vốn khi giá quay trở lại đường ray; ngược lại, làm trống khi giá phá vỡ đường ray, hòa vốn khi giá quay trở lại đường ray.

  • Nguyên tắc chiến lược

    Aberration cũng là một hệ thống vượt qua kênh, nhưng đường lên xuống của nó được quyết định bởi tỷ lệ biến động.

    Một, xác định trên và dưới đường: Aberration bao gồm ba đường dẫn, trong đó đường trung tâm là đường trung bình di chuyển trong một chu kỳ nhất định (AveMa), đường đi lên và đi xuống là đường trung tâm dựa trên giá trị tiêu chuẩn nhất định (StdValue) cộng với giảm, tức là đường Brain mà chúng ta quen thuộc, hệ thống được xây dựng rất đơn giản và đẹp.

    Các quy trình tính toán cụ thể như sau: (1) Tính trung gian: AveMa=Average ((Close[1],Length); (2) tính toán sai tiêu chuẩn: StdValue = StandardDev ((Close[1],Length); (3) Đường tính toán: UpperBand=Avema+StdDevUpStdValue; (StdDevUp là tham số trên đường ray) (4) Tính theo đường ray: LowerBand=Avema-StdDevDnStdValue; (StdDevDn là tham số dưới đường ray)

    Điều kiện mua bán: Bước đầu: Giá đóng cửa vượt qua đường cao hơn để mở nhiều hơn, rơi ra đường trung tâm; Bước trống: Giá đóng cửa giảm xuống dưới đường ray làm việc trống, phá vỡ đường ray giữa.

  • Mã nguồn chiến lược

    • Khung chiến lược rõ ràng về logic, khả năng sử dụng nhiều lần
    • Có thể chỉnh sửa trong thời gian thực khi chạy trên đĩa thực qua các chức năng tương tác
    • Chạy ổn định, các chi tiết được xử lý hoàn hảo
    • Hỗ trợ nhiều loại hoạt động đồng thời, có thể kiểm soát số lượng mở riêng biệt
    • Tự động khôi phục tiến độ dựa trên vị trí khi khởi động lại
    • Có mô-đun điều khiển gió, hiển thị rủi ro, ngăn chặn thiệt hại trong thời gian thực
    • Thông báo WeChat dưới đây
    • Nếu bạn không muốn thuê máy chủ, bạn có thể sử dụng máy tính của riêng bạn hoặc máy tính xích miếng để chạy Windows, Linux, Mac, hoặc bạn có thể làm sạch bộ định tuyến của bạn.
function Aberration(q, e, symbol, period, upRatio, downRatio, opAmount) {
    var self = {}
    self.q = q
    self.e = e
    self.symbol = symbol
    self.upTrack = 0
    self.middleTrack = 0
    self.downTrack = 0
    self.nPeriod = period
    self.upRatio = upRatio
    self.downRatio = downRatio
    self.opAmount = opAmount
    self.marketPosition = 0

    self.lastErrMsg = ''
    self.lastErrTime = ''
    self.lastBar = {
        Time: 0,
        Open: 0,
        High: 0,
        Low: 0,
        Close: 0,
        Volume: 0
    }
    self.symbolDetail = null
    self.lastBarTime = 0
    self.tradeCount = 0
    self.isBusy = false

    self.setLastError = function(errMsg) {
        self.lastErrMsg = errMsg
        self.lastErrTime = errMsg.length > 0 ? _D() : ''
    }

    self.getStatus = function() {
        return [self.symbol, self.opAmount, self.upTrack, self.downTrack, self.middleTrack, _N(self.lastBar.Close), (self.marketPosition == 0 ? "--" : (self.marketPosition > 0 ? "多#ff0000" : "空#0000ff")), self.tradeCount, self.lastErrMsg, self.lastErrTime]
    }
    self.getMarket = function() {
        return [self.symbol, _D(self.lastBarTime), _N(self.lastBar.Open), _N(self.lastBar.High), _N(self.lastBar.Low), _N(self.lastBar.Close), self.lastBar.Volume]
    }

    self.restore = function(positions) {
        for (var i = 0; i < positions.length; i++) {
            if (positions[i].ContractType == self.symbol) {
                self.marketPosition += positions[i].Amount * ((positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) ? 1 : -1)
            }
        }
        if (self.marketPosition !== 0) {
            self.tradeCount++
                Log("恢复", self.symbol, "当前持仓为", self.marketPosition)
        }
    }

    self.poll = function() {
        if (self.isBusy) {
            return false
        }

        if (!$.IsTrading(self.symbol)) {
            self.setLastError("不在交易时间内")
            return false
        }

        if (!self.e.IO("status")) {
            self.setLastError("未连接交易所")
            return false
        }

        var detail = self.e.SetContractType(self.symbol)
        if (!detail) {
            self.setLastError("切换合约失败")
            return false
        }
        if (!self.symbolDetail) {
            self.symbolDetail = detail
            Log("合约", detail.InstrumentName.replace(/\s+/g, ""), ", 策略一次开仓:", self.opAmount, "手, 一手", detail.VolumeMultiple, "份, 最大下单量", detail.MaxLimitOrderVolume, "保证金率:", detail.LongMarginRatio.toFixed(4), detail.ShortMarginRatio.toFixed(4), "交割日期", detail.StartDelivDate);
        }
        var records = self.e.GetRecords()
        if (!records || records.length == 0) {
            self.setLastError("获取柱线失败")
            return false
        }

        var bar = records[records.length - 1]
        self.lastBar = bar

        if (records.length <= self.nPeriod) {
            self.setLastError("柱线长度不够")
            return false
        }

        if (self.lastBarTime < bar.Time) {
            var sum = 0
            var pos = records.length - self.nPeriod - 1
            for (var i = pos; i < records.length - 1; i++) {
                sum += records[i].Close
            }
            var avg = sum / self.nPeriod
            var std = 0
            for (i = pos; i < records.length - 1; i++) {
                std += Math.pow(records[i].Close - avg, 2)
            }
            std = Math.sqrt(std / self.nPeriod)

            self.upTrack = _N(avg + (self.upRatio * std))
            self.downTrack = _N(avg - (self.downRatio * std))
            self.middleTrack = _N(avg)
            self.lastBarTime = bar.Time
        }
        var msg
        var act = ""
        if (self.marketPosition == 0) {
            if (bar.Close > self.upTrack) {
                msg = '做多 触发价: ' + bar.Close + ' 上轨:' + self.upTrack;
                act = "buy"
            } else if (bar.Close < self.downTrack) {
                msg = '做空 触发价: ' + bar.Close + ' 下轨:' + self.downTrack;
                act = "sell"
            }
        } else {
            if (self.marketPosition < 0 && bar.Close > self.middleTrack) {
                msg = '平空 触发价: ' + bar.Close + ' 平仓线:' + self.middleTrack;
                act = "closesell"
            } else if (self.marketPosition > 0 && bar.Close < self.middleTrack) {
                msg = '平多 触发价: ' + bar.Close + ' 平仓线:' + self.middleTrack;
                act = "closebuy"
            }
        }

        if (act == "") {
            return true
        }

        Log(self.symbol + ', ' + msg + (NotifyWX ? '@' : ''))

        self.isBusy = true
        self.tradeCount += 1
        if (self.lastErrMsg != '') {
            self.setLastError('')
        }
        self.q.pushTask(self.e, self.symbol, act, self.opAmount, function(task, ret) {
            self.isBusy = false
            if (!ret) {
                return
            }
            if (task.action == "buy") {
                self.marketPosition = 1
            } else if (task.action == "sell") {
                self.marketPosition = -1
            } else {
                self.marketPosition = 0
            }
        })
    }
    return self
}

function main() {
    if (exchange.GetName() !== 'Futures_CTP') {
        throw "只支持传统商品期货(CTP)"
    }
    
    SetErrorFilter("login|ready|初始化")

    LogStatus("Ready...")
    if (Reset) {
        LogProfitReset()
        LogReset()
    }
    
    // Ref: https://www.fmz.com/bbs-topic/362
    if (typeof(exchange.IO("mode", 0)) == 'number') {
        Log("切换行情模式成功")
    }

    LogStatus("等待与期货商服务器连接..")
    while (!exchange.IO("status")) {
        Sleep(500)
    }
    LogStatus("获取资产信息")
    var tblRuntime = {
        type: 'table',
        title: '交易信息',
        cols: ['品种', '每次开仓量', '上轨', '下轨', '中轨', '最后成交价', '仓位', '交易次数', '最后错误', '错误时间'],
        rows: []
    };
    var tblMarket = {
        type: 'table',
        title: '行情信息',
        cols: ['品种', '当前周期', '开盘', '最高', '最低', '最后成交价', '成交量'],
        rows: []
    };
    var tblPosition = {
        type: 'table',
        title: '持仓信息',
        cols: ['品种', '杠杆', '方向', '均价', '数量', '持仓盈亏'],
        rows: []
    };
    var positions = _C(exchange.GetPosition)
    if (positions.length > 0 && !AutoRestore) {
        throw "程序启动时不能有持仓, 但您可以勾选自动恢复来进行自动识别 !"
    }
    var initAccount = _C(exchange.GetAccount)
    var detail = JSON.parse(exchange.GetRawJSON())
    if (positions.length > 0) {
        initAccount.Balance += detail['CurrMargin']
    }
    var initNetAsset = detail['CurrMargin'] + detail['Available']
    var initAccountTbl = $.AccountToTable(exchange.GetRawJSON(), "初始资金")

    if (initAccountTbl.rows.length == 0) {
        initAccountTbl.rows = [
            ['Balance', '可用保证金', initAccount.Balance],
            ['FrozenBalance', '冻结资金', initAccount.FrozenBalance]
        ]
    }

    var nowAcccount = initAccount
    var nowAcccountTbl = initAccountTbl

    var symbols = Symbols.replace(/\s+/g, "").split(',')
    var pollers = []
    var prePosUpdate = 0
    var suffix = ""
    var needUpdate = false
    var holdProfit = 0

    function updateAccount(acc) {
        nowAcccount = acc
        nowAcccountTbl = $.AccountToTable(exchange.GetRawJSON(), "当前资金")
        if (nowAcccountTbl.rows.length == 0) {
            nowAcccountTbl.rows = [
                ['Balance', '可用保证金', nowAcccount.Balance],
                ['FrozenBalance', '冻结资金', nowAcccount.FrozenBalance]
            ]
        }
    }

    var q = $.NewTaskQueue(function(task, ret) {
        needUpdate = true
        Log(task.desc, ret ? "成功" : "失败")
        var account = task.e.GetAccount()
        if (account) {
            updateAccount(account)
        }
    })

    _.each(symbols, function(symbol) {
        var pair = symbol.split(':')
        pollers.push(Aberration(q, exchange, pair[0], NPeriod, Ks, Kx, (pair.length == 1 ? AmountOP : parseInt(pair[1]))))
    })

    if (positions.length > 0 && AutoRestore) {
        _.each(pollers, function(poll) {
            poll.restore(positions)
        })
    }
    var isFirst = true
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            var js = cmd.split(':', 2)[1]
            Log("执行调试代码:", js)
            try {
                eval(js)
            } catch (e) {
                Log("Exception", e)
            }
        }
        tblRuntime.rows = []
        tblMarket.rows = []
        var marketAlive = false
        _.each(pollers, function(poll) {
            if (poll.poll()) {
                marketAlive = true
            }
            tblRuntime.rows.push(poll.getStatus())
            tblMarket.rows.push(poll.getMarket())
        })
        q.poll()
        Sleep(LoopInterval * 1000)
        if ((!exchange.IO("status")) || (!marketAlive)) {
            if (isFirst) {
                LogStatus("正在等待开盘...", _D())
            }
            continue
        }
        isFirst = false
        var now = new Date().getTime()
        if (marketAlive && (now - prePosUpdate > 30000 || needUpdate)) {
            var pos = exchange.GetPosition()
            if (pos) {
                holdProfit = 0
                prePosUpdate = now
                tblPosition.rows = []
                for (var i = 0; i < pos.length; i++) {
                    tblPosition.rows.push([pos[i].ContractType, pos[i].MarginLevel, ((pos[i].Type == PD_LONG || pos[i].Type == PD_LONG_YD) ? '多#ff0000' : '空#0000ff'), pos[i].Price, pos[i].Amount, _N(pos[i].Profit)])
                    holdProfit += pos[i].Profit
                }
                if (pos.length == 0 && needUpdate) {
                    LogProfit(_N(nowAcccount.Balance - initAccount.Balance, 4), nowAcccount)
                }
            }
            needUpdate = false
            if (RCMode) {
                var account = exchange.GetAccount()
                if (account) {
                    updateAccount(account)
                    var detail = JSON.parse(exchange.GetRawJSON())
                    var netAsset = detail['PositionProfit'] + detail['CurrMargin'] + detail['Available']
                    var risk = detail['CurrMargin'] / (detail['CurrMargin'] + detail['Available'] + detail['PositionProfit'])
                    suffix = ", 账户初始净值约: " + _N(initNetAsset, 2) + " , 风控最小净值要求" + MinNetAsset + " , 当前账户净值约: " + _N(netAsset, 2) + ", 盈亏约: " + _N(netAsset - initNetAsset, 3) + " 元, 风险: " + ((risk * 100).toFixed(3)) + "% #ff0000"
                    if (netAsset < MinNetAsset) {
                        Log("风控模块触发, 中止运行并平掉所有仓位, 当前净值约 ", netAsset, ", 要求低于最小净值:", MinNetAsset)
                        if (RCCoverAll) {
                            Log("开始平掉所有仓位")
                            $.NewPositionManager().CoverAll()
                        }
                        throw "中止运行"
                    }
                }
            }
        }
        LogStatus('`' + JSON.stringify([tblRuntime, tblPosition, tblMarket, initAccountTbl, nowAcccountTbl]) + '`\n价格最后更新: ' + _D() + ', 持仓最后更新: ' + _D(prePosUpdate) + '\n当前持仓总盈亏: ' + _N(holdProfit, 3) + suffix)
    }
}
  • Kết quả thử nghiệm

    Trong khi đó, các nhà đầu tư khác cũng có thể tham gia vào việc xây dựng danh mục đầu tư.img

  • Tóm lại

    Một, chiến lược này rất đa dạng và thích nghi với chu kỳ, phù hợp với hầu hết các loại giao dịch. 2. Chiến lược rút tiền lớn đòi hỏi quản lý tài chính và kiểm soát rủi ro nghiêm ngặt.


Thêm nữa