• Stock Charts With GDI+


    本文摘选自《Practical C# Charts and Graphics》,有兴趣的朋友可以到网上下载电子书。

    今天主要贴出一些如何实现K线图(蜡烛图)的代码,废话不多说,直接看下面。

    1.外面文件读取类(TextFileReader.cs):

    View Code
    using System;
    using System.Text;
    using System.Collections.Specialized;
    using System.Collections;
    using System.Windows.Forms;
    using System.IO;
    
    namespace Example4_9
    {
        class TextFileReader
        {
            public string[,] ReadTextFile(string fileName)
            {
                if (File.Exists(fileName))
                {   
                    string[,] sArray = ReadFile(fileName);
                    return sArray;
                }
                else
                {
                    return null;
                }
            }
    
            private string[,] ReadFile(string fileName)
            {
                try
                {
                    StringCollection sc = new StringCollection();
                    FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
                    StreamReader sr = new StreamReader(fs);
    
                    // Read file into a string collection
                    int noBytesRead = 0;
                    string oneLine;
                    while ((oneLine = sr.ReadLine()) != null)
                    {
                        noBytesRead += oneLine.Length;
                        sc.Add(oneLine);
                    }
                    sr.Close();
    
                    string[] sArray = new string[sc.Count];
                    sc.CopyTo(sArray, 0);
    
                    char[] cSplitter = { ' ', ',', ':', '\t' };
                    string[] sArray1 = sArray[0].Split(cSplitter);
                    string[,] sArray2 = new string[sArray1.Length, sc.Count];
    
                    for (int i = 0; i < sc.Count; i++)
                    {
                        sArray1 = sArray[sc.Count - 1 - i].Split(cSplitter);
                        for (int j = 0; j < sArray1.Length; j++)
                        {
                            sArray2[j, i] = sArray1[j];
                        }
                    }
                    return sArray2;
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, "Error Saving File.");
                    return null;
                }
            }
        }
    }

    2.股票数据(DataSeries.cs)

    View Code
    using System;
    using System.Drawing;
    
    namespace Example4_9
    {
        public class DataSeries
        {
            private string[,] dataString;
            private LineStyle lineStyle;
            private string seriesName = "";
    
            public DataSeries()
            {
                lineStyle = new LineStyle();
            }
    
            public LineStyle LineStyle
            {
                get { return lineStyle; }
                set { lineStyle = value; }
            }
    
            public string[,] DataString
            {
                get { return dataString; }
                set { dataString = value; }
            }
    
            public string SeriesName
            {
                get { return seriesName; }
                set { seriesName = value; }
            }
        }
    }

    3.数据集合(DataCollection.cs)

    View Code
    using System;
    using System.Collections;
    using System.Drawing;
    
    namespace Example4_9
    {
        public class DataCollection
        {
            private Form1 form1;
            private ArrayList dataSeriesList;
            private int dataSeriesIndex = 0;
            private StockChartTypeEnum stockChartType = 
                StockChartTypeEnum.HiLoOpenClose;
    
            public DataCollection(Form1 fm1)
            {
                dataSeriesList = new ArrayList();
                form1 = fm1;
            }
    
            public StockChartTypeEnum StockChartType
            {
                get { return stockChartType; }
                set { stockChartType = value; }
            }
    
            public enum StockChartTypeEnum
            {
                HiLo = 0,
                HiLoOpenClose = 1,
                Candle = 2
            }
    
            public ArrayList DataSeriesList
            {
                get { return dataSeriesList; }
                set { dataSeriesList = value; }
            }
            public int DataSeriesIndex
            {
                get { return dataSeriesIndex; }
                set { dataSeriesIndex = value; }
            }
    
            public void Add(DataSeries ds)
            {
                dataSeriesList.Add(ds);
                if (ds.SeriesName == "")
                {
                    ds.SeriesName = "DataSeries" + dataSeriesList.Count.ToString();
                }
            }
    
            public void Insert(int dataSeriesIndex, DataSeries ds)
            {
                dataSeriesList.Insert(dataSeriesIndex, ds);
                if (ds.SeriesName == "")
                {
                    dataSeriesIndex = dataSeriesIndex + 1;
                    ds.SeriesName = "DataSeries" + dataSeriesIndex.ToString();
                }
            }
    
            public void Remove(string dataSeriesName)
            {
                if (dataSeriesList != null)
                {
                    for (int i = 0; i < dataSeriesList.Count; i++)
                    {
                        DataSeries ds = (DataSeries)dataSeriesList[i];
                        if (ds.SeriesName == dataSeriesName)
                        {
                            dataSeriesList.RemoveAt(i);
                        }
                    }
                }
            }
    
            public void RemoveAll()
            {
                dataSeriesList.Clear();
            }
    
            public void AddStockChart(Graphics g, ChartStyle cs)
            {
                foreach (DataSeries ds in DataSeriesList)
                {
                    Pen aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.Thickness);
                    aPen.DashStyle = ds.LineStyle.Pattern;
                    SolidBrush aBrush = new SolidBrush(ds.LineStyle.LineColor);
                    SolidBrush whiteBrush = new SolidBrush(Color.White);
                    float barLength = form1.PlotPanel.Width / (5*ds.DataString.GetLength(1));
                    for (int i = 0; i < ds.DataString.GetLength(1); i++)
                    {
                        float[] stockdata = new float[4];
                        for (int j = 0; j < stockdata.Length; j++)
                        {
                            stockdata[j] = Convert.ToSingle(ds.DataString[j+1,i]);
                        }
                        PointF ptHigh = cs.Point2D(new PointF(i, stockdata[1]));
                        PointF ptLow = cs.Point2D(new PointF(i, stockdata[2]));
                        PointF ptOpen = cs.Point2D(new PointF(i, stockdata[0]));
                        PointF ptCLose = cs.Point2D(new PointF(i, stockdata[3]));
                        PointF ptOpen1 = new PointF(ptOpen.X - barLength, ptOpen.Y);
                        PointF ptClose1 = new PointF(ptCLose.X + barLength, ptCLose.Y);
                        PointF ptOpen2 = new PointF(ptOpen.X + barLength, ptOpen.Y);
                        PointF ptClose2 = new PointF(ptCLose.X - barLength, ptCLose.Y);
                        
    
                        // Draw Hi-Lo stock chart:
                        if (StockChartType == StockChartTypeEnum.HiLo)
                        {
                            g.DrawLine(aPen, ptHigh, ptLow);
                        }
    
                        // Draw Hi-Li-Open-Close chart:
                        else if (StockChartType == StockChartTypeEnum.HiLoOpenClose)
                        {
                            g.DrawLine(aPen, ptHigh, ptLow);
                            g.DrawLine(aPen,ptOpen, ptOpen1);
                            g.DrawLine(aPen, ptCLose, ptClose1);
                        }
    
                        // Draw candle chart:
                        else if (stockChartType == StockChartTypeEnum.Candle)
                        {
                            PointF[] pts = new PointF[4];
                            pts[0] = ptOpen1;
                            pts[1] = ptOpen2;
                            pts[2] = ptClose1;
                            pts[3] = ptClose2;
                            g.DrawLine(aPen, ptHigh, ptLow);
                            if (stockdata[0] > stockdata[3])
                            {
                                g.FillPolygon(aBrush,pts);
                            }
                            else if (stockdata[0] < stockdata[3])
                            {
                                g.FillPolygon(whiteBrush, pts);
                            }
                            g.DrawPolygon(aPen, pts);
                        }
                    }
                    aPen.Dispose();
                    aBrush.Dispose();
                    whiteBrush.Dispose();
                }
            }
        }
    }

    4.股票图形类别(ChartType.cs)

    View Code
    using System;
    using System.Collections.Generic;
    using System.Collections;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    
    namespace Example4_9
    {
        public class ChartStyle
        {
            private Form1 form1;
            private Rectangle chartArea;
            private Color chartBackColor;
            private Color chartBorderColor;
            private Color plotBackColor = Color.White;
            private Color plotBorderColor = Color.Black;
            private DashStyle gridPattern = DashStyle.Solid;
            private Color gridColor = Color.LightGray;
            private float gridLineThickness = 1.0f;
            private bool isXGrid = false;
            private bool isYGrid = false;
            private string xLabel = "X Axis";
            private string yLabel = "Y Axis";
            private string sTitle = "Title";
            private Font labelFont = new Font("Arial", 10, FontStyle.Regular);
            private Color labelFontColor = Color.Black;
            private Font titleFont = new Font("Arial", 12, FontStyle.Regular);
            private Color titleFontColor = Color.Black;
            private float xLimMin = 0f;
            private float xLimMax = 10f;
            private float yLimMin = 0f;
            private float yLimMax = 10f;
            private float xTick = 1f;
            private float yTick = 2f;
            private Font tickFont;
            private Color tickFontColor = Color.Black;
            private float xtickOffset = 0f;
            private float ytickOffset = 0f;
            private BarTypeEnum barType = BarTypeEnum.Vertical;
    
            public ChartStyle(Form1 fm1)
            {
                form1 = fm1;
                chartArea = form1.ClientRectangle;
                chartBackColor = fm1.BackColor;
                chartBorderColor = fm1.BackColor;
                tickFont = form1.Font;
            }
    
            public BarTypeEnum BarType
            {
                get { return barType; }
                set { barType = value; }
            }
    
            public enum BarTypeEnum
            {
                Vertical = 0,
                Horizontal = 1,
                VerticalStack = 2,
                HorizontalStack = 3,
                VerticalOverlay = 4,
                HorizontalOverlay = 5
            }
    
            public Font TickFont
            {
                get { return tickFont; }
                set { tickFont = value; }
            }
    
            public Color TickFontColor
            {
                get { return tickFontColor; }
                set { tickFontColor = value; }
            }
    
            public Color ChartBackColor
            {
                get { return chartBackColor; }
                set { chartBackColor = value; }
            }
    
            public float XTickOffset
            {
                get { return xtickOffset; }
                set { xtickOffset = value; }
            }
    
            public float YTickOffset
            {
                get { return ytickOffset; }
                set { ytickOffset = value; }
            }
    
            public Color ChartBorderColor
            {
                get { return chartBorderColor; }
                set { chartBorderColor = value; }
            }
    
            public Color PlotBackColor
            {
                get { return plotBackColor; }
                set { plotBackColor = value; }
            }
    
            public Color PlotBorderColor
            {
                get { return plotBorderColor; }
                set { plotBorderColor = value; }
            }
            
            public Rectangle ChartArea
            {
                get { return chartArea; }
                set { chartArea = value; }
            }
    
            public bool IsXGrid
            {
                get { return isXGrid; }
                set { isXGrid = value; }
            }
            public bool IsYGrid
            {
                get { return isYGrid; }
                set { isYGrid = value; }
            }
            public string Title
            {
                get { return sTitle; }
                set { sTitle = value; }
            }
            public string XLabel
            {
                get { return xLabel; }
                set { xLabel = value; }
            }
            public string YLabel
            {
                get { return yLabel; }
                set { yLabel = value; }
            }
            public Font LabelFont
            {
                get { return labelFont; }
                set { labelFont = value; }
            }
            public Color LabelFontColor
            {
                get { return labelFontColor; }
                set { labelFontColor = value; }
            }
            public Font TitleFont
            {
                get { return titleFont; }
                set { titleFont = value; }
            }
            public Color TitleFontColor
            {
                get { return titleFontColor; }
                set { titleFontColor = value; }
            }
            public float XLimMax
            {
                get { return xLimMax; }
                set { xLimMax = value; }
            }
            public float XLimMin
            {
                get { return xLimMin; }
                set { xLimMin = value; }
            }
            public float YLimMax
            {
                get { return yLimMax; }
                set { yLimMax = value; }
            }
            public float YLimMin
            {
                get { return yLimMin; }
                set { yLimMin = value; }
            }
            public float XTick
            {
                get { return xTick; }
                set { xTick = value; }
            }
            public float YTick
            {
                get { return yTick; }
                set { yTick = value; }
            }
            virtual public DashStyle GridPattern
            {
                get { return gridPattern; }
                set { gridPattern = value; }
            }
            public float GridThickness
            {
                get { return gridLineThickness; }
                set { gridLineThickness = value; }
            }
            virtual public Color GridColor
            {
                get { return gridColor; }
                set { gridColor = value; }
            }
    
            public void PlotPanelStyle(Graphics g)
            {
                Pen aPen = new Pen(ChartBorderColor, 1f);
                SolidBrush aBrush = new SolidBrush(ChartBackColor);
                SizeF tickFontSize = g.MeasureString("A", TickFont);
    
                // Create vertical gridlines:
                float fX, fY, xm, ym;
    
                aPen = new Pen(GridColor, 1f);
                aPen.DashStyle = GridPattern;
                xm = XLimMin + XTickOffset;
                if (BarType == BarTypeEnum.Vertical || 
                    BarType == BarTypeEnum.VerticalOverlay ||
                    BarType == BarTypeEnum.VerticalStack)
                {
                    xm = XTickOffset + XLimMin;
                }
    
                // Create vertical gridelines:
                if (IsYGrid == true)
                {
    
                    for (fX = xm; fX < XLimMax; fX += XTick)
                    {
                        g.DrawLine(aPen, Point2D(new PointF(fX, YLimMin)),
                            Point2D(new PointF(fX, YLimMax)));
                    }
                }
                // Create the x-axis tick marks:
                for (fX = xm; fX < XLimMax; fX += XTick)
                {
                    PointF yAxisPoint = Point2D(new PointF(fX, YLimMin));
                    g.DrawLine(Pens.Black, yAxisPoint, new PointF(yAxisPoint.X,
                                       yAxisPoint.Y - 8f));
                }
    
                // Create horizontal gridlines:
                aPen = new Pen(GridColor, 1f);
                aPen.DashStyle = GridPattern;
                ym = YLimMin + YTickOffset;
                if (BarType == BarTypeEnum.Horizontal ||
                    BarType == BarTypeEnum.HorizontalOverlay ||
                    BarType == BarTypeEnum.HorizontalStack)
                {
                    ym = YTickOffset + YLimMin + YTick / 2;
                }
    
                if (IsXGrid == true)
                {
                    for (fY = ym; fY < YLimMax; fY += YTick)
                    {
                        g.DrawLine(aPen, Point2D(new PointF(XLimMin, fY)),
                            Point2D(new PointF(XLimMax, fY)));
                    }
                }
    
                // Create the y-axis tick marks:
                for (fY = ym; fY < YLimMax; fY += YTick)
                {
                    PointF xAxisPoint = Point2D(new PointF(XLimMin, fY));
                    g.DrawLine(Pens.Black, xAxisPoint,
                        new PointF(xAxisPoint.X + 5f, xAxisPoint.Y));
                }
                aPen.Dispose();
                aBrush.Dispose();
            }
    
            public void SetChartArea(Graphics g)
            {
                SetPlotPanel(g);
                // Draw chart area:
                Pen aPen = new Pen(ChartBorderColor, 1f);
                SolidBrush aBrush = new SolidBrush(ChartBackColor);
                SizeF tickFontSize = g.MeasureString("A", TickFont);
                g.FillRectangle(aBrush, ChartArea);
                g.DrawRectangle(aPen, ChartArea);
    
                // Create the x-axis tick labels:
                aBrush = new SolidBrush(TickFontColor);
                float xm = XLimMin + XTickOffset;
                float xticklabel = 0f;
                if (BarType == BarTypeEnum.Vertical ||
                    BarType == BarTypeEnum.VerticalOverlay ||
                    BarType == BarTypeEnum.VerticalStack)
                {
                    xm = XTickOffset + XLimMin;
                    xticklabel = 0;
                    
                }
    
                for (float fX =  xm; fX <= XLimMax; fX += XTick)
                {
                    PointF yAxisPoint = Point2D(new PointF(fX, YLimMin));
                    StringFormat sFormat = new StringFormat();
                    sFormat.Alignment = StringAlignment.Center;
                    g.DrawString((fX + xticklabel).ToString(), TickFont, aBrush,
                        new PointF(form1.PlotPanel.Left + yAxisPoint.X,
                        form1.PlotPanel.Top + yAxisPoint.Y + 4f), sFormat);
                }
    
                // Create the y-axis tick labels:
                float ym = YLimMin + YTickOffset;
                float yticklabel = 0f;
                if (BarType == BarTypeEnum.Horizontal ||
                    BarType == BarTypeEnum.HorizontalOverlay ||
                    BarType == BarTypeEnum.HorizontalStack)
                {
                    ym = YTickOffset + YLimMin + YTick / 2;
                    yticklabel = YTick / 2;
                }
                for (float fY = ym; fY <= YLimMax; fY += YTick)
                {
                    PointF xAxisPoint = Point2D(new PointF(XLimMin, fY));
                    StringFormat sFormat = new StringFormat();
                    sFormat.Alignment = StringAlignment.Far;
                    g.DrawString((fY + yticklabel).ToString(), TickFont, aBrush,
                        new PointF(form1.PlotPanel.Left + xAxisPoint.X - 3f,
                        form1.PlotPanel.Top + xAxisPoint.Y
                        - tickFontSize.Height / 2), sFormat);
                }
    
                AddLabels(g);
            }
    
            private void SetPlotPanel(Graphics g)
            {
                // Set form1.PlotPanel:
                float xOffset = ChartArea.Width / 30.0f;
                float yOffset = ChartArea.Height / 30.0f;
                SizeF labelFontSize = g.MeasureString("A", LabelFont);
                SizeF titleFontSize = g.MeasureString("A", TitleFont);
                if (Title.ToUpper() == "NO TITLE")
                {
                    titleFontSize.Width = 8f;
                    titleFontSize.Height = 8f;
                }
                float xSpacing = xOffset / 3.0f;
                float ySpacing = yOffset / 3.0f;
                SizeF tickFontSize = g.MeasureString("A", TickFont);
                float tickSpacing = 2f;
                SizeF yTickSize = g.MeasureString(YLimMin.ToString(), TickFont);
                for (float yTick = YLimMin + YTickOffset; yTick <= YLimMax; yTick += YTick)
                {
                    SizeF tempSize = g.MeasureString(yTick.ToString(), TickFont);
                    if (yTickSize.Width < tempSize.Width)
                    {
                        yTickSize = tempSize;
                    }
                }
                float leftMargin = xOffset + labelFontSize.Width +
                            xSpacing + yTickSize.Width + tickSpacing;
                float rightMargin = xOffset;
                float topMargin = yOffset + titleFontSize.Height + ySpacing;
                float bottomMargin = yOffset + labelFontSize.Height +
                            ySpacing + tickSpacing + tickFontSize.Height;
    
                // Define the plot panel size:
                int[] panelsize = new int[4];
                form1.PlotPanel.Left = ChartArea.X + (int)leftMargin;
                form1.PlotPanel.Top = ChartArea.Y + (int)topMargin;
                form1.PlotPanel.Width = ChartArea.Width - (int)leftMargin - 2 * (int)rightMargin;
                form1.PlotPanel.Height = ChartArea.Height - (int)topMargin - (int)bottomMargin;
                form1.PlotPanel.BackColor = plotBackColor;
            }
    
            private void AddLabels(Graphics g)
            {
                float xOffset = ChartArea.Width / 30.0f;
                float yOffset = ChartArea.Height / 30.0f;
                SizeF labelFontSize = g.MeasureString("A", LabelFont);
                SizeF titleFontSize = g.MeasureString("A", TitleFont);
    
                // Add horizontal axis label:
                SolidBrush aBrush = new SolidBrush(LabelFontColor);
                SizeF stringSize = g.MeasureString(XLabel, LabelFont);
                g.DrawString(XLabel, LabelFont, aBrush,
                    new Point(form1.PlotPanel.Left + form1.PlotPanel.Width / 2 -
                    (int)stringSize.Width / 2, ChartArea.Bottom - 
                    (int)yOffset - (int)labelFontSize.Height));
    
                // Add y-axis label:
                StringFormat sFormat = new StringFormat();
                sFormat.Alignment = StringAlignment.Center;
                stringSize = g.MeasureString(YLabel, LabelFont);
                // Save the state of the current Graphics object
                GraphicsState gState = g.Save();
                g.TranslateTransform(ChartArea.X + xOffset, ChartArea.Y 
                    + yOffset + titleFontSize.Height
                    + yOffset / 3 + form1.PlotPanel.Height / 2);
                g.RotateTransform(-90);
                g.DrawString(YLabel, LabelFont, aBrush, 0, 0, sFormat);
                // Restore it:
                g.Restore(gState);
    
                // Add title:
                aBrush = new SolidBrush(TitleFontColor);
                stringSize = g.MeasureString(Title, TitleFont);
                if (Title.ToUpper() != "NO TITLE")
                {
                    g.DrawString(Title, TitleFont, aBrush,
                        new Point(form1.PlotPanel.Left + form1.PlotPanel.Width / 2 -
                        (int)stringSize.Width / 2, ChartArea.Top + (int)yOffset));
                }
                aBrush.Dispose();
            }
    
            public PointF Point2D(PointF pt)
            {
                PointF aPoint = new PointF();
                aPoint.X = (pt.X - XLimMin) *
                    form1.PlotPanel.Width / (XLimMax - XLimMin);
                aPoint.Y = form1.PlotPanel.Height -(pt.Y - YLimMin) *
                    form1.PlotPanel.Height / (YLimMax - YLimMin);
                return aPoint;
            }
        }
    }

    5.改善后画线类(LineStyle.cs)

    View Code
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Text;
    
    namespace Example4_9
    {
        public class LineStyle
        {
            private DashStyle linePattern = DashStyle.Solid;
            private Color lineColor = Color.Black;
            private float LineThickness = 1.0f;
            private PlotLinesMethodEnum pltLineMethod = PlotLinesMethodEnum.Lines;
            private bool isVisible = true;
    
            public LineStyle()
            {
            }
    
            public bool IsVisible
            {
                get { return isVisible; }
                set { isVisible = value; }
            }
    
            public PlotLinesMethodEnum PlotMethod
            {
                get { return pltLineMethod; }
                set { pltLineMethod = value; }
            }
    
            virtual public DashStyle Pattern
            {
                get { return linePattern; }
                set { linePattern = value; }
            }
    
            public float Thickness
            {
                get { return LineThickness; }
                set { LineThickness = value; }
            }
    
            virtual public Color LineColor
            {
                get { return lineColor; }
                set { lineColor = value; }
            }
    
            public enum PlotLinesMethodEnum
            {
                Lines = 0,
                Splines = 1
            }
        }
    }

    6.Form1中相关代码

    View Code
    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    
    namespace Example4_9
    {
        public partial class Form1 : Form
        {
            private ChartStyle cs;
            private DataCollection dc;
    
            public Form1()
            {
                InitializeComponent();
                this.SetStyle(ControlStyles.ResizeRedraw, true);
                this.BackColor = Color.White;
    
                // Subscribing to a paint eventhandler to drawingPanel: 
                PlotPanel.Paint +=
                    new PaintEventHandler(PlotPanelPaint);
    
                cs = new ChartStyle(this);
                dc = new DataCollection(this);
                // Specify chart style parameters:
                cs.Title = "Chart of GE Stock";
                cs.XTickOffset = 1;
                cs.XLimMin = -1f;
                cs.XLimMax = 20f;
                cs.YLimMin = 32f;
                cs.YLimMax = 36f;
                cs.XTick = 2f;
                cs.YTick = 0.5f;
                dc.StockChartType = DataCollection.StockChartTypeEnum.HiLoOpenClose;
            }
    
            private void AddData()
            {
                dc.DataSeriesList.Clear();
                TextFileReader tfr = new TextFileReader();
                DataSeries ds = new DataSeries();
    
                // Add GE stock data from a text data file:
                ds = new DataSeries();
                ds.DataString = tfr.ReadTextFile("GE.txt");
                ds.LineStyle.LineColor = Color.DarkBlue;
                dc.Add(ds);         
            }
    
            private void PlotPanelPaint(object sender, PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                AddData();
                cs.PlotPanelStyle(g);
                dc.AddStockChart(g, cs);
            }
    
            protected override void OnPaint(PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                cs.ChartArea = this.ClientRectangle;
                cs.SetChartArea(g);
            }
        }
    }

    改变股票图表样式,修改dc.StockChartType属性即可,如: dc.StockChartType =  DataCollection.StockChartTypeEnum.HiLoOpenClose;  

    数据文件如下:

    5-May-06    34.94    35.22    34.87    35.16
    4-May-06    34.5    34.94    34.48    34.8
    3-May-06    34.22    34.67    34.19    34.4
    2-May-06    34.39    34.59    34.1    34.48
    1-May-06    34.64    34.72    34.32    34.39
    28-Apr-06    34.49    34.78    34.35    34.59
    27-Apr-06    33.9    34.68    33.89    34.43
    26-Apr-06    34.07    34.44    33.88    34.13
    25-Apr-06    34    34.06    33.8    33.97
    24-Apr-06    33.81    34    33.8    33.93
    21-Apr-06    34.25    34.32    33.68    33.97
    20-Apr-06    33.8    34.18    33.63    34.12
    19-Apr-06    33.95    33.97    33.5    33.89
    18-Apr-06    33.52    33.97    33.21    33.87
    17-Apr-06    33.76    33.76    33.07    33.29
    13-Apr-06    34.19    34.36    33.61    33.89
    12-Apr-06    34.3    34.53    34.17    34.46
    11-Apr-06    33.92    34.07    33.63    34.05
    10-Apr-06    34.06    34.08    33.8    33.92
    7-Apr-06    34.55    34.75    34.01    34.03

    最终样式如下:

  • 相关阅读:
    业余草双因素认证(2FA)教程
    业余草网站热门关键字
    微博爬虫“免登录”技巧详解及 Java 实现(业余草的博客)
    业余草通告CSDN博客用户zhang__ao非法转载文章的公告
    CODE大全给你推荐几个免费的leapftp 注册码
    业余草最新热门博客推荐
    莫比乌斯反演
    P5091 【模板】欧拉定理
    LaTeX Test
    P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
  • 原文地址:https://www.cnblogs.com/jiewong/p/stock.html
Copyright © 2020-2023  润新知