期货CTP接口与K线模块的对接(1)

先做一个练习。
这是用tick生成K线的练习。
这里的tick是程序随机生成的。
通过这个练习,了解K线生成的逻辑。
练习效果如下图所示(加了一些花活儿,实盘所用的K线比这简单)。
在这里插入图片描述
下面是练习步骤。
一、在VisualStudio中新建项目“BarsTest”,这是一个C#的窗体程序,主窗体为“Form1.cs”,尺寸为576×540。
二、在该窗体中放一个PictureBox,命名为“panel”,尺寸为528×468。
三、将“Form1.cs”的源码修改为如下内容:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace BarsTest
{
   
    public partial class Form1 : Form
    {
   
        int intvTicks = 60; //K线每分钟多少个tick
        int blackAlpha = 255; //黑色的不透明度
        int blackAlphaAdd = -45; //黑色不透明度的增量
        int whiteAlpha = 255; //白色的不透明度
        int whiteAlphaAdd = -30; //白色不透明度的增量
        string whiteText1 = String.Empty; string whiteText2 = String.Empty; //白色文字
        int panelWidth = 0; int panelHeight = 0; //画板尺寸
        int leftMargin = 10; int rightMargin = 10; int topMargin = 0; int bottomMargin = 20; //画板边距
        int diagramWidth = 0; int diagramHeight = 0; //K线组显示尺寸
        int barWidth = 16; //K线宽度
        int barsIntv = 0; //K线间距
        int barsCount = 0; //画板中的K线数量
        int startPrice = 5000; //初始价格
        int uppLP = 10000; //涨停价
        int lowLP = 2000; //跌停价
        List<Bar> bars = new List<Bar>(); //K线组
        bool newBarCreated = false; //画板上显示K线以后是否产生过新K线
        int barsN = 0; //K线数量
        int startI = 0; //画板中最左端K线的序号
        int barsH = 0; //画板中所有K线的最高价
        int barsL = 1000000; //画板中所有K线的最低价
        double barsPP = 1; //画板纵向密度(价格每变化1,高度变化多少像素)
        double endBarX = 0; //飞起来的末端K线左边的横坐标
        int endBarInitialX = 0; //固定的末端K线左边的横左边
        double endBarY = 0; //飞起来的末端K线开盘价的纵坐标
        int endBarInitialY = 0; //固定的末端K线开盘价的纵坐标
        int lastHY = 0; //上一根末端K线最高价的纵坐标
        int lastLY = 0; //上一根末端K线最低价的纵坐标
        int shiftDirectionX = 1; int shiftDirectionY = -1; double shiftX = 1.5; double shiftY = 1.5; //关于末端K线移动的几个变量
        bool backHome = false; //末端K线是不是正在返回起点
        Color barColor = Color.FromArgb(100, 100, 120); //K线默认颜色
        Color endBarColor = Color.FromArgb(255, 120, 120, 120); //末端K线颜色
        Color triColorB = Color.DarkOrange; //买条件单颜色
        Color triColorS = Color.DarkSeaGreen; //卖条件单颜色
        Color longCostColor = Color.Magenta; //多仓成本线颜色
        Color shortCostColor = Color.Cyan; //空仓成本线颜色
        Color orderColor = Color.White; //挂单线颜色
        int endBarAlpha = 255; //末端K线不透明度
        int brightestIndex = 0; //除了末端K线,最亮的K线的序号
        int addBrightestIndexIntv = 2; //行情走多少个tick加一次brightestIndex
        int addBrightestIndexTicks = 0; //最近干这事时的timer3Ticks
        int textID = 4; //飞起来的K线的文字的序号
        int winY = 0; //刚刚止盈的价格的纵坐标
        List<Order> orderInfo = new List<Order>(); //挂单信息
        int maxOrdID = 3; //最大报单序号
        int vol = 0; //持仓手数
        double cost = 0; //持仓平均成本
        int stopPrice = 0; //止损价
        int initialStopPrice = 0; //初始止损价
        int stopStep = 3; //止损步长
        int stepBH = 0; //有关买入后最高价的步长
        int stepSL = 0; //有关卖出后最低价的步长
        int assignedDirection = 0; //指定的开仓方向(防止同向反复开仓)
        int deals = 0; //交易次数
        int floatProfit = 0; //浮盈
        int closeProfit = 0; //平盈
        int maxProfit = 0; //盈利峰值
        int maxReduce = 0; //最大回撤
        int winLots = 0; //盈利手数
        int winAmt = 0; //盈利交易的总额
        int lossLots = 0; //亏损手数
        int lossAmt = 0; //亏损交易的总额

        public Form1()
        {
   
            InitializeComponent();
            panelWidth = panel.Width; panelHeight = panel.Height; //测量画板尺寸
            topMargin = panelHeight / 5; //预先确定画板上方空白高度
            diagramWidth = panelWidth - leftMargin - rightMargin; //算出画板画图部分的宽度
            diagramHeight = panelHeight - topMargin - bottomMargin; //算出画板画图部分的高度
            timer2 = new System.Windows.Forms.Timer();
            timer2.Interval = 250;
            timer2.Tick += new System.EventHandler(this.timer2_Tick);
            timer2.Stop();
            timer3 = new System.Windows.Forms.Timer();
            timer3.Interval = 25;
            timer3.Tick += new System.EventHandler(this.timer3_Tick);
            timer3.Stop();
            #region //创建每分钟intvTicks个tick的K线N根
            updateBarsCount(); //根据画板宽度、已经预先确定的K线宽度,算出画板可容纳多少根K线
            barsN = randomInt(5, 10); //随机确定初始K线根数
            if (barsN > barsCount) startI = barsN - barsCount; //初始K线根数不能超过画板容量
            int O = startPrice; //这是首根初始K线的开盘价,由此开始计算每根初始K线的开、高、低、收
            for (int i = 0; i < barsN; i++) //对每根初始K线来说
            {
   
                int change = 0; //在每分钟的intvTicks个tick中,每个tick的价格变化跳数在-1~1间取随机数,change是这1分钟的总数
                int maxAdd = 0; //这期间,价格增加的跳数最多曾达到多少
                int maxMinus = 0; //这期间,价格减少的跳数最多曾达到多少
                for (int j = 0; j < intvTicks; j++) //遍历这intvTicks个tick
                {
   
                    change += randomInt(-1, 1); //价格随机变化
                    if (O + change > uppLP) change = uppLP - O;
                    else if (O + change < lowLP) change = lowLP - O;
                    if (change > maxAdd) maxAdd = change;
                    if (change < maxMinus) maxMinus = change;
                }
                int H = O + maxAdd; //当前K线的最高价
                int L = O + maxMinus; //当前K线的最低价
                int C = O + change; //当前K线的收盘价
                Bar bar = new Bar();
                bar.O = O; bar.H = H; bar.L = L; bar.C = C;
                bars.Add(bar); //将当前K线添加到K线组中
                O = C; //当前K线的收盘价成为下一根K线的开盘价
            }
            updateBarsMainHLPP(); //更新画板上的最高价、最低价、纵向密度
            endBarInitialX = leftMargin + (barsN - 1 - startI) * barsIntv;
            endBarX = endBarInitialX;
            endBarInitialY = priceToY(bars.Last().O);
            endBarY = endBarInitialY;
            brightestIndex = barsN - 2; //初始化有关画图的一些数据
            refreshPanel(); //刷新画板
            #endregion
            timer2.Start();
        }

        /*更新画板可容纳的K线数量*/
        void updateBarsCount()
        {
   
            barsIntv = (int)(Math.Ceiling((double)barWidth * 1.4)); //根据预设的K线宽度,计算K线间距
            barsCount = diagramWidth / barsIntv; //根据画板宽度和K线间距,算出画板可容纳的K线数量
            if (barsCount < 2) barsCount = 2;
        }

        /*更新画板上的最高价、最低价、纵向密度*/
        void updateBarsMainHLPP()
        {
   
            int highest = 0; int lowest = 1000000;
            int i = startI; while (i < barsN) //遍历画板上的K线,找出其最高价、最低价
            {
   
                int thisH = bars[i].H; if (thisH > highest) highest = thisH;
                int thisL = bars[i].L; if (thisL < lowest) lowest = thisL;
                i++;
            }
            barsH = highest; barsL = lowest;
            updateBarsMainPP(); //计算纵向密度
        }

        /*更新纵向密度*/
        void updateBarsMainPP()
        {
   
            int HL = barsH - barsL;
            if (HL >= 0)
            {
   
                if (HL == 0) HL = 1;
                barsPP = (double)diagramHeight / (double)HL; //纵向密度=画板高度 / 画板内K线所占高度
            }
        }

        /*将价格转换为画板上的纵坐标*/
        int priceToY(double price)
        {
   
            return topMargin + (int)(barsPP * (barsH - price));
        }

        /*根据价格price与末端K线开盘价的差距,计算price的纵坐标*/
        int endPriceY(int price)
        {
   
            int endBarO = bars.Last().O; //末端K线的开盘价
            int priceChange = endBarO - price; //price与末端K线开盘价的差距
            int yChange = (int)(barsPP * priceChange); //price的纵坐标与末端K线开盘价纵坐标的差距
            return (int)(endBarY + yChange); //price的纵坐标
        }

        /*刷新画板*/
        void refreshPanel()
        {
   
            Bitmap bitmap = new Bitmap(panelWidth, panelHeight);
            Graphics draw = Graphics.FromImage(bitmap);
            Font font; SolidBrush fontBrush; int fontX; PointF point; string text;
            draw.FillRectangle(new SolidBrush(panel.BackColor), 0, 0, panelWidth, topMargin); //抹去原来的图像
            if (blackAlphaAdd != 0)
            {
   
                font = new Font("Georgia", 16); //“Ticks”
                fontBrush = new SolidBrush(Color.FromArgb(whiteAlpha, 255, 160, 0));
                point = new PointF(346, 178);
                draw.DrawString("Ticks", font, fontBrush, point);
                SolidBrush blackBrush = new SolidBrush(Color.FromArgb(blackAlpha, 0, 0, 0));
                draw.FillRectangle(blackBrush, 343, 178, 138, 58);
            }
            if (whiteAlpha > 0)
            {
   
                if (!String.IsNullOrEmpty(whiteText1))
                {
   
                    font = new Font("Arial", 12); //“to”
                    fontBrush = new SolidBrush(Color.FromArgb(whiteAlpha, 160, 160, 160));
                    point = new PointF(350, 220);
                    draw.DrawString(whiteText1, font, fontBrush, point);
                }
                if (!String.IsNullOrEmpty(whiteText2))
                {
   
                    font = new Font("Arial", 20, FontStyle.Bold); //“Bars”
                    fontBrush = new SolidBrush(Color.FromArgb(whiteAlpha, 255, 255, 255));
                    point = new PointF(370, 211);
                    draw.DrawString(whiteText2, font, fontBrush, point);
                }
            }
            int i = startI; while (i < barsN)
            {
   
                int barX; int endGrayBarX = -1;
                Bar thisBar = bars[i];
                int openY; int highY; int lowY; int closeY;
                int endGrayOpenY = -1; int endGrayHighY = -1; int endGrayLowY = -1; int endGrayCloseY = -1;
                if (timer3Ticks < 80 || i < barsN - 1) //固定K线坐标
                {
   
                    barX = leftMargin + (i - startI) * barsIntv;
                    openY = priceToY(thisBar.O); highY = priceToY(thisBar.H);
                    lowY = priceToY(thisBar.L); closeY = priceToY(thisBar.C);
                }
                else //飞起来的K线的坐标
                {
   
                    barX = (int)endBarX;
                    openY = (int)endBarY; highY = endPriceY(thisBar.H);
                    lowY = endPriceY(thisBar.L); closeY = endPriceY(thisBar.C);
                    endGrayBarX = leftMargin + (i - startI) * barsIntv;
                    endGrayOpenY = priceToY(thisBar.O); endGrayHighY = priceToY(thisBar.H);
                    endGrayLowY = priceToY(thisBar.L); endGrayCloseY = priceToY(thisBar.C);
                }
                Color thisBarColor;
                if (i < barsN - 1) //历史K线颜色
                {
   
                    int R = barColor.R; int G = barColor.G; int B = barColor.B;
                    double p = 1 / (double)3;
                    double d = 1 / Math.Pow(absInt(i - brightestIndex) + 1, p);
                    R = (int)(d * R); G = (int)(d * G); B = (int)(d * B);
                    thisBarColor = Color.FromArgb(R, G, B);
                    //thisBarColor = barColor;
                }
                else //末端K线颜色
                {
   
                    thisBarColor = endBarColor;
                }
                #region //K线样式
                string style;
                if (closeY < openY) style = "Stroke"; //阳线
                else if (closeY > openY) style = "Fill"; //阴线
                else style = "Line"; //星线
                #endregion
                #region //末端固定K线和飞起来的文字
                if (endGrayBarX >= 0)
                {
   
                    Color endGrayBarColor;
                    int limit = 80;
                    if (endBarColor.R == 255) limit = 120;
                    if (endBarAlpha >= 255) endGrayBarColor = Color.FromArgb(limit, endBarColor.R, endBarColor.G, endBarColor.B);
                    else endGrayBarColor = Color.FromArgb(maxInt(limit, 255 - endBarAlpha), endBarColor.R, endBarColor.G, endBarColor.B);
                    int endGrayMinOC = minInt(endGrayOpenY, endGrayCloseY);
                    int endGrayMaxOC = maxInt(endGrayOpenY, endGrayCloseY);
                    Pen endGrayPen = new Pen(endGrayBarColor, 1);
                    SolidBrush endGrayBrush = new SolidBrush(endGrayBarColor);
                    draw.DrawLine(endGrayPen, endGrayBarX + barWidth / 2, endGrayHighY, endGrayBarX + barWidth / 2, endGrayMinOC);
                    if (style.Equals("Stroke")) draw.DrawRectangle(endGrayPen, endGrayBarX, endGrayMinOC, barWidth, endGrayMaxOC - endGrayMinOC);
                    else if (style.Equals("Fill")) draw.FillRectangle(endGrayBrush, endGrayBarX, endGrayMinOC, barWidth, endGrayMaxOC - endGrayMinOC);
                    else if (style.Equals("Line")) draw.DrawLine(endGrayPen, endGrayBarX, endGrayOpenY, endGrayBarX + barWidth, endGrayOpenY);
                    draw.DrawLine(endGrayPen, endGrayBarX + barWidth / 2, endGrayMaxOC, endGrayBarX + barWidth / 2, endGrayLowY);
                    font = new Font("Arial", 9);
                    fontBrush = new SolidBrush(endBarColor);
                    if (textID == 0)
                    {
   
                        if (timer3Ticks < 100)
                        {
   
                            point = new PointF(barX - 45, maxInt(0, highY));
                            text = "让";
                        }
                        else if (timer3Ticks < 115)
                        {
   
                            point = new PointF(barX - 45, maxInt(0, highY));
                            text = "让K";
                        }
                        else if (timer3Ticks < 130)
                        {
   
                            point = new PointF(barX - 45, maxInt(0, highY));
                            text = "让K线";
                        }
                        else if (timer3Ticks < 150)
                        {
   
                            point = new PointF(barX - 45, maxInt(0, highY));
                            text = "";
                        }
                        else if (timer3Ticks < 165)
                        {
   
                            point = new PointF(barX - 75, maxInt(0, highY));
                            text = "再";
                        }
                        else if (timer3Ticks < 180)
                        {
   
                            point = new PointF(barX - 75, maxInt(0, highY));
                            text = "再飞";
                        }
                        else if (timer3Ticks < 195)
                        {
   
                            point = new PointF(barX - 75, maxInt(0, highY));
                            text = "再飞一";
                        }
                        else if (timer3Ticks < 230)
                        {
   
                            point = new PointF(barX - 75, maxInt(0, highY));
                            text = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值