网格变形策略之单边网格 (注释版)

Author: 小小梦, Created: 2017-09-06 18:39:54, Updated: 2019-07-31 18:19:33

PriceDiff), Precision); // 开仓平仓价差,即 每个节点的盈利空间 var state = fishTable[idx]; // 赋值 渔网 节点的状态 var fishId = uuidTable[idx]; // 编号

        // 此处判断作用为: 过滤 未完成的订单
        if (hasOrder(orders, fishId)) {                                                                 // 如果 所有未完成订单,即挂单数组 中有ID为 fishId 的订单
            continue;                                                                                   // 跳过本次循环  继续循环
        }

        if (fishId != -1 && IsSupportGetOrder) {                                                        // 网格 节点 id 不等于 初始值,即下过订单,并且 交易所支持 GetOrder
            var order = trader.GetOrder(fishId);                                                        // 获取 该 fishId 号 的订单
            // 此处判断作用为: 过滤 没有找到订单 的 网格节点,以下判断(state == STATE_WAIT_COVER) 等等 的逻辑不会触发
            if (!order) {                                                                               // 如果 !order 为真 即获取订单失败 
                Log("获取订单信息失败, ID: ", fishId);                                                     // 输出日志
                continue;                                                                               // 跳过本次循环 继续循环
            }
            // 此处判断作用为: 过滤 处于挂起状态,未成交,或者 未完全成交的 网格节点, 以下判断(state == STATE_WAIT_COVER) 等等 的逻辑不会触发
            if (order.Status == ORDER_STATE_PENDING) {                                                  // 如果订单状态 是在交易所 挂起状态
                //Log("订单状态为未完成, ID: ", fishId);
                continue;                                                                               // 跳过本次循环 继续循环
            }
        }

        if (state == STATE_WAIT_COVER) {                                                                // 如果 当前节点 状态是 等待平仓
            var coverId = CoverFunc(coverPrice, (BuyFirst ? amountS[idx] : amountB[idx]), (BuyFirst ? '完成买单:' : '完成卖单:'), openPrice, '量:', (BuyFirst ? amountB[idx] : amountS[idx]));
            // 调用 平仓 函数 CoverFunc 挂出 平仓单

            if (typeof(coverId) === 'number' || typeof(coverId) === 'string') {        // 判断 如果 平仓函数 返回的 Id 为 数值(由 发明者量化 API 直接返回) 或者 字符串(由 trader 对象的 Buy/Sell函数返回)
                fishTable[idx] = STATE_WAIT_CLOSE;                                     // 已经挂出  平仓单, 更新状态为 :  STATE_WAIT_CLOSE 即等待 节点任务完成
                uuidTable[idx] = coverId;                                              // 把 订单号 储存在 uuidTable 对应的 idx 位置上。
            }
        } else if (state == STATE_WAIT_OPEN || state == STATE_WAIT_CLOSE) {            // 如果状态是 等待开仓 或者 等待完成
            var openId = OpenFunc(openPrice, BuyFirst ? amountB[idx] : amountS[idx]);  // 下开仓单。
            if (typeof(openId) === 'number' || typeof(openId) === 'string') {          // 判断是否下单成功
                fishTable[idx] = STATE_WAIT_COVER;                                     // 更新状态 为等待平仓
                uuidTable[idx] = openId;                                               // 记录当前 节点 订单ID
                if (state == STATE_WAIT_CLOSE) {                                       // 如果是等待完成 (开仓订单下了后 才会触发)
                    ProfitCount++;                                                     // 累计盈利次数
                    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);    // 计算 收益率
                    if (AmountType == 0) {                                             // 根据 买卖同量  , 自定义量  不同的处理。
                        var profit = _N((ProfitCount * amount * PriceDiff) + LastProfit, 8);      // 计算: 所有盈利节点的 盈亏 和 上次撒网盈亏 之和 即 总盈亏
                        Log((BuyFirst ? '完成卖单:' : '完成买单:'), coverPrice, '量:', (BuyFirst ? amountS[idx] : amountB[idx]), '平仓收益', profit);
                        // 输出 订单完成信息
                    } else {
                        Log((BuyFirst ? '完成卖单:' : '完成买单:'), coverPrice, '量:', (BuyFirst ? amountS[idx] : amountB[idx]));
                    }
                }
            }
        }
    }
    Sleep(CheckInterval);                        // 网格逻辑 主要 while 循环检测, 每次 暂停一定时间 CheckInterval 即:检测间隔
}
return true;                                     // 本次撒网完成 返回 true

}

function main() { // 策略主函数,程序从这里开始执行。 if (ResetData) { // RestData 为界面参数, 默认 true , 控制 启动时 是否清空所有数据。默认全部清空。 LogProfitReset(); // 执行 API LogProfitReset 函数,清空 所有收益。 LogReset(); // 执行 API LogReset 函数, 清空 所有日志。 } // exchange.SetMaxDigits(Precision) // 已废弃,使用 exchange.SetPrecision 代替。 exchange.SetPrecision(Precision, 3) // exchange.SetPrecision(2, 3); // 设置价格小数位精度为2位, 品种下单量小数位精度为3位 // Precision 为界面参数。

if (typeof(AmountType) === 'undefined') {        // 订单 数量类型, 0:“买卖同量” ,  1:“自定义量”  , 检测 如果该参数是 未定义的,默认设置 0 。
    AmountType = 0;                              // typeof 会 检测 AmountType 的类型, 如果是 undefined  即 “未定义” ,则给 AmountType 赋值 0。
}
if (typeof(AmountDot) === 'undefined') {         // 订单量 小数点 最长位数 AmountDot 如果是 未定义的, 设置 AmountDot 为 3 。
    AmountDot = 3;                               // 其实已经由 exchange.SetPrecision(Precision, 3) 设置过了,在底层会截断处理。
}
if (typeof(EnableDynamic) === 'undefined') {     // 检测 是否 开启动态挂单 参数,  如果 EnableDynamic 是未定义的, 设置 为 false 即 不开启。
    EnableDynamic = false;
}
if (typeof(AmountCoefficient) === 'undefined') { // 如果未定义, 默认设置   "*1"
    AmountCoefficient = "*1";
}
if (typeof(EnableAccountCheck) === 'undefined') {// 如果未定义, 启用资金检验 参数 设置为 true ,即 开启。
    EnableAccountCheck = true;
}
BuyFirst = (OpType == 0);                        // 根据 OpType 的设置 去 给BuyFirst 赋值, OpType 设置网格类型, 0: 先买后卖, 1: 先卖后买
IsSupportGetOrder = exchange.GetName().indexOf('itstamp') == -1;    // 检测 交易所 名称, 如果是  Bitstamp  则提醒
if (!IsSupportGetOrder) {
    Log(exchange.GetName(), "不支持GetOrder, 可能影响策略稳定性.");
}

SetErrorFilter("502:|503:|S_U_001|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|refused|EOF|When");
// SetErrorFilter  过滤错误信息  

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

if (!RestoreProfit) {     //  恢复上次盈利 若果是  false 则 给 LastProfit 赋值 0 , 即不恢复。
    LastProfit = 0;
}

var orgAccount = _C(exchange.GetAccount);     // 获取账户信息,    此处记录 策略开始运行时的 初始账户信息 ,用于 计算一些收益,如: 总体浮动盈亏 等。本策略有几个参数 都是 该变量传入。
var fishCount = 1;                            // 撒网次数 初始1
while (true) {                                // 策略 主循环
    if (!fishing(orgAccount, fishCount)) {    // 撒网函数 fishing
        break;
    }
    fishCount++;                              // 撒网次数 累计
    Log("第", fishCount, "次重新撒网...");      // 输出 撒网信息。
    FirstPriceAuto = true;                    // 重置 首价格自动 为true
    Sleep(1000);                              // 轮询间隔 1000毫秒
}

}


### 如有注释错误,欢迎指正 ^^



Related

More

活着 可以留个联系方式吗,大佬

活着 这个策略可以设置有利位置最大边界自动移动,如果是不利位置可以移动吗,还是只能靠止损重新撒网,但是重新撒网好像平衡有问题,无法平衡到策略初始状态。我平衡了几次都是币不足只能创建两三格网格。

18180828122 不支持合约吗,回测合约提示订阅失败

kkms mark

jjkk 当网格比较多的时候,下单超过api调用频率了,在什么地方加个延时呀??

逍遥侯CC 楼主能留个联系方式吗

nxtplayer 666,学习一下代码思路

小小梦 V : DoMyBestForeverAgo

小小梦 这个策略应该是个现货策略。

jjkk 具体在什么地方呀,找不到呀

小小梦 控制下 轮询 间隔时间 或者 , 下单 时候的 间隔时间。

小小梦 BotVS QQ群 可以QQ我 ^^ : 小小梦