리소스 로딩... 로딩...

3.1 템플릿: 반복 가능한 코드 _ 디지털 화폐 현금 거래 클래식 라이브러리

저자:발명가들의 수량화 - 작은 꿈, 2016-11-12 11:25:51, 2020-03-21 18:53:14에서 작성되었습니다.

템플릿: 복제 가능한 코드 _ 디지털 화폐 현금 거래 클래버


  • 알림 模板类库

    먼저 템플릿에 대해 알아봅시다. 사실 2.6장에서는템플릿(음악) 우리가 간단히 말하는 템플릿 은 발명가들의 템플릿 클래스 리뷰라고 불리는 템플릿 템플릿 의 전략 범주 분류에 속합니다.

    img

    함수를 출력하는 이름의 방식은 $.functionName = function (() {...}; 。여야 합니다. function $.functionName (() {...}는 잘못된 것입니다.

    img

    우리는 테스트 템플릿 이라는 템플릿 클래스 라이브러리를 만들었습니다.

    img

    템플릿을 추가하려는 정책을 입력합니다.

    img

    템플릿 추가:

    img

    그리고 우리는 그것을 다시 볼 수 있습니다.

    img

    • 파이썬 버전의 템플릿

      • 1, 엑스포트 함수 이름

        템플릿에 이렇게 엑스포트 함수와 엑스포트 함수의 구현 함수를 작성한다.

        def test():               # 实现
            Log("测试!")
        
        ext.fun_Export = test     # 导出函数
        

        전화

        img

        img

      • 2, 템플릿을 추가합니다

        정책에서 JS 버전의 템플릿과 마찬가지로 템플릿을 참조하는 방법을 지정하기 위해 해당 템플릿을 선택하고 저장합니다.

  • 템플릿 클래스 라이브러리 디지털 통화 현금 거래 클래스 라이브러리

    사용자가 프로그래밍 기술을 배우고 있지만 거래 세부 사항을 파악하는 데 어려움을 겪고 있으며 전략을 작성하고 싶다면 디지털 통화 현금 거래 클래스 라이브러리를 사용할 수 있습니다. 템플릿 클래스 라이브러리는 거래 논리를 포장하여 사용하기 쉽습니다. 참고로, 템플릿을 복사하기 위해서는 먼저 코드를 읽고, 코드 구현을 이해해야 하며, 사용 시 더욱 편리하게 사용할 수 있습니다.

    img

    디지털 화폐 현금 거래 클래스 라이브러리 템플릿 추가

    img

    다음으로 우리는 이것을 사용하게 됩니다. 이 템플릿의 출력 함수를 모르는 학생은 템플릿의 소스 코드를 직접 볼 수 있습니다. 우리가 직접 작성한 전략 상호 작용 함수 get_Command (?) 를 기억하시나요? 2.5 장에서는 이 함수를 사용해서 트랜잭션을 모방합니다.

// 交互函数
function get_Command() { //负责交互的函数,交互及时更新 相关数值 ,熟悉的用户可以自行扩展
    var keyValue = 0; // 命令传来的参数 数值
    var way = null; //路由
    var cmd = GetCommand(); //获取  交互命令API
    if (cmd) {
        Log("按下了按钮:", cmd); //日志显示
        arrStr = cmd.split(":"); // GetCommand 函数返回的 是一个字符串,这里我处理的麻烦了,因为想熟悉一下JSON 
        //,所以先对字符串做出处理,把函数返回的字符串以 : 号分割成2个字符串。储存在字符串数组中。

        if (arrStr.length === 2) { //接受的不是 数值型的,是按钮型的。
            jsonObjStr = '{' + '"' + arrStr[0] + '"' + ':' + arrStr[1] + '}'; // 把 字符串数组中的元素重新 
            //拼接 ,拼接成 JSON 字符串  用于转换为JSON 对象。
            jsonObj = JSON.parse(jsonObjStr); // 转换为JSON 对象

            for (var key in jsonObj) { // 遍历对象中的  成员名
                keyValue = jsonObj[key]; //取出成员名对应的 值 , 就是交互按钮的值
            }

            if (arrStr[0] == "") { // 此处为 数字型  。这里处理分为  按钮  和  数字型  。 详见 策略参数 设置界面 下的 交互设置
                way = 1;
            }
            if (arrStr[0] == "") {
                way = 2;
            }
            if (arrStr[0] == "扩展2") {
                way = 3;
            }
            if (arrStr[0] == "扩展3") {
                way = 4;
            }
        } else if (arrStr.length === 1) { // 此处为 按钮型  
            //路由
            if (cmd == "buy") {   //  buy 就是 添加的控件的 名称  在下图 已经用红框 圈出来了
                way = 0;
            }
            if (cmd == "sell") {  //  sell 就是 添加的控件的 名称  在下图 已经用红框 圈出来了
                way = 5;
            }
        } else {
            throw "error:" + cmd + "--" + arrStr;
        }
        switch (way) { // 分支选择 操作
            case 0: //处理 buy 按钮
                singal = BUY;
                break;
            case 1: //处理 
                break;
            case 2: //处理 
                break;
            case 3: //处理
                break;
            case 4: //处理
                break;
            case 5: //处理 sell 按钮
                singal = SELL;
                break;
            default:
                break;
        }
    }
}
var WAITING = 0;
var BUY = 1;
var SELL = 2;
var singal = WAITING;
function main() {
    var initAccount = _C(exchange.GetAccount);
    Log("初始账户信息:", initAccount);
    var sellInfo = null;
    var buyInfo = null;
    while(true){
        get_Command();            // 获取交互 命令
        if(singal === BUY){
            buyInfo = $.Buy(0.5); // 调用 数字货币现货交易类库 导出函数$.Buy ,该函数 返回一个结构,包含成交均价、成交数量。
            Log("nowAccount:", _C(exchange.GetAccount), "buyInfo:", buyInfo);
            singal = WAITING;
        }
        if(singal === SELL){
            sellInfo = $.Sell(0.5);
            Log("nowAccount:", _C(exchange.GetAccount), "sellInfo:", sellInfo);
            singal = WAITING;
        }
        LogStatus("buyInfo:", buyInfo, "----sellInfo:", sellInfo);
        Sleep(1000);
    }
}

이 페이지에 추가하는 것을 잊지 마세요.

img

OK! 한번 해보세요.

img

이 문서는 이 문자를 클릭하기 전에 표시된 내용입니다.

img

구매를 클릭하세요:

img

이 문자를 클릭하면,

img

템플릿을 사용하기에 매우 편리합니다. 코드에 있는 구매, 판매는 2개의 출력 함수만 사용하며, 다른 세부 논리는 템플릿에 의해 처리됩니다.

  • 분석 디지털 화폐 현금 거래 클래식 소스

    어떤 도구에 대해 잘 알고 있어야 합니다. 코드는 인터페이스 파라미터에서 분리되지 않습니다:

    img

    이 글의 소스:

function CancelPendingOrders(e, orderType) { // 该函数作用是 取消所有挂单
    while (true) {
        var orders = e.GetOrders();  //  获取 所有未成交的挂单
        if (!orders) {               //  容错处理: orders 获取异常 为null 的情况。
            Sleep(RetryDelay);
            continue;
        }
        var processed = 0;           //  处理计数 , 每次循环初始 复制为0 , 一旦最后检测 仍然为0 即证明没有 挂单需要处理,结束while循环。
        for (var j = 0; j < orders.length; j++) {  //  遍历 orders 数组,访问每一个未成交的挂单。
            if (typeof(orderType) === 'number' && orders[j].Type !== orderType) {  // 如果指定了 参数orderType 只处理 orderType类型的挂单,其它跳过。
                continue;
            }
            e.CancelOrder(orders[j].Id, orders[j]);     //  取消当前索引的挂单。
            processed++;                                //  处理计数自加
            if (j < (orders.length - 1)) {              //  当前索引小于 数组orders 最后一个索引时 执行Sleep
                Sleep(RetryDelay);
            }
        }
        if (processed === 0) {       //  处理计数  等于 初始值 即没有 需要处理的挂单, 跳出 while 循环。
            break;
        }
    }
}
function GetAccount(e, waitFrozen) {  // 获取账户信息, 可以指定 是否等待冻结
    if (typeof(waitFrozen) == 'undefined') {  // 如果没有传入  waitFrozen 函数, 赋值 waitFrozen 为false
        waitFrozen = false;
    }
    var account = null;            // 声明一个变量
    var alreadyAlert = false;      // 声明一个变量, 用来标记 是否已经提醒过 。 false 为没有提醒。
    while (true) {
        account = _C(e.GetAccount);   //  调用API 获取当前账户信息
        if (!waitFrozen || (account.FrozenStocks < e.GetMinStock() && account.FrozenBalance < 0.01)) {
        // 如果不等待冻结,就不判断 (account.FrozenStocks < e.GetMinStock() && account.FrozenBalance < 0.01)
        // 即 符合 if 条件 执行以下 break; 语句。
            break;
        }
        if (!alreadyAlert) { // 如果 没提醒过 即 alreadyAlert 为 false
            alreadyAlert = true;     //  赋值为 true 标记为 已经提醒过。
            Log("发现账户有冻结的钱或币", account);   //  输出一条日志 提醒
        }
        Sleep(RetryDelay);
    } // 注意 : 如果有冻结的钱 或者 币  有可能一直卡在此处。
    return account;  //  返回账户信息
}
function StripOrders(e, orderId) {  // 该函数在 2.4 章节 也介绍过。
    var order = null;
    if (typeof(orderId) == 'undefined') {
        orderId = null;
    }
    while (true) {
        var dropped = 0;
        var orders = _C(e.GetOrders);
        for (var i = 0; i < orders.length; i++) {
            if (orders[i].Id == orderId) {
                order = orders[i];
            } else {
                var extra = "";
                if (orders[i].DealAmount > 0) {
                    extra = "成交: " + orders[i].DealAmount;
                } else {
                    extra = "未成交";
                }
                e.CancelOrder(orders[i].Id, orders[i].Type == ORDER_TYPE_BUY ? "买单" : "卖单", extra);
                dropped++;
            }
        }
        if (dropped === 0) {
            break;
        }
        Sleep(RetryDelay);
    }
    return order;
}
// mode = 0 : direct buy, 1 : buy as buy1
function Trade(e, tradeType, tradeAmount, mode, slidePrice, maxAmount, maxSpace, retryDelay) {
    // 交易函数,e:交易所对象 , tradeType:交易类型 , tradeAmount:交易数量, mode:模式, slidePrice:滑价, maxAmount:单次最大交易量, maxSpace: 最大挂单距离, retryDelay: 重试时间。
    var initAccount = GetAccount(e, true);  // 进入交易函数 初始时 获取账户信息。
    var nowAccount = initAccount;           // 声明一个 用于保存当前账户信息的变量,并初始化为 initAccount
    var orderId = null;                     // 声明一个用于保存 订单ID 的变量
    var prePrice = 0;                       // 上一次的价格
    var dealAmount = 0;                     // 已经处理过的(成交过的) 交易数量
    var diffMoney = 0;                      // 账户 钱之差
    var isFirst = true;                     // 是否是 第一次的循环的 标记
    var tradeFunc = tradeType == ORDER_TYPE_BUY ? e.Buy : e.Sell;   // 根据参数 tradeType 确定 调用API  Buy 还是 Sell 。让 tradeFunc 引用相应的API接口。 
    var isBuy = tradeType == ORDER_TYPE_BUY;  // 是否是 Buy的标记, 用 tradeFunc == ORDER_TYPEBUY 表达式的布尔值 初始化。
    while (true) {  // while 循环
        var ticker = _C(e.GetTicker);    // 获取当前行情数据。 
        // _C 不清楚的请查阅 平台论坛 相关帖子https://www.fmz.com/bbs-topic/320
        var tradePrice = 0;              // 初始交易价格 0
        if (isBuy) { // 如果是 买入操作
            tradePrice = _N((mode === 0 ? ticker.Sell : ticker.Buy) + slidePrice, 4); // 根据挂单模式 还是吃单模式,去计算下单价格, mode 为 当前函数的参数。
            // 对于 _N 不清楚的可以查询 https://www.fmz.com/bbs-topic/320 第7个问题。
        } else {
            tradePrice = _N((mode === 0 ? ticker.Buy : ticker.Sell) - slidePrice, 4);
        }
        if (!orderId) { // 判断 是否已经下单,没有执行以下。
            if (isFirst) { // 如果是第一次执行, 什么都不做
                isFirst = false;  // 标记为 false 即: 不是第一次执行 状态
            } else { // 之后判断 isFirst 都会为假 ,执行else
                nowAccount = GetAccount(e, true);  // 获取账户信息, 等待冻结。
            }
            var doAmount = 0;  // 初始化本次要处理的量 为0
            if (isBuy) {  //  如果是 买入操作 
                diffMoney = _N(initAccount.Balance - nowAccount.Balance, 4); // 每次记录 ,用于最后计算 成交均价
                dealAmount = _N(nowAccount.Stocks - initAccount.Stocks, 4);  // 实际已经 处理完成的量(成交)
                doAmount = Math.min(maxAmount, tradeAmount - dealAmount, _N((nowAccount.Balance - 10) / tradePrice, 4)); // 根据几个待选 值取最小的。
            } else {  //  处理 卖出的操作
                diffMoney = _N(nowAccount.Balance - initAccount.Balance, 4);
                dealAmount = _N(initAccount.Stocks - nowAccount.Stocks, 4);
                doAmount = Math.min(maxAmount, tradeAmount - dealAmount, nowAccount.Stocks);
            }
            if (doAmount < e.GetMinStock()) {  //  如果 要处理的量 小于 平台的最小成交量 ,即为 交易完成,跳出while循环
                break;
            }
            prePrice = tradePrice;  // 把本次循环计算出来的 交易价格 缓存再 prePrice 变量
            orderId = tradeFunc(tradePrice, doAmount, ticker);   // 下单 ,附带输出  ticker 数据
            if (!orderId) { // 如果 orderId 为 null ,取消所有挂单
                CancelPendingOrders(e, tradeType);
            }
        } else { // orderId 不等于 null 
            if (mode === 0 || (Math.abs(tradePrice - prePrice) > maxSpace)) { // 如果是挂单模式,超出挂单最大失效距离, 执行以下, 把 orderId 赋值 为 null 。
                orderId = null;
            }
            var order = StripOrders(e, orderId);  // 取消 除orderId 以外的所有挂单,并返回 orderId 的 order信息,如果orderId为null ,则取消全部挂单。
            if (!order) { 
                orderId = null;
            }
        }
        Sleep(retryDelay);
    }
    if (dealAmount <= 0) {  // 处理量 小于等于 0 , 即 无法操作,  交易失败,返回 null 
        return null;
    }
    return { // 返回 成功的交易信息,  成交均价、  成交数量。
        price: _N(diffMoney / dealAmount, 4),
        amount: dealAmount
    };
}
$.Buy = function(e, amount) {       // 导出函数  处理买入操作
    if (typeof(e) === 'number') {
        amount = e;
        e = exchange;
    }
    return Trade(e, ORDER_TYPE_BUY, amount, OpMode, SlidePrice, MaxAmount, MaxSpace, RetryDelay);
};
$.Sell = function(e, amount) {      // 导出函数   处理卖出操作
    if (typeof(e) === 'number') {
        amount = e;
        e = exchange;
    }
    return Trade(e, ORDER_TYPE_SELL, amount, OpMode, SlidePrice, MaxAmount, MaxSpace, RetryDelay);
};
$.CancelPendingOrders = function(e, orderType) {   // 导出函数  用于 取消所有未完成 挂单
    if (typeof(orderType) === 'undefined') {
        if (typeof(e) === 'number') {
            orderType = e;
            e = exchange;
        } else if (typeof(e) === 'undefined') {
            e = exchange;
        }
    }
    return CancelPendingOrders(e, orderType);
};
$.GetAccount = function(e) {     //  导出函数  用于 获取当前账户信息  区别于  GetAccount(e, waitFrozen)
    if (typeof(e) === 'undefined') {
        e = exchange;
    }
    return _C(e.GetAccount);
};
var _MACalcMethod = [TA.EMA, TA.MA, talib.KAMA][MAType];   // 附带 均线指标设置
// 返回上穿的周期数. 正数为上穿周数, 负数表示下穿的周数, 0指当前价格一样
$.Cross = function(a, b) {  // 均线交叉 函数,用于 判断 均线交叉 
    var crossNum = 0;       // 交叉周期计数
    var arr1 = [];          // 声明数组 arr1  用来 接收 指标数据 (数组结构)
    var arr2 = [];          // 声明数组 arr2  ....
    if (Array.isArray(a)) { // 判断 参数 传入的是 周期数 还是 计算好的 指标数据(数组)
        arr1 = a;           // 如果是 数组   就把   a 参数(即指标数组 )  赋值给  arr1 
        arr2 = b;           // ....
    } else {                // 如果传入的  a,b 不是 数组 ,是 周期数  执行一下。
        var records = null; // 声明  records 变量  初始化 null 
        while (true) {      // while 循环  用于确保  records K线数据 获取 符合标准
            records = exchange.GetRecords();        // 调用  GetRecords  这个 API 函数 获取K线数据
            if (records && records.length > a && records.length > b) {     // 判断 如果 records 获取到数据 并且 records K线数据 的 bar 个数(即 records 这个数组的长度) 大于 参数 周期数  a ,b  ,代表符合计算指标的要求。(bar 个数不够 是计算不出指标数据的)
                break;            //  满足 计算指标的 条件 就执行  break 跳出 while 循环
            }
            Sleep(RetryDelay);    //  不符合 条件 就在while 循环中  重复执行 获取 K线 ,这里 每次循环都Sleep 一下,避免 访问过于频繁。
        }
        arr1 = _MACalcMethod(records, a);     // 根据界面参数 MAType 的设置  引用 指标的函数名,在这里 传入K线数据,指标参数  周期数a  , 去计算 指标数据,指标数据返回给 arr1 
        arr2 = _MACalcMethod(records, b);     // MAType 是一个索引 ,根据 你界面上的设置 设置为相应的 索引 0 ~ n 自上而下, 这个索引 又确定了 [TA.EMA, TA.MA, talib.KAMA] 这个数组种  哪个  函数引用 赋值给  _MACalcMethod ,从而确定调用哪种 指标计算函数。
    }
    if (arr1.length !== arr2.length) {         // 如果计算出的 指标数据 长度 不一致 ,则抛出错误 。
        throw "array length not equal";        //  相同K线 计算出的 指标数据 长度 应当是一样的,不一样则异常
    }
    for (var i = arr1.length-1; i >= 0; i--) { // 从指标数据  数组 自后向前  遍历数组
        if (typeof(arr1[i]) !== 'number' || typeof(arr2[i]) !== 'number') {   // 读取到任何 指标数据不为数值类型的时候就跳出,即 指标数据 由于计算周期不同,有数据 为null 了,无法比较 ,所以 只用 arr1 arr2 都是有效值的数据。
            break;
        }
        if (arr1[i] < arr2[i]) {           // 此处 比较难以理解,由于crossNum 初始为0 , 不会触发一下 if 内的代码, arr1[i] 、arr2[i] 比较是 自后向前比较的, 即从离当前时间最近的 bar 的指标开始对比的, arr1[i] < arr2[i] 快线小于慢线,所以 在初始 crossNum 为0 的时候 ,快线小于慢线的 周期数 会持续记录在crossNum中, 直到 出现 arr1[i] > arr2[i] 的时候,此刻即 快线  慢线相交(这个时候break, crossNum 就是交叉后的周期数,最直观的就是 自己 模拟2组快慢线 数据数组,带入此处函数 根据逻辑 走一遍就明白了。)
            if (crossNum > 0) {
                break;
            }
            crossNum--;
        } else if (arr1[i] > arr2[i]) {
            if (crossNum < 0) {
                break;
            }
            crossNum++;
        } else {
            break;
        }
    }
    return crossNum;
};
// 仅调试模板策略用
function main() {
    Log($.GetAccount());
    Log($.Buy(0.5));
    Log($.Sell(0.5));
    exchange.Buy(1000, 3);
    $.CancelPendingOrders(exchanges[0]);
    Log($.Cross(30, 7));
    Log($.Cross([1,2,3,2.8,3.5], [3,1.9,2,5,0.6]));
}

연구하는 것을 좋아하는 동료는 Log ((1, XXX) 를 사용할 수 있습니다. 이 문서는 템플릿 논리가 실행되는 과정을 확인하고, 거래 세부 사항을 이해하는 데 도움이되는 실행 프로세스를 연구합니다.

  • 일반적인 템플릿은 이미 내장되어 있고, 정책을 만들면 정책 페이지의 템플릿 탭에서 일반적인 템플릿을 찾을 수 있습니다.

    예를 들어:

    img

    화살표 위치를 클릭하면 템플릿 소스 코드를 복사할 수 있습니다.


더 많은

이 연구는 마치 만약 당신의 단서가 항상 결제되지 않았다면, usdt가 얼어붙어있다면, 항상 거기에 붙어있을 것 같았습니다.

FangBei간단한 파이썬 템플릿의 예는 있나요?

픽시3173저는 Cross = function (a, b) 의 내적 논리를 잘 설명해야 한다고 생각합니다.

발명가들의 수량화 - 작은 꿈https://www.botvs.com/strategy/21104 이것은 파이썬 버전의 템플릿입니다.

픽시3173산업의 양심

발명가들의 수량화 - 작은 꿈이 강렬한 조사는 실제로 추상적이고, 코멘트는 이미 보완되어 있으며, 이해할 수 있습니다.