HQChart使用教程60-新版k线训练使用教程

样例页面

手机端页面 https://opensource2.zealink.com/hqweb/demo/demo_ktrain.html
手机端横屏页面 https://opensource2.zealink.com/hqweb/demo/demo_ktrain2.html

K线训练重构

老的K训练缺陷:

  1. 算法比较单一, 只能买一卖一, 无法一条数据上多次卖买。
  2. K线回放只是简单的在显示的时候限制数据个数,而不是数据一个一个的增加.导致复权和有些指标计算会不正确.
  3. 不支持数据拖拽,手机端手势操作

基于这些缺陷, 决定重构新版本的K线训练.
 1.  支持一条K线上多次买卖,这样就可以训练T+0的模拟
 2.  支持移动端手势和PC鼠标对数据的操作,缩放,移动等
 3.  模拟K线回放,数据是一个一个的增加.

创建K线图

通过setoption来创建K线训练图, option参数和K线图参数一致。type使用K线训练
Type: ‘K线训练’ 横屏使用 “K线训练横屏”
Train K线训练配置

  1. DataCount: 训练数据个数
  2. StartDate: 数据训练的起始位置 { Date:日期, Time:时间(分钟K线训练使用) }
    下面是一个创建K线训练的配置, 使用600000股票训练,从20180201 开始训练,训练200个数据
this.Option = 
{
    Type: 'K线训练',
    Windows: //窗口指标
    [
        //{Index:"EMPTY"},
        {Index:"MA", Modify:false,Change:false},
        {Index:"VOL", Modify:false,Change:false}
    ], 
    Symbol: "600000.sh",
    IsAutoUpate: false,       //是自动更新数据

    IsShowRightMenu: false,    //右键菜单
    CorssCursorTouchEnd:true,  
    
    CorssCursorInfo:{ Left:0, Right:2, Bottom:1, IsShowCorss:true },

    KLine:
    {
        Right: 0,                    //复权 0 不复权 1 前复权 2 后复权
        Period: 0,                   //周期 0 日线 1 周线 2 月线 3 年线 
        MaxReqeustDataCount: 2000,   //数据个数
        PageSize: 50,               //一屏显示多少数据
        IsShowTooltip: false,                 //是否显示K线提示信息
        RightSpaceCount:2,
    },

    KLineTitle: //标题设置
    {
        IsShowName: false,         //不显示股票名称
        IsShowSettingInfo: false,  //不显示周期/复权
        IsShowDateTime:true
    },

    Border: //边框
    {
        Top:1,
        Left: 1,    //左边间距
        Right: 1     //右边间距
    },

    Frame:  //子框架设置
    [
        { SplitCount: 3, IsShowLeftText:false },
        { SplitCount: 2, IsShowLeftText:false }
    ],

    Train:
    {
        DataCount:200,                   //训练数据
        StartDate:{ Date:20180201 }
    },

    ExtendChart:    //扩展图形
    [
        { Name:'KLineTooltip' },  //手机端tooltip
        { Name:'背景图', FrameID:0 }
    ],
}

操作接口

K线训练接口没有对外开放,可以通过内部图形实例来操作
this.Chart.JSChartContainer JSChartContainer就是hqchart实例的内部图形实例变量, 所有K线训练操作都通过调用它的成员函数来实现。

下一个K线

MoveNextKLineData(option)
移动一个K线
option可选, k不填默认移动一个K线
{
PageSize: 移动以后一屏显示多少个数据(可选) 默认是当前的数据个数一致
Step:移动一个K线,(可选), 默认移动1个K线
}

this.MoveNextKLine=function()
{
    this.Chart.JSChartContainer.MoveNextKLineData();
}

自动/停止自动移动K线

Run(option)/Stop()

Run(option)
option可选, 不填每次移动1个K线
option和 MoveNextKLineData()里的option设置一致

this.Run=function()
{
    this.Chart.JSChartContainer.Run();
}

this.Stop=function()
{
    this.Chart.JSChartContainer.Stop();
}

买卖股票

BuyOrSell=function(data, isDraw);
data 买卖股票的数据 { Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 }
isDraw 是否更新图形
可以多次买卖无限制

扫描二维码关注公众号,回复: 11360608 查看本文章
this.Sell=function()    
{
    .....
    ++this.OrderID;
    //以最新价格卖出
    var data={ Price:this.LatestKData.Close, Vol:10 ,Op:1 , ID:this.OrderID }; //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 }
    ......

    this.Chart.JSChartContainer.BuyOrSell(data, false); 
    this.Chart.JSChartContainer.MoveNextKLineData();	//卖了股票移动到下一个K线上
}

this.Buy=function()
{
    ........
    ++this.OrderID;
    //以最新价格买入
    var data={ Price:this.LatestKData.Close, Vol:10 ,Op:0 , ID:this.OrderID }; //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 }
    ........
    this.Chart.JSChartContainer.BuyOrSell(data, false);
    this.Chart.JSChartContainer.MoveNextKLineData(); //买了股票移动到下一个K线上
}

K线移动监听事件

事件ID JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP
回调函数格式 function(event,data,obj)
event 注册的事件信息
data k训练信息

  1. TrainDataCount: 剩余训练数据个数
  2. BuySellData 所有的买卖数据
  3. LastData 最新一条K线原始数据(为复权或计算周期的)
  4. LastShowData 最新一条K线显示数据 (已复权或已计算周期的)
  5. KLine K线信息 { Start 训练起始位置, End 当前最后一个数据位置 }

obj k线训练内部实例

 this.Create=function()  //创建图形
 {
      var self=this;
      $(window).resize(function() { self.OnSize(); });    //绑定窗口大小变化事件

      var blackStyle=HQChartStyle.GetStyleConfig(STYLE_TYPE_ID.BLACK_ID); //读取黑色风格配置
      //JSChart.SetStyle(blackStyle);
      //this.DivKLine.style.backgroundColor=blackStyle.BGColor; //设置最外面的div背景

      this.OnSize();  //让K线全屏
      this.Chart.SetOption(this.Option);  //设置K线配置
		
	   //注册K线移动监听事件
      this.Chart.AddEventCallback({ 
          event:JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP, 
          callback:(event,data,obj)=> { this.OnKLineMove(event,data,obj); }
      });
}

//K线移动事件回调, 把最后的K线信息显示到元素上。
this.OnKLineMove=function(event,data,obj)
{
    console.log("[KLineChart::OnKLineMove] data", data);

    this.LatestKData=data.LastShowData;

    var dateTime=`日期:${this.LatestKData.Date}`;
    if (this.LatestKData.Time)  dateTime=`日期:${this.LatestKData.Date} 时间:${this.LatestKData.Time}`;

    //更新界面显示信息
    var message=`状态:${data.Description} ${dateTime} 最新价格: ${this.LatestKData.Close.toFixed(2)} 剩余数据:${data.TrainDataCount}`;
   
    $("#traininfo")[0].innerText=message;

    if (data.TrainDataCount<=0) this.LatestKData=null;
}

重新开始训练

RestartTrain=function(option)
option:
{
Symbol:训练的股票
Train:{ DataCount:训练数据格式, DateTime{ Date:训练起始日期, Time:训练起始时间(分钟K线才有)}
Period: 周期
Right: 复权
}

 //重新开始训练
    this.RestartTrain=function()   
    {
        //外部清空上一次训练数据
       .......
        var option=
        { 
            Symbol:"000001.sz", 
            Train:{ DataCount:30, DateTime: { Date:20190301 } } ,
            Period:0,   //周期
            Right:1,    //复权
        }
        this.Chart.JSChartContainer.RestartTrain(option);
    }
}

买卖数据计算

由于训练成绩的规则会根据业务需求调整,所有k线训练内部不计算成绩, 有外部自行计算收益和成绩,你可以通过卖入价和卖出价简单的统计胜率, 或使用初始资金,买卖股票,最后通过持仓计算最后资金来计算复杂收益

K线背景色设置功能

为了在UI上直观的体现用户在训练的时候那次操作时赚钱的,那次操作时赔钱的。我增加了K线背景色的设置,可以设置一个时间区间段的颜色。效果如下图
在这里插入图片描述

  1. 创建
    在setoption里面(ExtendChart)创建背景色的画法并绑定到第1个窗口
    Name:固定背景图
    FrameID: 绑定窗口的索引
 ExtendChart:    //扩展图形
[
     { Name:'KLineTooltip' },  //手机端tooltip
     { Name:'背景图', FrameID:0 }
 ],
  1. 获取背景色画法实例
    遍历所有的扩展画法,找到背景色画法实例
this.GetBGChartPaint=function()
{
    for(var i in this.Chart.JSChartContainer.ExtendChartPaint) 
    {
        var item=this.Chart.JSChartContainer.ExtendChartPaint[i];
        if (item.ClassName=='BackgroundPaint') return item;
    }

    return null;
}
  1. 设置背景色
    data:[ ] 背景色数组
    单个背景数据结构
{ Start: 起始位置
   {Date:日期, Time:时间(分钟K线才有)}, 
 End:  结束位置
 { Date:日期, Time:时间(分钟K线才有) } ,
 Color:背景颜色 'rgba(200,200,200,0.5)
};
//计算成绩
this.CalulateScore=function()
{
    var count=0, success=0;
    var aryBGData=[];   //背景颜色
    
    .... 生成背景色数据

    var bgPaint=this.GetBGChartPaint();
    if (bgPaint) bgPaint.Data=aryBGData; //设置到背景色画法里面
}

买卖图标修改

通过获取全局的资源配置修改K线训练的配置就可以。
HQChart使用教程4- 如何自定义K线图颜色风格

图标使用SVG, Family 为iconfont字体名字 Text:为竖屏图标字符 HScreenText:为横屏字符。 横屏和竖屏使用2个不同的图标字符。
下面是h5用的。

this.KLineTrain = 
{
    IconFont:
    {
        Family:'iconfont',  
        Buy:{ Text:'\ue64a', HScreenText:'\ue68a' ,Color:'rgb(255,140,0)' }, //买
        Sell:{ Text:'\ue64b', HScreenText:'\ue68a' ,Color:'rgb(6,79,18)' },  //卖
        Last:{ Text:'\ue681', HScreenText:'\ue68a' ,Color:'rgb(55,0,255)' }, //最后一个K线
    }
};

小程序和uniapp画布都不支持SVG. 只能是文字输出作为买卖图标,比SVG效果要差好多(平台不行我也没办法)
读取全局资源配置,修改下面的配置就可以

this.KLineTrain = {
 Font:'bold 14px arial',
  LastDataIcon: {Color:'rgb(0,0,205)',Text:'⬇'},
  BuyIcon: {Color:'rgb(0,205,102 )',Text:'B'},
  SellIcon: {Color:'rgb(255,127,36 )',Text:'S'},
}

完整代码

就贴一个竖屏的吧,横屏的都一样,就UI布局改下,具体看demo页面源码就可以了,我就不贴出来了。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  

    <title>K线图训练(手机)</title>  
    <!-- 加载资源 -->
    <link rel="stylesheet" href="../jscommon/umychart.resource/css/tools.css" />
    <link rel="stylesheet" href="../jscommon/umychart.resource/font/iconfont.css" />

    <style>
        .line-box{
            height: 25px;
        }
        .btn-style{
            padding: 3px 8px;
            border: 1px solid #ececec;
            border-radius: 5px;
            background-color: #f5f5f5;
            cursor: pointer;
        }
            
    </style>
</head>  
<body>
    <div id="kline" style="width: 900px;height:400px;position: relative;"></div>
    <div class="line-box">
        <span class="btn-style" id='nextkline'>下一K线</span>
        <label>
            <input type="checkbox" id='autorun' /> K线自动前进
        </label>
        <span class="btn-style" id='reset'>重新开始</span>
    </div>
    <div class="line-box">
        <span class="btn-style" id='buy'>[]</span>
        <span class="btn-style" id='sell'>[]</span>
    </div>
    <div>
        <span id='traininfo'>加载中......</span>
       
    </div>
    <div>
        <span id='traininfo2'>成绩:</span>
    </div>

    <script src="content/js/jquery.min.js"></script>
    <script src="content/js/webfont.js"></script>
    <script src='../jscommon/umychart.console.js'></script>     <!-- 日志输出 -->
    <script src="../jscommon/umychart.network.js"></script>     <!-- 网络请求分装 -->
    <script src="../jscommon/umychart.js"></script>             <!-- K线图形 -->
    <script src="../jscommon/umychart.complier.js"></script>    <!-- 麦语言解析执行器 -->
    <script src="../jscommon/umychart.index.data.js"></script>  <!-- 基础指标库 -->
    <script src="../jscommon/umychart.style.js"></script>       <!-- 白色风格和黑色风格配置信息 -->
    
    <script>

        //JSConsole.Chart.Log=() =>{}
        //JSConsole.Complier.Log=()=>{}

        //简单的把K线控件封装下
        function KLineChart(divKLine)
        {
            this.DivKLine=divKLine;
            this.Chart=JSChart.Init(divKLine);   //把K线图绑定到一个Div上
            this.LatestKData;   //最新的K线数据
            this.LatestTrade;   //最新一条交易记录
            this.AryTrade=[];   //交易记录 {Buy:, Sell:} 成对

            this.ClearDivDOM=function()     
            {
                var childList = this.DivKLine.childNodes;
                for(var i in childList)
                {
                    this.DivKLine.removeChild(childList[i]);
                }
            }

            //K线配置信息
            this.Option = {
                Type: 'K线训练',
                Windows: //窗口指标
                [
                    //{Index:"EMPTY"},
                    {Index:"MA", Modify:false,Change:false},
                    {Index:"VOL", Modify:false,Change:false}
                ], 
                Symbol: "600000.sh",
                IsAutoUpate: false,       //是自动更新数据

                IsShowRightMenu: false,    //右键菜单
                CorssCursorTouchEnd:true,  
                
                CorssCursorInfo:{ Left:0, Right:2, Bottom:1, IsShowCorss:true },

                KLine:
                {
                    Right: 0,                    //复权 0 不复权 1 前复权 2 后复权
                    Period: 0,                   //周期 0 日线 1 周线 2 月线 3 年线 
                    MaxReqeustDataCount: 2000,   //数据个数
                    PageSize: 50,               //一屏显示多少数据
                    IsShowTooltip: false,                 //是否显示K线提示信息
                    RightSpaceCount:2,
                },

                KLineTitle: //标题设置
                {
                    IsShowName: false,         //不显示股票名称
                    IsShowSettingInfo: false, //不显示周期/复权
                    IsShowDateTime:true
                },

                Border: //边框
                {
                    Top:1,
                    Left: 1,    //左边间距
                    Right: 1     //右边间距
                },

                Frame:  //子框架设置
                [
                    { SplitCount: 3, IsShowLeftText:false },
                    { SplitCount: 2, IsShowLeftText:false }
                ],

                Train:
                {
                    DataCount:200,                   //训练数据
                    //StartDate:{ Date:20180201 }
                },

                ExtendChart:    //扩展图形
                [
                    { Name:'KLineTooltip' },  //手机端tooltip
                    { Name:'背景图', FrameID:0 }
                ],
            }
                 
            this.Create=function()  //创建图形
            {
                var self=this;
                $(window).resize(function() { self.OnSize(); });    //绑定窗口大小变化事件

                var blackStyle=HQChartStyle.GetStyleConfig(STYLE_TYPE_ID.BLACK_ID); //读取黑色风格配置
                //JSChart.SetStyle(blackStyle);
                //this.DivKLine.style.backgroundColor=blackStyle.BGColor; //设置最外面的div背景

                this.OnSize();  //让K线全屏
                this.Chart.SetOption(this.Option);  //设置K线配置

                this.Chart.AddEventCallback({ 
                    event:JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP, 
                    callback:(event,data,obj)=> { this.OnKLineMove(event,data,obj); }
                });
            }

            this.OnSize=function()  //自适应大小调整
            {
                var height= $(window).height()-90;
                var width = $(window).width();
                this.DivKLine.style.top='px';
                this.DivKLine.style.left='px';
                this.DivKLine.style.width=width+'px';
                this.DivKLine.style.height=height+'px';
                this.Chart.OnSize();
            }

            this.MoveNextKLine=function()
            {
                this.Chart.JSChartContainer.MoveNextKLineData();
            }

            this.Run=function()
            {
                this.Chart.JSChartContainer.Run();
            }

            this.Stop=function()
            {
                this.Chart.JSChartContainer.Stop();
            }

            this.OnKLineMove=function(event,data,obj)
            {
                console.log("[KLineChart::OnKLineMove] data", data);

                this.LatestKData=data.LastShowData;

                var dateTime=`日期:${this.LatestKData.Date}`;
                if (this.LatestKData.Time)  dateTime=`日期:${this.LatestKData.Date} 时间:${this.LatestKData.Time}`;

                //更新界面显示信息
                var message=`状态:${data.Description} ${dateTime} 最新价格: ${this.LatestKData.Close.toFixed(2)} 剩余数据:${data.TrainDataCount}`;
               
                $("#traininfo")[0].innerText=message;

                if (data.TrainDataCount<=0) this.LatestKData=null;
            }

            this.OrderID=10;        //模拟单号

            this.Sell=function()    
            {
                if (!this.LatestKData) return;

                ++this.OrderID;
                //以最新价格卖出
                var data={ Price:this.LatestKData.Close, Vol:10 ,Op:1 , ID:this.OrderID }; //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 }
                this.LatestTrade=data;
                var tradeItem=this.AryTrade[this.AryTrade.length-1];
                tradeItem.Sell={ Price:data.Price, ID:data.ID , Date:this.LatestKData.Date, Time:this.LatestKData.Time };
                this.CalulateScore();

                $("#sell").hide();
                $("#buy").show();

                this.Chart.JSChartContainer.BuyOrSell(data, false);
                this.Chart.JSChartContainer.MoveNextKLineData();
            }

            this.Buy=function()
            {
                if (!this.LatestKData) return;

                ++this.OrderID;
                //以最新价格买入
                var data={ Price:this.LatestKData.Close, Vol:10 ,Op:0 , ID:this.OrderID }; //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 }
                this.LatestTrade=data;

                var tradeItem={ Buy:{Price:data.Price, ID:data.ID, Date:this.LatestKData.Date, Time:this.LatestKData.Time } };
                this.AryTrade.push(tradeItem);

                $("#buy").hide();
                $("#sell").show();

                this.Chart.JSChartContainer.BuyOrSell(data, false);
                this.Chart.JSChartContainer.MoveNextKLineData();

                this.CalulateScore();
            }

            //计算成绩
            this.CalulateScore=function()
            {
                var count=0, success=0;
                var aryBGData=[];   //背景颜色
                for(var i in this.AryTrade)
                {
                    var item=this.AryTrade[i];
                    if (!item.Buy || !item.Sell) continue;

                    var bgItem={ Start:{Date:item.Buy.Date, Time:item.Buy.Time}, End:{ Date:item.Sell.Date, Time:item.Sell.Time } };
                    if (item.Buy.Price<item.Sell.Price) 
                    {
                        ++success;
                        bgItem.Color='rgba(250,128,114,0.5)';
                    }
                    else
                    {
                        bgItem.Color='rgba(152,251,152,0.5)';
                    }

                    aryBGData.push(bgItem);
                    ++count;
                }
                
                var result=0;
                if (count>0) result=success/count;
                var message=`成绩:交易次数${count} 成功次数${success} 胜率:${result.toFixed(2)}`;
                $("#traininfo2")[0].innerText=message;

                var bgPaint=this.GetBGChartPaint();
                if (bgPaint) bgPaint.Data=aryBGData;
            }

            this.GetBGChartPaint=function()
            {
                for(var i in this.Chart.JSChartContainer.ExtendChartPaint)
                {
                    var item=this.Chart.JSChartContainer.ExtendChartPaint[i];
                    if (item.ClassName=='BackgroundPaint') return item;
                }

                return null;
            }

            //重新开始训练
            this.RestartTrain=function()   
            {
                this.AryTrade=[];
                this.LatestKData=null;
                this.LatestTrade=null;
                $("#traininfo2")[0].innerText='成绩:';
                $("#traininfo")[0].innerText='加载中......';
                $("#buy").show();
                $("#sell").hide();

                var bgPaint=this.GetBGChartPaint();
                if (bgPaint) bgPaint.Data=null;

                var option=
                { 
                    Symbol:"000001.sz", 
                    Train:{ DataCount:30, DateTime: { Date:20190301 } } ,
                    Period:0,   //周期
                    Right:1,    //复权
                }
                this.Chart.JSChartContainer.RestartTrain(option);
            }
        }

        $(function () 
        {
            WebFont.load({ custom: { families: ['iconfont'] } });   //预加载下iconfont资源

            var klineControl=new KLineChart(document.getElementById('kline'));
            klineControl.Create();

            $("#nextkline").click(function() { klineControl.MoveNextKLine()} );
            $("#autorun").click(function() 
            { 
                if (this.checked) klineControl.Run();
                else klineControl.Stop();
            });

            $("#buy").click(function() { klineControl.Buy()} );
            $("#sell").click(function() { klineControl.Sell({ Price:8.2, Vol:14 , Op:1 })} );
            $("#reset").click(function() { klineControl.RestartTrain()} );

            $("#buy").show();
            $("#sell").hide();
        })

    </script>  
</body>  
</html>




如果还有问题或新的需求可以加交流QQ群: 950092318

HQChart代码地址

地址:https://github.com/jones2000/HQChart

如果教程或hqchart对你有帮助, 请在git上star,教程点下赞 。谢谢~~

猜你喜欢

转载自blog.csdn.net/jones2000/article/details/105760924