アベレーション戦略

作者: リン・ハーン小さな夢作成日: 2016年12月10日 12:53:45 更新日: 2016年12月10日 12:57:30

アベレーション戦略は,トレンドでお金を得るための戦略です


  • 履歴

フューチャー・フューチャーで直感的に遊んでいる友人は,Aberration戦略は,Keith Fitschenが1986年に発明した伝説の取引システムで,年間100%以上の収益率を達成したものであると少し知らないかもしれません. 1993年に,彼はアメリカの Future Truth誌にこのシステムを公開し,その戦略がリリースされた日から,そのパフォーマンスは常にトップにランク付けされており,1997,2001年と2005年にリリースされた取引システムの業績ランキングに1位を獲得しています. これは,トレンドトラッキングの戦略に属する中長線取引システムで,穀物,肉,金属,エネルギー,外為,株式指数先物など8種の品種間で柔軟に動作し,トレンドを長線的に追跡して利益を得る.また,複数の関連していないまたは関連性が低い市場で同時に取引しているため,ある市場またはいくつかの市場でトレンドを得るために高い利益を得ることで,他の不安定な市場での損失を補うことができる.その取引頻度は,一般的に年に3〜4回,60%の時間を保持し,平均して60日間を保持する. この戦略の開平戦略は以下のとおりである:まず35日間の移動平均線と35日間の閉盘価格の標準差を利用し,上下三つの軌道を導き出す.上下1つのバーの閉盘価格が上線時,上下が上線時,下下が下線時空き,下下が中間線時,上下が中間線時空き. この戦略の考え方はシンプルで,移動平均線と標準差設定経路を利用して,経路を突破したかどうかを判断し,トレンドを捕捉する.しかし,トレンドが徐々に弱くなったとき,中軌がまず緩む傾向があるため,K線が中軌を反向的に通り過ぎると,トレンドが終了したと推定され,出場を停止する.また,トレンドの誤判がある場合,K線が中軌を反向的に通り過ぎると,損失を間に合うように停止する. この戦略は初期に発表されたもので,現在の取引市場ではあまり適用されないかもしれないが,トレンドキャプチャのアイデアは永続している.

  • 履歴書 2

    Abberation取引システムは1986年にKeith Fitschenによって発明され,1993年にFuture Trust誌に掲載された.興味深いことに,Keithは生まれながらの取引者ではなく,アメリカ空軍で20年以上勤務し,武器のナビゲーションシステム専攻で,タイムシーンのデータ処理に深い力を有している. アバレーション・トレード・システムは,不動的なトレンドフォローで特徴付けられ,長期信号を用いて,1つの品種で年間3〜4回取引し,総取引時間の60%以上を保持し,異なる資金規模に応じて異なる品種数を割り当てることができる.それは,長線取引によってトレンドを捕捉し,同時に複数の関連のない市場で取引するので,ある品種が撤回すると,他の品種が利益を得ることができる.年にわたって,常に1つまたは複数の品種が大きな利益を得ることができる.これらの大きな利益は,トレンド市場での小さな損失を補う.すぐに稼げる戦略を見て,私は内なる興奮を抑えることができなかった. 具体的には,Abberationシステムは3つの軌道を利用して取引を行う.まず,この品種の過去N日間の閉店価格の算術平均MA ((close) を中間軌跡 (MID) として計算し,閉店価格の標準差 std ((close) を波動性の測定として計算し,軌道MID+mを計算する.std ((close) と下軌MID-mstd ((close) 〜は,価格が上線を突破すると多し,価格が中線に戻ると平衡する;逆に,価格が下線を突破すると空し,価格が中線に戻ると平衡する〜.

  • 戦略の原理

    アベレーションは通路突破システムでもあり,上下通路は波動率によって決定される.

    1 軌道上下を決定する: アベレーションは3つの通路線で構成され,中軌は一定の周期の移動平均線 (AveMa) で,上下軌は中軌の基礎で,一定の価格基準差 (StdValue) を加減する.

    具体的には,計算は以下の通りです. (1) 中間軌道計算:AveMa=Average ((Close[1],Length); (2) 計算基準差: StdValue = StandardDev ((Close[1],Length); (3) 軌道計算:UpperBand=Avema+StdDevUpStdValue; (StdDevUpは上線パラメータ) (4) 下線を計算する:LowerBand=Avema-StdDevDnStdValue; (StdDevDnは下線パラメータ)

    2 売買条件: 取引先の価格が上線を突破し,中盤を脱落し,取引先の価格が上線を突破し,中盤を脱落する. 空頭: 閉店価格が下線を下回り,空き開場をすると,中盤を突破した.

  • 策略ソースコード

    • 戦略の枠組みは論理的に明確で,再利用性が強い
    • インタラクティブ機能のリアルディスクで動作する際にリアルタイムでデュウミュウできます
    • 安定して動作し,細部が完璧に処理されています
    • 多種同時操作をサポートし,個別に開放量を制御することができます.
    • 再起動時,ポジションによるプロGRESSを自動的に復元します.
    • 風制御モジュールは,リアルタイムでリスクを示し,停止します.
    • 微信通知をダウンロード
    • サーバーをレンタルしたくない人は,Windows,Linux,Macのシステムでも,ルーターも刷り切れる.
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)
    }
}
  • テスト結果

    このシステムでは,投資ポートフォリオを構築するだけで,システムの力を発揮できる.img

  • 概要

    1. この戦略の多様性と周期的適応性は,ほとんどの取引種に適しています. 2. この戦略は,資金の管理とリスク管理を厳格に行う必要がある.


もっと