फ्यूचर्स बाजार में उच्च आवृत्ति ट्रेडिंग रणनीतियाँ OK/VC/796 (2018-03-27 16:30:08)

लेखक:शून्य, दिनांकः 2014-11-12 19:55:41
टैगः

यह रणनीति फ्यूचर्स के लिए एक रणनीति है। बाजार की कीमतों पर असर पड़ेगा इसलिए यह बड़ी राशि के लिए उपयुक्त नहीं है। यह रणनीति बाजार के व्यवहार का अध्ययन करने के लिए लिखी गई है और इसे वास्तविक समय में छोटी राशि के साथ परीक्षण करने के लिए कहा गया है।


var DO_IDLE  = 0;
var DO_LONG  = 1;
var DO_SHORT = 2;

var _MarginLevel = [5, 10, 20][MLevel];
var _ContractType = ["week", "month", "quarter"][ContractType];
var _CurrentDirection = [DO_LONG, DO_SHORT, DO_IDLE][OpType !=2 ? OpType : WaitType];
var _isAuto = OpType == 2;
var _IsBitVC = false;
var _Is796 = false;
var _IsOKCoin = false;
var _MinAmount = 0;
var _Fee = 0.0003;

function _N(v, precision) {
    if (typeof(precision) != 'number') {
        precision = _IsOKCoin ? 3 : 2;
    }
    var d = parseFloat(v.toFixed(Math.max(10, precision+5)));
    s = d.toString().split(".");
    if (s.length < 2 || s[1].length <= precision) {
        return d;
    }

    var b = Math.pow(10, precision);
    return Math.floor(d*b)/b;
}

function GetOrders() {
    var orders = null;
    while (!(orders = exchange.GetOrders())) {
        Sleep(Interval);
    }
    return orders;
}

function CancelPendingOrders(orderType) {
    while (true) {
        var orders = GetOrders();
        var count = 0;
        if (typeof(orderType) != 'undefined') {
            for (var i = 0; i < orders.length; i++) {
                if (orders[i].Type == orderType) {
                    count++;
                }
            }
        } else {
            count = orders.length;
        }
        if (count == 0) {
            return;
        }

        for (var j = 0; j < orders.length; j++) {
            if (typeof(orderType) == 'undefined' || (orderType == orders[j].Type)) {
                exchange.CancelOrder(orders[j].Id, orders[j]);
                if (j < (orders.length-1)) {
                    Sleep(Interval);
                }
            }
        }
    }
}

function GetPosition(orderType) {
    var positions;
    while (!(positions = exchange.GetPosition())) {
        Sleep(Interval);
    }
    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType == _ContractType && positions[i].Type == orderType) {
            return positions[i];
        }
    }
    return null;
}

function GetAccount() {
    var account;
    while (!(account = exchange.GetAccount())) {
        Sleep(Interval);
    }
    return account;
}

function GetLimit() {
    var ticker;
    while (!(ticker = exchange.GetTicker())) {
        Sleep(Interval);
    }
    if (IsVirtual()) {
        return {high: ticker.Sell + 100, low: ticker.Buy - 100};
    }
    var js = exchange.GetRawJSON();
    try {
        var obj = JSON.parse(js);
        return {high: parseFloat(obj.limit_highest_price), low: parseFloat(obj.limit_lowest_price)};
    } catch (e) {
        Log(e);
    }
    return null;
}

function GetDepth() {
    var depth;
    while (true) {
        depth = exchange.GetDepth();
        if (depth && depth.Asks.length > 0 && depth.Bids.length > 0 && depth.Asks[0].Price > depth.Bids[0].Price) {
            break;
        }
        Sleep(Interval);
    }
    return depth;
}

var LastOpenPrice = 0;
var LastCoverPrice = 0;
var LastHoldPrice = 0;
var LastRecord = null;
var LastEMATime = 0;

function GetDirection() {
    if (OpType != 2) {
        return _CurrentDirection;
    }
    var n = new Date().getTime();
    if ((n - LastEMATime) < (EMAInterval * 1000)) {
        return _CurrentDirection;
    }
    LastEMATime = n;

    var records = exchange.GetRecords();
    if (!records || records.length < (EMA_Slow + 3)) {
        return _CurrentDirection;
    }
    var newLast = records[records.length-1];
    if ((!LastRecord) || (LastRecord.Time == newLast.Time && LastRecord.Close == newLast.Close)) {
        if (!LastRecord) {
            LastRecord = newLast;
        }
        return _CurrentDirection;
    }
    LastRecord = newLast;

    var emaFast = TA.EMA(records, EMA_Fast);
    var emaSlow = TA.EMA(records, EMA_Slow);
    return emaFast[emaFast.length-1] >= emaSlow[emaSlow.length-1] ? DO_LONG : DO_SHORT;
}

function GetPrice() {
    var buyPrice = 0;
    var buyAmount = 0;
    var sellPrice = 0;
    var sellAmount = 0;
    var depth = GetDepth();
    for (var i = 0; i < depth.Asks.length; i++) {
        sellAmount += depth.Asks[i].Amount;
        if (sellAmount >= DepthSell) {
            sellPrice = depth.Asks[i].Price;
            break;
        }
    }

    for (var i = 0; i < depth.Bids.length; i++) {
        buyAmount += depth.Bids[i].Amount;
        if (buyAmount >= DepthBuy) {
            buyPrice = depth.Bids[i].Price;
            break;
        }
    }

    var diff = MinDiff - (sellPrice - buyPrice);
    if (diff >= 0) {
        buyPrice = buyPrice - (diff/2);
        sellPrice = sellPrice + (diff/2);
    } else {
        buyPrice += SlidePrice;
        sellPrice -= SlidePrice;
    }
    return {buy : buyPrice, sell: sellPrice};
}


function updateProfit() {
    var account = GetAccount();
    if (_IsBitVC) {
        try {
            var obj = JSON.parse(exchange.GetRawJSON());
            LogProfit(obj.dynamicRights, 'Stocks:', account.Stocks, 'FrozenStocks:', account.FrozenStocks);
        } catch(e) {
            Log(e);
        }
    } else {
        LogProfit(account.Stocks + account.FrozenStocks);
    }
}

var _prePositions = 0;

function onTick() {
    var price = GetPrice();

    if (_IsBitVC) {
        var limit = GetLimit();
        if (limit) {
            price.sell = Math.max(Math.min(price.sell, limit.high), limit.low);
            price.buy = Math.min(Math.max(price.buy, limit.low), limit.high);
        }
    }

    var openFunc = _CurrentDirection == DO_LONG ? exchange.Buy : exchange.Sell;
    var openDirection = _CurrentDirection == DO_LONG ? "buy" : "sell";
    var openTradeType = _CurrentDirection == DO_LONG ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;

    var coverFunc = _CurrentDirection == DO_LONG ? exchange.Sell : exchange.Buy;
    var coverDirection = _CurrentDirection == DO_LONG ? "closebuy" : "closesell";
    var coverTradeType = _CurrentDirection == DO_LONG ? ORDER_TYPE_SELL : ORDER_TYPE_SELL;

    var openPrice = _N(_CurrentDirection == DO_LONG ? price.buy : price.sell);
    var coverPrice = _N(_CurrentDirection == DO_LONG ? price.sell : price.buy);

    var op = 0;
    var isFighting = false;
    var marketCoverPrice = coverPrice;

    if (LastHoldPrice > 0 && LastCoverPrice > 0) {
        if (_CurrentDirection == DO_LONG) {
            isFighting = (LastHoldPrice - coverPrice) <= StopLoss;
            if (isFighting) {
                coverPrice = _N((LastHoldPrice * (1+_Fee)) + StopProfit);
            } else {
                isFighting = true;
            }
        } else {
            isFighting = (coverPrice - LastHoldPrice) <= StopLoss;
            if (isFighting) {
                coverPrice = _N((LastHoldPrice * (1-_Fee)) - StopProfit);
            }
        }
    }

    if (LastHoldPrice > 0) {
        LogStatus(_CurrentDirection == DO_LONG ? "多仓" : "空仓", isFighting ? "僵持中.." : "止损中..", "持仓均价: ", _N(LastHoldPrice), "盘口平仓价:", marketCoverPrice, isFighting ? "#0000ff" : "#ff0000");
    } else {
        LogStatus(_CurrentDirection == DO_LONG ? "做多" : "做空", "开仓价: ",  openPrice, "平仓价:", marketCoverPrice, "抢盘中... #428bca");
    }

    if (openPrice != LastOpenPrice) {
        op = 1;
    }

    if (coverPrice != LastCoverPrice) {
        op = op == 0 ? 2 : 3;
    }

    if (op == 3) {
        CancelPendingOrders();
    } else if (op != 0) {
        CancelPendingOrders(op == 1 ? openTradeType : coverTradeType);
    } else {
        return;
    }

    var position = 0;

    var hold = GetPosition(openTradeType);
    if (hold) {
        position = hold.Amount;
        LastHoldPrice = hold.Price;
    } else {
        LastHoldPrice = 0;
    }

    var coverAmount = _N(Math.min(position, _IsBitVC ? (LotCover * 100) : LotCover));
    if (!_Is796) {
        coverAmount = parseInt(coverAmount);
    }
    if (_IsBitVC) {
        coverAmount = parseInt(parseInt(coverAmount / 100) * 100);
    }
    if ((op == 2 || op == 3) && (coverAmount >= _MinAmount)) {
        exchange.SetDirection(coverDirection);
        if (coverFunc(coverPrice, coverAmount, "上次平仓价格", LastCoverPrice) > 0) {
            LastCoverPrice = coverPrice;
        }
    }

    if (position == 0 && _prePositions != 0) {
        updateProfit();
        _prePositions = 0;
    }
    
    var d = GetDirection();
    if (_prePositions == 0) {
        _prePositions = position;
    }


    if (_isAuto) {
        if (d != _CurrentDirection) {
            if (position == 0 && GetOrders().length == 0) {
                Log(d == DO_LONG ? "开始做多" : "开始做空");
                _CurrentDirection = d;
            }
            return;
        }
    }

    var account = GetAccount();
    var canUsedStocks = account.Stocks;
    if (KeepStocksRate > 0) {
        canUsedStocks = _N(Math.max(account.Stocks - _N((position * (_IsOKCoin ? 10 : 1) / _MarginLevel / (_Is796 ? 1 : openPrice)) * KeepStocksRate), 0) / KeepStocksRate);
    }
    var openAmount = 0;
    if (_IsBitVC) {
        openAmount = parseInt(parseInt(Math.min(((canUsedStocks * _MarginLevel * (openPrice*0.9)) / 100), Lot)) * 100);
    } else if (_IsOKCoin) {
        openAmount = parseInt(Math.min(((canUsedStocks * _MarginLevel * (openPrice*0.9)) / 10), Lot));
    } else {
        openAmount = _N(Math.min(canUsedStocks * _MarginLevel, Lot));
    }
    if ((op == 1 || op == 3) && (openAmount >= _MinAmount)) {
        exchange.SetDirection(openDirection);
        if (openFunc(openPrice, openAmount, "上次建仓价格", LastOpenPrice) > 0) {
            LastOpenPrice = openPrice;
        }
    }
}

function onexit() {
    CancelPendingOrders();
    Log("Exit");
}

function main() {
    var eName = exchange.GetName();

    if (eName.indexOf("Futures") == -1) {
        throw "该策略为期货专用策略";
    }
    if (_IsOKCoin && _MarginLevel == 5) {
        throw "OKCoin期货只支持10倍或20倍杠杆";
    }
    if (DisableLog) {
        EnableLog(false);
    }

    _IsBitVC = eName.indexOf("BitVC") != -1;
    _Is796 = eName.indexOf("796") != -1;
    _IsOKCoin = eName.indexOf("OKCoin") != -1;

    if (_IsBitVC) {
        _MinAmount = 100;
    } else if (_IsOKCoin) {
        _MinAmount = 1;
    } else {
        _MinAmount = exchange.GetMinStock();
    }

    exchange.SetRate(1);
    Log(exchange.GetName(), GetAccount());
    CancelPendingOrders();
    LoopInterval = Math.max(LoopInterval, 1);
    EMAInterval = Math.max(EMAInterval, 1);
    if (_IsBitVC || _IsOKCoin) {
        Lot = parseInt(Math.max(1, Lot));
        LotCover = parseInt(Math.max(1, LotCover));
        if (Lot < 1 || LotCover < 1) {
            throw "手数最少为1, BitVC一手相当于100元人民币, OKCoin相当于10美金.";
        }
    }
    KeepStocksRate = parseInt(KeepStocksRate);
    Log("预留", KeepStocksRate, "倍的保证金");

    if (_IsOKCoin && ContractType == 0) {
        _ContractType = "this_week";
    }
    if (!_IsOKCoin && ContractType == 1) {
        throw "只有OKCoin期货支持月全约";
    }
    if (_Is796 && ContractType != 0) {
        throw "796只支持周合约类型";
    }
    exchange.SetContractType(_ContractType);
    exchange.SetMarginLevel(_MarginLevel);

    if (OpType == 2) {
        Log("开始收集K线信息, 请耐心等待.");
    }

    while (true) {
        if (_CurrentDirection == DO_IDLE) {
            _CurrentDirection = GetDirection();
        } else {
            onTick();
        }
        Sleep(LoopInterval * 1000);
    }
}

अधिक