এবারেশন কৌশল

লেখক:ছোট্ট স্বপ্ন, তৈরিঃ ২০১৬-১২-১০ 12:53:45, আপডেটঃ ২০১৬-১২-১০ 12:57:30

প্রবণতা থেকে অর্থ উপার্জন করুন


  • জীবনবৃত্তান্ত

ভবিষ্যৎ ব্যবসায়ের সাথে জড়িত অনেক বন্ধু হয়তো এবেরেশন কৌশল সম্পর্কে অজানা। এটি একটি কিংবদন্তি ট্রেডিং সিস্টেম, যা ১৯৮৬ সালে কিথ ফিটসেনের উদ্ভাবনে ১০০% এরও বেশি বার্ষিক রিটার্ন অর্জন করেছিল। ১৯৯৩ সালে তিনি এটিকে আমেরিকান ফোরাম ফিউচার ট্রুথ ফোরাম ম্যাগাজিনে প্রকাশ করেছিলেন। এটি একটি মাঝারি-দীর্ঘ-রেখাযুক্ত ট্রেডিং সিস্টেম, যা প্রবণতা অনুসরণকারী কৌশলগুলির অন্তর্ভুক্ত। এটি আটটি জাতের মধ্যে নমনীয়ভাবে কাজ করে, যেমন শস্য, মাংস, ধাতু, শক্তি, বৈদেশিক মুদ্রা, স্টক ইনডেক্স ফিউচার ইত্যাদি। এটি দীর্ঘ-রেখাযুক্তভাবে প্রবণতা অনুসরণ করে মুনাফা অর্জন করে। এবং যেহেতু এটি একই সাথে একাধিক অপ্রাসঙ্গিক বা খুব কম প্রাসঙ্গিক বাজারে ট্রেড করে, তাই এটির ট্রেডিং ফ্রিকোয়েন্সি সাধারণত বছরে 3-4 বার একটি জাতের ট্রেড করে, 60% সময় ধরে ধরে রাখা হয়, প্রতি ট্রেডের গড় 60 দিন ধরে রাখা হয়। এই কৌশলটির পলিসি খোলার কৌশলটি হলঃ প্রথমে ৩৫ দিনের চলমান গড় এবং ৩৫ দিনের মধ্যে বন্ধের মূল্যের স্ট্যান্ডার্ড ডিফারেন্স ব্যবহার করে, উপরের মধ্যম এবং নীচের তিনটি ট্র্যাভেল বের করুন, যখন একটি বারের বন্ধের দামটি ট্র্যাকটি অতিক্রম করে, নীচে ট্র্যাকটি অতিক্রম করার সময় ফাঁকা থাকে, নীচে ট্র্যাকটি অতিক্রম করার সময় অনেকগুলি মাথা, এবং উপরে ট্র্যাকটি অতিক্রম করার সময় ফাঁকা মাথা। এই কৌশলটির ধারণা খুবই সহজ, যা হল চলমান গড় এবং স্ট্যান্ডার্ড ডিফেক্ট সেটিং চ্যানেল ব্যবহার করে, এবং তারপর যে কোন সময় সিদ্ধান্ত নেয় যে চ্যানেলটি ভেঙে গেছে কিনা, যাতে প্রবণতাটি ধরা যায়। যখন প্রবণতা ধীরে ধীরে দুর্বল হয়, তখন মধ্যপন্থীটি প্রথমে হ্রাস পায়, তাই যখন K লাইনটি মধ্যপন্থীটি অতিক্রম করে, তখন প্রবণতাটি শেষ বলে মনে করা হয় এবং স্টপ করা যায়। যদি প্রবণতাটি ভুল হয়, তবে K লাইনটি মধ্যপন্থীটি অতিক্রম করার সময়ও সময়মতো ক্ষতি বন্ধ করা যায়। এই কৌশলটি অনেক আগে প্রকাশিত হয়েছিল এবং এখনকার ট্রেডিং বাজারে এটি খুব বেশি প্রযোজ্য নাও হতে পারে, তবে ট্রেন্ড ক্যাপচারের ধারণাটি দীর্ঘস্থায়ী।

  • প্রথম পাতা

    Abberation ট্রেডিং সিস্টেমটি ১৯৮৬ সালে কিথ ফিটসেনের দ্বারা উদ্ভাবিত হয়েছিল এবং ১৯৯৩ সালে ফিউচার ট্রাস্ট ম্যাগাজিনে প্রকাশিত হয়েছিল। মজার বিষয় হল, কিথ জন্মগতভাবে ট্রেডার ছিলেন না। তিনি মার্কিন বিমান বাহিনীতে 20 বছরেরও বেশি সময় ধরে কাজ করেছেন। এবেরেশন ট্রেডিং সিস্টেমের বৈশিষ্ট্য হল প্যাসিভ ট্রেন্ড অনুসরণ করা, দীর্ঘমেয়াদী সংকেত গ্রহণ করা, এক জাতের উপর বছরে ৩-৪ বার ট্রেড করা, মোট ট্রেডিং সময়কালের ৬০% এর বেশি সময় ধরে রাখা এবং বিভিন্ন মূলধনের আকারের উপর ভিত্তি করে বিভিন্ন জাতের সংখ্যা বরাদ্দ করা যায়। এটি দীর্ঘ লাইন ট্রেডিংয়ের মাধ্যমে প্রবণতা ক্যাপচার করে বিশাল মুনাফা অর্জন করে, যখন একাধিক অপ্রাসঙ্গিক বাজারে ট্রেড করা হয়, যখন এক জাতটি প্রত্যাহার করে, অন্যটি লাভ করতে পারে। বছরের সময়কালে সর্বদা এক বা একাধিক জাতের বিশাল মুনাফা অর্জন করতে পারে। এই বিশাল মুনাফাগুলি প্রবণতা বাজারের ক্ষুদ্র ক্ষতির জন্য মেটায়। আমি অবিলম্বে অর্থ উপার্জনের কৌশলটি দেখতে চাইনি, আমি অভ্যন্তরীণ উত্তেজনাকে আটক করতে পারি না। বিশেষ করে, এবারেশন সিস্টেমটি তিনটি ট্র্যাভেল ব্যবহার করে ট্রেডিং করে। প্রথমে এই জাতের গত N দিনের বন্ধের মূল্যের গাণিতিক গড় MA (close) মধ্যম ট্র্যাভেল (MID) হিসাবে গণনা করে, বন্ধের মূল্যের স্ট্যান্ডার্ড ডিফারেন্স (std) কাছাকাছি (close) এর অস্থিরতার পরিমাপ হিসাবে, ট্র্যাভেল MID + m গণনা করে।std ((close) এবং নিম্নপথে MID-mstd ((close) ); যখন দামটি উপরের দিকে চলে যায় তখন বেশি করে এবং যখন দামটি মধ্যবর্তী দিকে ফিরে আসে তখন স্থির হয়; বিপরীতে, যখন দামটি নীচের দিকে চলে যায় তখন শূন্য করে এবং যখন দামটি মধ্যবর্তী দিকে ফিরে আসে তখন স্থির হয়।

  • কৌশলগত নীতি

    এবারেশন একটি প্যানেল-ব্রেকিং সিস্টেম, তবে এর উপরের এবং নীচের প্যানেলগুলি ভেরিয়েবলের হার দ্বারা নির্ধারিত হয়।

    ১। ট্রেনের উপরে ও নীচে যা আছে তা নির্ধারণ করুনঃ এবেরেশন হল তিনটি চ্যানেলের লাইন, যার মধ্যে মধ্যপন্থী একটি নির্দিষ্ট চক্রের চলমান গড় (AveMa) এবং উপরের ট্রেনটি মধ্যপন্থী ভিত্তিতে একটি নির্দিষ্ট দামের মানদণ্ডের পার্থক্য (StdValue) যোগ করে এবং হ্রাস করে।

    এই গণনা প্রক্রিয়াটি নিম্নরূপঃ (১) গড় ট্র্যাক গণনাঃ AveMa=Average ((Close[1],Length); (২) গণনার মানদণ্ডের পার্থক্যঃ StdValue = StandardDev ((Close[1],Length); (3) ট্র্যাক গণনাঃ UpperBand=Avema+StdDevUpStdValue; (StdDevUp ট্রেনের পরামিতি) (৪) ট্রেনের নিচে গণনাঃ LowerBand=Avema-StdDevDnStdValue; (StdDevDn ট্রেনের নিচে প্যারামিটার)

    ২। ক্রয়-বিক্রয় শর্তাবলীঃ ডাব্লুএইচপিঃ বন্ধের দামটি ট্রেনের উপরে দিয়ে আরও বেশি খোলা, মাঝারি ট্রেনের বাইরে পড়েছে; খালি মাথাঃ বন্ধের দাম নীচের দিকে নেমে গেছে, খালি খোলা অবস্থান, মাঝারি ট্রেনের বিচ্ছেদ।

  • কৌশল উৎস কোড

    • কৌশলগত কাঠামো যুক্তিগতভাবে পরিষ্কার, পুনরাবৃত্তিযোগ্য
    • ইন্টারেক্টিভ ফাংশনগুলির মাধ্যমে রিয়েল-টাইম ডিবাগিং
    • এটি স্থিতিশীল এবং বিস্তারিতভাবে পরিচালিত।
    • একাধিক বৈচিত্র্যের জন্য সমর্থন, একযোগে পরিচালনা, পৃথকভাবে খোলার পরিমাণ নিয়ন্ত্রণ করতে পারেন
    • পুনরায় চালু করার সময় স্বয়ংক্রিয়ভাবে অবস্থান অনুযায়ী অগ্রগতি পুনরুদ্ধার করুন
    • বায়ু নিয়ন্ত্রণ মডিউল রয়েছে, যা ঝুঁকি, ক্ষতি বন্ধের জন্য রিয়েল-টাইম প্রদর্শন করে
    • উইকিমিডিয়া বিজ্ঞপ্তি
    • যারা সার্ভার ভাড়া নিতে চান না তারা তাদের নিজের কম্পিউটার বা রসকপি ব্যবহার করে উইন্ডোজ, লিনাক্স, ম্যাক সিস্টেম চালাতে পারেন, রাউটারটি ব্রাশ হয়ে গেছে।
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

  • সংক্ষিপ্তসার

    ১। এই কৌশলটির বৈচিত্র্য এবং চক্রের অভিযোজনশীলতা বেশ ভালো, যা বেশিরভাগ ট্রেডিং বৈচিত্র্যের জন্য উপযুক্ত। ২। এই কৌশলটি বড় প্রত্যাহারের জন্য কঠোর তহবিল ব্যবস্থাপনা এবং ঝুঁকি নিয়ন্ত্রণের প্রয়োজন।


আরো