Loading ...

策略状态栏中构造交互按钮功能

Author: 小小梦, Created: 2017-06-13 15:24:05, Updated: 2018-03-16 18:32:58

策略状态栏中构造交互按钮功能

  • API 文档中的描述

    // 也可以构造一个按钮在表格中, 策略用GetCommand接收cmd属性的内容
    var table = {
        type: 'table',
        title: '持仓操作',
        cols: ['列1', '列2', 'Action'],
        rows: [
            ['abc', 'def', {'type':'button', 'cmd': 'coverAll', 'name': '平仓'}],
        ]
    };
    LogStatus('`' + JSON.stringify(table) + '`')
    // 或者构造一单独的按钮
    LogStatus('`' + JSON.stringify({'type':'button', 'cmd': 'coverAll', 'name': '平仓'}) + '`')
    // 可以自定义按钮风格(bootstrap的按钮属性)
    LogStatus('`' + JSON.stringify({'type':'button', 'class': 'btn btn-xs btn-danger', 'cmd': 'coverAll', 'name': '平仓'}) + '`')
    

    API文档可以看到在策略状态栏中显示 表格、字符串、图片、图表 等内容 都是通过调用 API 函数: LogStatus实现的。 我们还可以 通过 构造一个 JSON数据 来设定一个可交互的按钮。

  • DEMO 源码:

    function test1(p) {
        Log("调用自定义函数,参数:", p);
        return p;
    }
    function main() {
        while (true) {
            var table = {
                type: 'table',
                title: '持仓操作',
                cols: ['列1', '列2', 'Action'],
                rows: [
                    ['a', '1', {
                        'type': 'button',                       // 显示按钮 必须要 把 type 设置为 button 类型
                        'cmd': "CoverAll",                      // 字符串,发送的 数据,由GetCommand()函数接受。
                        'name': '平仓'                           // 按钮上显示的名字
                    }],
                    ['b', '1', {
                        'type': 'button',
                        'cmd': 10,                              // 数值
                        'name': '发送数值'
                    }],
                    ['c', '1', {
                        'type': 'button',
                        'cmd': _D(),                            // 函数 策略运行 期间会一直调用
                        'name': '调用函数'
                    }],
                    ['d', '1', {
                        'type': 'button',
                        'cmd': 'JScode:test1("ceshi")',       // 字符串, 用于执行的 JS 代码。
                        'name': '发送JS代码'
                    }]
                ]
            };
            LogStatus('`' + JSON.stringify(table) + '`')
    
            var str_cmd = GetCommand();
            if (str_cmd) {
                Log("接收到的交互数据 str_cmd:", "类型:", typeof(str_cmd), "值:", str_cmd);
            }
    
            if (str_cmd && str_cmd.split(':', 2)[0] == "JScode") {          // 判断是否有消息
                var js = str_cmd.split(':', 2)[1];                          // 分割 返回的消息 字符串, 限制返回2个, 把索引为1的 元素 赋值给 名为js 的变量 
                Log("执行调试代码:", js);                                     // 输出 执行的代码
                try {                                                       // 异常检测
                    eval(js);                                               // 执行 eval函数, 该函数执行传入的参数(代码)。
                } catch (e) {                                               // 抛出异常
                    Log("Exception", e);                                    // 输出错误信息
                }
            }
    
            Sleep(500);
        }
    }
    

    我们来实际运行一下,策略运行如图:

    img

    我们可以点击 状态栏 上表格内的按钮 触发交互,我们依次点击 “平仓”、“发送数值” 这两个按钮。

    点击 “平仓” 按钮的时候可以正常发送出消息:

    img

    > 但是点击  “发送数值” 的时候就不行了,原因是[ ```'cmd': 10,                              // 数值``` ]这里是 10  。不能发送数值类型。
    
    ![img](/upload/asset/2d8e0f86599f1b82da792544b7b840bc824d4a96.png) 
    # 已经优化 兼容了 数值,返回的 为数值形式的 字符串。
    

    接下来我们点击 “调用函数” 按钮, 用来测试被调用的函数是 _D() 函数,_D()函数会不停的返回当前的时间字符串,所以这里如果写函数调用,会不停的调用。

    img

    日志中会打印接收到的数据:

    img

    最后我们来点击 “发送JS代码” 按钮,我们可以执行我们代码中用来测试的自定义函数

    function test1(p) {
        Log("调用自定义函数,参数:", p);
        return p;
    }
    

    点击按钮:

    img

    可以看到 执行了函数 test1 中的 Log("调用自定义函数,参数:", p); 语句。

  • 代码中插入 'class': 'btn btn-xs btn-danger', 样式可以改变按钮的外观。

    img

    img

赶快动手练练吧!


More

fmzero 列2的数值,能不能做成输入类型?

hokshelato 实际测试结果和教程中的结果有出入。所有发送的数据都被解析为了 `string`,因此: 1. **发送数值**按钮是可以发送数值 `10` 的。 2. **调用函数**按钮触发的时候,`_D()` 函数已经被解析了,提示框询问的是“确定要向机器人发送命令 **2018-03-16 16:40:50** ?”,而且只被执行一次,并不像教程中说的会不停返回。 但是,如果我使用别的函数,如:`'cmd': Log(exchange.GetAccount()),`,机器人启动后即使没有按下按钮,也会不停返回数据。如果是 `'cmd': exchange.GetAccount(),`,触发按钮的时候提示是的“确定要向机器人发送命令 **[object Object]** ?”,`GetCommand()` 也无法获得具体返回的值。 所以,能否详细解释下 BotVS 对交互按钮中 `cmd` 属性的处理逻辑?

何先生 小小梦,除了可以在状态栏当中添加表格和按钮,其他的表单控件怎么添加,比如文本框

syxchina 这个厉害

指印足痕 梦总您好,感谢分享,但是能写一下Python版本的么?从 LogStatus('`' + JSON.stringify(table) + '`') 之后的开始就行 再就是JavaScript版本的我全文复制,运行后表格可以出现,但是点击按钮后没有输出 我是一步步按照这个来的 不知道是什么原因。打扰了,谢谢!

职业养鸡户 666 这个事件更丰富了

职业养鸡户 666 这个事件更丰富了

小小梦 暂时 状态栏的 控件类型只有一种 ,按钮。

小小梦 所以 才有 第四 个 按钮 : 发送JS代码, 这个就是 按下了 才去执行 对应的函数 或者 JS 代码。而不是 不停执行。

hokshelato 想通了,`'cmd': _D()` 本身是没有输出的,`'cmd': Log(_D())` 才会一直不停输出。但是,既然是希望通过按钮来触发的,为什么 `cmd` 中的函数会一直在被调用呢?这样的设计似乎不妥吧?

hokshelato 不好意思,有点迷糊了。您代码中的 `test1(a++)` 是会不停输出,也正如我前面说的,即便我没有按下那个按钮,机器人一启动就在那儿输出了。可为什么如果换成`_D()` 就不会有输出,而必须通过按钮才能触发?

小小梦 第2点 您可能 理解错了, 我说的 不停调用是 指: 在整个程序 运行期间, 每次这个 _D() 都会 返回一个新的时间,用作这个 按钮的 命令。 并不是说 卡在这个 位置 一直调用_D()。您第一次 点击 调用函数按钮触发 提示框: 2018-03-16 16:40:50 , 下次 再点击的时候 显示 就是 另外一个时间了。 其实 就是 _D()每次策略循环 都在被调用。 我的代码 你测试下, 会不停输出,亲测。 ``` var a = 0 function test1(p) { Log("调用自定义函数,参数:", p); return p; } function main() { while (true) { var table = { type: 'table', title: '持仓操作', cols: ['列1', '列2', 'Action'], rows: [ ['a', '1', { 'type': 'button', // 显示按钮 必须要 把 type 设置为 button 类型 'cmd': "CoverAll", // 字符串,发送的 数据,由GetCommand()函数接受。 'name': '平仓' // 按钮上显示的名字 }], ['b', '1', { 'type': 'button', 'cmd': 10, // 数值 'name': '发送数值' }], ['c', '1', { 'type': 'button', 'cmd': test1(a++), // 函数 策略运行 期间会一直调用 'name': '调用函数' }], ['d', '1', { 'type': 'button', 'cmd': 'JScode:test1("ceshi")', // 字符串, 用于执行的 JS 代码。 'name': '发送JS代码' }] ] }; LogStatus('`' + JSON.stringify(table) + '`') var str_cmd = GetCommand(); if (str_cmd) { Log("接收到的交互数据 str_cmd:", "类型:", typeof(str_cmd), "值:", str_cmd); } if (str_cmd && str_cmd.split(':', 2)[0] == "JScode") { // 判断是否有消息 var js = str_cmd.split(':', 2)[1]; // 分割 返回的消息 字符串, 限制返回2个, 把索引为1的 元素 赋值给 名为js 的变量 Log("执行调试代码:", js); // 输出 执行的代码 try { // 异常检测 eval(js); // 执行 eval函数, 该函数执行传入的参数(代码)。 } catch (e) { // 抛出异常 Log("Exception", e); // 输出错误信息 } } Sleep(500); } } ``` 第一个问题 : 数值 类型 现在兼容了,这个也亲测,我修改下文档。 感谢提出建议 ^^

小小梦 哦 目前暂时 只实现了 状态栏表格里 添加 按钮控件, 其他控件 还没有支持 ^^ 。

小小梦 哦 明白了 , 回测是不会显示触发的, 因为回测很快 ,没时间触发,所以就没这个机制。模拟盘 实盘都是可以的 ,亲测!

指印足痕 哦哦 我用的是在线回测,没有添加托管者, 我晚上回家用自己电脑试一下,真是麻烦了

小小梦 您好 ~ 感谢支持, 我前一段写了一个 Python 的模板 ,您可以看下这个帖子 :https://www.botvs.com/bbs-topic/975 策略 在: https://www.botvs.com/strategy/46031 另外上面的代码 我直接复制 用实盘跑了一下: https://dn-filebox.qbox.me/68a8bbbddf26ebcd597efc54f7d6ebee6c1703e4.png 按钮有响应, 我感觉是不是 您的托管者版本 比较老了, 这个功能是最近增加的,您可以尝试 更新一下托管者 用最新版本试下。

小小梦 您好 ~ 感谢支持, 我前一段写了一个 Python 的模板 ,您可以看下这个帖子 :https://www.botvs.com/bbs-topic/975 策略 在: https://www.botvs.com/strategy/46031