격자 변형 전략의 단면 격자 (OK 선물)

저자:제로, 날짜: 2015-12-16 23:00:05
태그:오케이격자

그레이드가 방향을 설정할 수 있습니다. 사면 팔면: 네트워크는 첫 번째 가격부터 아래로 청구서를 매달아, 각 청구서 간격 가격 간격 이 매개 변수,挂单数量은 "单笔数量",挂足 총 수 한 청구서, 임의의 청구서 거래가 완료된 후, 프로그램은 구매 가격에 따라 추가 가격 차이 ((元) 이 매개 변수의 값의 가격 판매 주문, 판매, 판매 후, 다시 원래의 grid의 가격에 따라 挂单 판매 후 구매: 다른 방식으로 작동합니다.

이 전략의 가장 큰 위험은 단일 시장이며, 가격 변동은 격자 범위를 초월합니다.

자동 중단 및 이동 기능이있는 격자


var isFuture = false;

function hasOrder(orders, orderId) {
    for (var i = 0; i < orders.length; i++) {
        if (orders[i].Id == orderId) {
            return true;
        }
    }
    return false;
}


function cancelPending() {
    var ret = false;
    while (true) {
        if (ret) {
            Sleep(Interval);
        }
        var orders = _C(exchange.GetOrders);
        if (orders.length == 0) {
            break;
        }

        for (var j = 0; j < orders.length; j++) {
            exchange.CancelOrder(orders[j].Id, orders[j]);
            ret = true;
        }
    }
    return ret;
}


function balanceAccount(orgAccount, initAccount) {
    if (isFuture) {
        while (true) {
            cancelPending();
            var positions = _C(exchange.GetPosition);
            if (positions.length === 0 ) {
                var accountNow = _C(exchange.GetAccount);
                LogProfit(_N(accountNow.Stocks - orgAccount.Stocks), "可用保证金:", accountNow.Stocks);
                return;
            }
            for (var i = 0; i < positions.length; i++) {
                if (positions[i].Type == PD_LONG) {
                    exchange.SetDirection("closebuy");
                    exchange.Sell(positions[i].Amount);
                } else {
                    exchange.SetDirection("closesell");
                    exchange.Buy(positions[i].Amount);
                }
            }
            Sleep(Interval);
        }
    }
    var account = _C(exchange.GetAccount);
    while (true) {
        var diff = _N(account.Stocks - initAccount.Stocks);
        if (Math.abs(diff) < exchange.GetMinStock()) {
            break;
        }
        var depth = _C(exchange.GetDepth);
        var books = diff > 0 ? depth.Bids : depth.Asks;
        var n = 0;
        var price = 0;
        for (var i = 0; i < books.length; i++) {
            n += books[i].Amount;
            if (n >= Math.abs(diff)) {
                price = books[i].Price;
                break;
            }
        }
        Log("开始平衡", (diff > 0 ? "卖出" : "买入"), Math.abs(diff), "个币");
        if (diff > 0) {
            exchange.Sell(price - 0.2, diff);
        } else {
            exchange.Buy(price + 0.2, -diff);
        }
        Sleep(1000);
        cancelPending();
        account = _C(exchange.GetAccount);
    }
    Log("平衡完成", account);
}

var STATE_WAIT_OPEN  = 0;
var STATE_WAIT_COVER = 1;
var STATE_WAIT_CLOSE = 2;
var ProfitCount = 0;
var BuyFirst = (OpType == 0);
var IsSupportGetOrder = true;
var LastBusy = 0;
var LastFloatProfit = 0;

function setBusy() {
    LastBusy = new Date();
}

function isTimeout() {
    if (MaxIdle <= 0) {
        return false;
    }
    var now = new Date();
    if (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) {
        LastBusy = now;
        return true;
    }
    return false;
}

function onexit() {
    if (CancelAllWS) {
        Log("正在退出, 尝试取消所有挂单");
        cancelPending();
    }
    Log("策略成功停止");
    Log(_C(exchange.GetAccount));
}


function fishing(orgAccount, fishCount) {
    setBusy();
    var account = _C(exchange.GetAccount);
    Log(account);
    var InitAccount = account;
    var ticker = _C(exchange.GetTicker);
    var amount = _N(AmountOnce);
    var amountB = amount;
    var amountS = amount;
    if (typeof(AmountType) !== 'undefined' && AmountType == 1) {
        amountB = BAmountOnce;
        amountS = SAmountOnce;
    }
    if (FirstPriceAuto) {
        FirstPrice = BuyFirst ? _N(ticker.Buy - PriceGrid) : _N(ticker.Sell + PriceGrid);
    }
    // Initialize fish table
    var fishTable = {};
    var uuidTable = {};
    var needStocks = 0;
    var needMoney = 0;
    var actualNeedMoney = 0;
    var actualNeedStocks = 0;
    var notEnough = false;
    var canNum = 0;
    var marginLevel = [10,20][MarginLevelIdx];
    exchange.SetMarginLevel(marginLevel);
    for (var idx = 0; idx < AllNum; idx++) {
        var price = _N(BuyFirst ? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid));
        if (isFuture) {
            needStocks += ((100 * amountB) / price) / marginLevel;
            if (_N(needStocks) <= _N(account.Stocks)) {
                actualNeedStocks = needStocks;
                canNum++;
            } else {
                notEnough = true;
            }
        } else {
            needStocks += amountS;
            needMoney += price * amountB;
            if (BuyFirst) {
                if (_N(needMoney) <= _N(account.Balance)) {
                    actualNeedMondy = needMoney;
                    actualNeedStocks = needStocks;
                    canNum++;
                } else {
                    notEnough = true;
                }
            } else {
                if (_N(needStocks) <= _N(account.Stocks)) {
                    actualNeedMondy = needMoney;
                    actualNeedStocks = needStocks;
                    canNum++;
                } else {
                    notEnough = true;
                }
            }
        }
        fishTable[idx] = STATE_WAIT_OPEN;
        uuidTable[idx] = -1;
    }
    if (EnableProtectDiff) {
        if (BuyFirst && (FirstPrice - ticker.Sell) > ProtectDiff) {
            throw "首次买入价比市场卖1价高" + _N(FirstPrice - ticker.Sell) + ' 元';
        } else if (!BuyFirst && (ticker.Buy - FirstPrice) > ProtectDiff) {
            throw "首次卖出价比市场买1价高 " + _N(ticker.Buy - FirstPrice) + ' 元';
        }
    }
    if (BuyFirst && !isFuture) {
        if (account.Balance < _N(needMoney)) {
            if (fishCount == 1) {
                throw "资金不足, 需要"+ _N(needMoney) + "元";
            } else {
                Log("资金不足, 需要", _N(needMoney), "元, 程序只做", canNum, "个网格 #ff0000");
            }
        } else {
            Log('预计动用资金: ', _N(needMoney), "元");
        }
    } else {
        if (account.Stocks < _N(needStocks)) {
            if (fishCount == 1) {
                throw "币数不足, 需要 "+ _N(needStocks) + " 个币";
            } else {
                Log("资金不足, 需要", _N(needStocks), "个币, 程序只做", canNum, "个网格 #ff0000");
            }
        } else {
            Log('预计动用币数: ', _N(needStocks), "个");
        }
    }

    var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell;
    var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy;
    var ts = new Date();
    var preMsg = "";
    var profitMax = 0;
    while (true) {
        var now = new Date();
        if (now.getTime() - ts.getTime() > 5000) {
            if (typeof(GetCommand) == 'function' && GetCommand() == "收网") {
                Log("开始执行命令进行收网操作");
                balanceAccount(orgAccount, InitAccount);
                return false;
            }
            ts = now;
            var msg = "";
            var positions, isHold;
            var ticker = _C(exchange.GetTicker);
            var nowAccount = _C(exchange.GetAccount);
            if (isFuture) {
                positions = _C(exchange.GetPosition);
                isHold = positions.length > 0;
                if (isHold) {
                    msg += "持仓: " + positions[0].Amount + " 持仓均价: " + _N(positions[0].Price) + " 浮动盈亏: " + _N(positions[0].Profit);
                    if (EnableStopLoss && -positions[0].Profit >= StopLoss) {
                        Log("当前浮动盈亏", positions[0].Profit, "开始止损");
                        balanceAccount(orgAccount, InitAccount);
                        if (StopLossMode === 0) {
                            throw "止损退出";
                        } else {
                            return true;
                        }
                    }
                } else {
                    msg += "空仓";
                }
                msg += " 可用保证金: " + nowAccount.Stocks;
                
            } else {
                isHold = Math.abs(amount_diff) >= exchange.GetMinStock();
                
                var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks);
                var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance);
                var floatProfit = _N(money_diff + (amount_diff * ticker.Last));
                var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks - orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last));
                LastFloatProfit = floatProfitAll;
                profitMax = Math.max(floatProfit, profitMax);
                if (EnableStopLoss) {
                    if ((profitMax - floatProfit) >= StopLoss) {
                        Log("当前浮动盈亏", floatProfit, "利润最高点: ", profitMax, "开始止损");
                        balanceAccount(orgAccount, InitAccount);
                        if (StopLossMode === 0) {
                            throw "止损退出";
                        } else {
                            return true;
                        }
                    }
                }
                if (isHold) {
                    if (RestoreProfit && ProfitAsOrg) {
                        if (BuyFirst) {
                            money_diff += LastProfit;
                        } else {
                            money_diff -= LastProfit;
                        }
                    }
                    var hold_amount = amount_diff;
                    var hold_price = (-money_diff) / amount_diff;
                    if (!BuyFirst) {
                        hold_amount = -amount_diff;
                        hold_price = (money_diff) / -amount_diff;
                    }
                    msg = (BuyFirst ? "做多: " : "做空: ") +  _N(hold_amount, 4) + " 个币, 均价: " + _N(hold_price);
                } else {
                    msg += "空仓";
                }
                msg += " 当前网格浮动盈亏: " + floatProfit + " 总浮动盈亏: " + floatProfitAll + " 第 " + fishCount + " 次撒网 最新币价: " + _N(ticker.Last);
            }
            if (isHold) {
                setBusy();
            }

            var distance = 0;
            if (AutoMove) {
                if (BuyFirst) {
                    distance = ticker.Last - FirstPrice;
                } else {
                    distance = FirstPrice - ticker.Last;
                }
                var refish = false;
                if (!isHold && isTimeout()) {
                    Log("空仓过久, 开始移动网格");
                    refish = true;
                }
                if (distance > MaxDistance) {
                    Log("价格超出网格区间过多, 开始移动网格, 当前距离: ", _N(distance), "当前价格:", ticker.Last);
                    refish = true;
                }
                if (refish) {
                    balanceAccount(orgAccount, InitAccount);
                    return true;
                }
            }

            if (AutoMove && distance > 0) {
                msg += " (离网格" + (BuyFirst ? "向上" : "向下") + "偏离: " + _N(distance) + " 元)";
            }
            if (msg != preMsg) {
                LogStatus(msg);
                preMsg = msg;
            }

        }
        var orders = _C(exchange.GetOrders);
        for (var idx = 0; idx < canNum; idx++) {
            var openPrice = _N(BuyFirst ? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid));
            var coverPrice = _N(BuyFirst ? openPrice + PriceDiff : openPrice - PriceDiff);
            var state = fishTable[idx];
            var fishId = uuidTable[idx];
            if (hasOrder(orders, fishId)) {
                continue;
            }

            if (fishId != -1 && IsSupportGetOrder) {
                var order = exchange.GetOrder(fishId);
                if (!order) {
                    Log("获取订单信息失败, ID: ", fishId);
                    continue;
                }
                if (order.Status == ORDER_STATE_PENDING) {
                    Log("订单状态为未完成, ID: ", fishId);
                    continue;
                }
            }

            if (state == STATE_WAIT_COVER) {
                if (isFuture) {
                    exchange.SetDirection(BuyFirst ? "closebuy" : "closesell");
                }
                var coverId = CoverFunc(coverPrice, BuyFirst ? amountS : amountB, BuyFirst ? '完成买单:' : '完成卖单:', openPrice);
                if (coverId) {
                    fishTable[idx] = STATE_WAIT_CLOSE;
                    uuidTable[idx] = coverId;
                }
            } else if (state == STATE_WAIT_OPEN || state == STATE_WAIT_CLOSE) {
                if (isFuture) {
                    exchange.SetDirection(BuyFirst ? "buy" : "sell");
                }
                var openId = OpenFunc(openPrice, BuyFirst ? amountB : amountS);
                if (openId) {
                    fishTable[idx] = STATE_WAIT_COVER;
                    uuidTable[idx] = openId;
                    if (state == STATE_WAIT_CLOSE) {
                        ProfitCount++;
                        if (AmountType === 0) {
                            Log((BuyFirst ? '完成卖单: ' : '完成买单: ') + coverPrice);
                        } else {
                            Log((BuyFirst ? '完成卖单: ' : '完成买单: ') + coverPrice);
                        }
                        if (!isFuture) {
                            var account = _C(exchange.GetAccount);
                            var ticker = _C(exchange.GetTicker);
                            var initNet = _N(((InitAccount.Stocks + InitAccount.FrozenStocks) * ticker.Buy) + InitAccount.Balance + InitAccount.FrozenBalance, 8);
                            var nowNet = _N(((account.Stocks + account.FrozenStocks) * ticker.Buy) + account.Balance + account.FrozenBalance, 8);
                            var actualProfit = _N(((nowNet - initNet)) * 100 / initNet, 8);
                            LogProfit(LastFloatProfit, "总浮动盈亏率:", _N(LastFloatProfit * 100 / actualNeedMondy, 4), '%');
                        }
                    }
                }
            }
        }
        Sleep(CheckInterval);
    }
    return true;
}

function main() {
    if (typeof(AmountType) === 'undefined') {
        AmountType = 0;
    }
    IsSupportGetOrder = exchange.GetName().indexOf('itstamp') == -1;
    if (!IsSupportGetOrder) {
        Log(exchange.GetName(), "不支持GetOrder, 可能影响策略稳定性.");
    }
    
    isFuture = exchange.GetName().indexOf("Future") != -1;
    if (AmountType === 0) {
        BAmountOnce = AmountOnce;
        SAmountOnce = AmountOnce;
    }
    if (exchange.GetName() == "Futures_OKCoin" && (AmountOnce.toString().indexOf(".") != -1 || BAmountOnce.toString().indexOf(".") != -1 || SAmountOnce.toString().indexOf(".") != -1)) {
        throw "OKCoin期货下单数必须为整数";
    }

    SetErrorFilter("502:|503:|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|refused|EOF|When");

    exchange.SetRate(1);
    Log('已经禁用汇率转换, 当前货币为', exchange.GetBaseCurrency());

    if (!RestoreProfit) {
        LastProfit = 0;
    }
    exchange.SetContractType(["this_week", "next_week", "quarter"][ContractTypeIdx]);
    var orgAccount = _C(exchange.GetAccount);
    var fishCount = 1;
    while (true) {
        if (!fishing(orgAccount, fishCount)) {
            break;
        }
        fishCount++;
        Log("第", fishCount, "次重新撒网...");
        FirstPriceAuto = true;
        Sleep(1000);
    }
}



관련

더 많은

구름실제 디스크 테스트okex 거래소, 100%의 오류 위험을 신고합니다. 보시다시피, 격자 총 수 제한은 유효하지 않습니다, 보증금이 만료 될 때까지 계속 매달릴 것입니다.

얼음 덩어리주식 설명서를 삭제하면 실행이 됩니다.

1966년Z 크기가 크다. 이 그리드는 V3 API에 맞을 수 있을까요?

a8269917그리고 그 가격의 비율을 바꾸면 됩니다.

스리우안녕하세요, 문제가 있습니다: 전략이 시작되면 아래로 오프닝이 시작되면 자금 활용률 문제가 발생할 수 있습니다. 왜냐하면 일단 오프닝이 완료되면 자금이 잠겨있어 같은 양의 자금이 동시에 더 많은 계약을 처리 할 수 없습니다.

스리우안녕하세요, 문제가 있습니다: 전략이 시작되면 아래로 오프닝이 시작되면 자금 활용률 문제가 발생할 수 있습니다. 왜냐하면 일단 오프닝이 완료되면 자금이 잠겨있어 같은 양의 자금이 동시에 더 많은 계약을 처리 할 수 없습니다.

이 공격한 돼지제가 질문하고 싶은 것은, 이것이 2년 전의 전략이었는데, 지금 이 순간에도 유용할 수 있을까요?

제로이 사진이 어떻게 바뀌었는지 보여드리겠습니다.

a8269917하지만 선물 계약 자금은 통용되지 않습니다, 당신은 자금을 절약하거나 다른 계약에 사용할 수 없습니다, 당신이 처음에 두 개의 운영 두 개의 네트워크에 자금을 분할하고, 그리고 동적 화폐 연결을 원하는 경우 두 개의 운영 두 개의 네트워크에 사용 하 여 자금을 사용 하 여, 그리고 그 다음 동적 화폐 연결을 사용률을 높이기 위해, 또한 위험을 증가, 나는 여전히 고려해야 할 것 같습니다. 괜찮은 고정 화폐 거래, 오늘 몇 개의 계약을 선택하고, 내일이 폭발하는 것을 두려워, 모든 다른 사람들을 위해 일, 선물은 현금보다, 이 전략은 현금 화폐는 동적 화폐 연결을 가지고, 선물은 내가 가장 중요하다고 생각 하 고, 당신은 한 계약을 집중, 고정 화폐 거래 당신은 매우 낮은 점을 흡입하고, 그리고 즉시 밖으로 팔 수 있습니다, 수익은 매우 높습니다.

스리우이 모든 것은 우리가 할 수 있는 일입니다. 만약 여러분이 1만원을 가지고 있다면, 이제 두 개의 격자가 있습니다. 각각은 아래로 10개의 격자이고, 각각의 격자에는 1000만원 정도가 있습니다. 만약 여러분이 처음부터 연결을 한다면, 10,000원 정도가 모두 얼어붙어 있습니다. 하나의 격자만 복사할 수 있습니다. 하지만 만약 여러분이 동적 연결을 하고 있다면, 여러분은 단지 그 격자의 바닥값을 더해야 합니다.

a8269917제가 여러분에게 대답하기를, 네트워크 거래의 자금 활용률은 높지 않습니다.