예제 #1
0
        protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            if (IsInHitTest)
            {
                return;
            }

            int    lastBar   = ChartBars.ToIndex;
            int    firstBar  = ChartBars.FromIndex;
            double highPrice = 0;
            double lowPrice  = double.MaxValue;

            SharpDX.Direct2D1.Brush brushDown = BarDownBrush.ToDxBrush(RenderTarget);
            SharpDX.Direct2D1.Brush lineBrush = LineBrush.ToDxBrush(RenderTarget);
            SharpDX.Direct2D1.Brush brushUp   = BarUpBrush.ToDxBrush(RenderTarget);
            brushDown.Opacity = (float)(Opacity / 100.0);
            brushUp.Opacity   = (float)(Opacity / 100.0);

            for (int idx = firstBar; idx <= lastBar && idx >= 0; idx++)
            {
                highPrice = Math.Max(highPrice, Bars.GetHigh(idx));
                lowPrice  = Math.Min(lowPrice, Bars.GetLow(idx));
            }

            int    volumeBarCount = BarCount;
            double priceRange     = highPrice - lowPrice;
            double priceBoxSize   = priceRange / volumeBarCount;
            double volumeMax      = 0;

            // Pass 1: Fill all VolumeInfo structures with appropriate data
            for (int i = 0; i < volumeBarCount; i++)
            {
                double priceUpper = lowPrice + priceBoxSize * (i + 1);
                double priceLower = lowPrice + priceBoxSize * i;

                double priceVolumeUp   = 0;
                double priceVolumeDown = 0;

                for (int idx = firstBar; idx <= lastBar; idx++)
                {
                    double checkPrice;

                    PriceSeries series = (Inputs[0] as PriceSeries);

                    switch (series.PriceType)
                    {
                    case PriceType.Open:            checkPrice = Bars.GetOpen(idx); break;

                    case PriceType.Close:           checkPrice = Bars.GetClose(idx); break;

                    case PriceType.High:            checkPrice = Bars.GetHigh(idx); break;

                    case PriceType.Low:                     checkPrice = Bars.GetLow(idx); break;

                    case PriceType.Median:          checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx)) / 2; break;

                    case PriceType.Typical:         checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx) + Bars.GetClose(idx)) / 3; break;

                    case PriceType.Weighted:        checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx) + 2 * Bars.GetClose(idx)) / 4; break;

                    default:                                        checkPrice = Bars.GetClose(idx); break;
                    }

                    if (checkPrice >= priceLower && checkPrice < priceUpper)
                    {
                        if (Bars.GetOpen(idx) < Bars.GetClose(idx))
                        {
                            priceVolumeUp += Bars.GetVolume(idx);
                        }
                        else
                        {
                            priceVolumeDown += Bars.GetVolume(idx);
                        }
                    }
                }

                volumeInfo[i].up    = priceVolumeUp;
                volumeInfo[i].down  = priceVolumeDown;
                volumeInfo[i].total = priceVolumeUp + priceVolumeDown;

                volumeMax = Math.Max(volumeMax, volumeInfo[i].total);
            }

            // Pass 2: Paint the volume bars
            for (int i = 0; i < Math.Min(volumeBarCount, lastBar - firstBar + 1); i++)
            {
                double priceUpper   = lowPrice + priceBoxSize * (i + 1);
                double priceLower   = lowPrice + priceBoxSize * i;
                int    yUpper       = Convert.ToInt32(chartScale.GetYByValue(priceUpper)) + BarSpacing;
                int    yLower       = Convert.ToInt32(chartScale.GetYByValue(priceLower));
                int    barWidthUp   = (int)((chartScale.Height / 2) * (volumeInfo[i].up / volumeMax));
                int    barWidthDown = (int)((chartScale.Height / 2) * (volumeInfo[i].down / volumeMax));

                SharpDX.RectangleF rect = new SharpDX.RectangleF(ChartPanel.X, yUpper, barWidthUp, Math.Abs(yUpper - yLower));
                RenderTarget.FillRectangle(rect, brushUp);
                RenderTarget.DrawRectangle(rect, brushUp);

                SharpDX.RectangleF rect2 = new SharpDX.RectangleF(ChartPanel.X + barWidthUp, yUpper, barWidthDown, Math.Abs(yUpper - yLower));
                RenderTarget.DrawRectangle(rect2, brushDown);
                RenderTarget.FillRectangle(rect2, brushDown);

                if (DrawLines)
                {
                    RenderTarget.DrawLine(new SharpDX.Vector2(ChartPanel.X, yLower), new SharpDX.Vector2(ChartPanel.X + ChartPanel.W, yLower), lineBrush);
                    if (i == volumeBarCount - 1)
                    {
                        RenderTarget.DrawLine(new SharpDX.Vector2(ChartPanel.X, yUpper), new SharpDX.Vector2(ChartPanel.X + ChartPanel.W, yUpper), lineBrush);
                    }
                }
            }

            lineBrush.Dispose();
            brushDown.Dispose();
            brushUp.Dispose();
        }
예제 #2
0
        protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            if (Bars == null || Bars.Instrument == null || IsInHitTest)
            {
                return;
            }

            int    firstBarIdxToPaint = -1;
            double tickSize           = Bars.Instrument.MasterInstrument.TickSize;
            double volumeMax          = 0;

            SharpDX.Direct2D1.Brush upBrush      = VolumeUpBrush.ToDxBrush(RenderTarget);
            SharpDX.Direct2D1.Brush downBrush    = VolumeDownBrush.ToDxBrush(RenderTarget);
            SharpDX.Direct2D1.Brush neutralBrush = VolumeNeutralBrush.ToDxBrush(RenderTarget);
            SharpDX.Direct2D1.Brush lineBrushDx  = LineBrush.ToDxBrush(RenderTarget);

            upBrush.Opacity      = (float)(alpha / 100.0);
            downBrush.Opacity    = (float)(alpha / 100.0);
            neutralBrush.Opacity = (float)(alpha / 100.0);

            for (int i = newSessionBarIdx.Count - 1; i >= 0; i--)
            {
                int prevSessionBreakIdx = newSessionBarIdx[i];

                if (prevSessionBreakIdx <= ChartBars.ToIndex)
                {
                    startIndexOf       = newSessionBarIdx.IndexOf(prevSessionBreakIdx);
                    firstBarIdxToPaint = prevSessionBreakIdx;
                    break;
                }
            }

            if (sortedDicList.Count < 1 && cacheDictionary.Keys.Count > 0)
            {
                sortedDicList.Add(cacheDictionary);
            }

            foreach (Dictionary <double, VolumeInfoItem> tmpDict in sortedDicList)
            {
                foreach (KeyValuePair <double, VolumeInfoItem> keyValue in tmpDict)
                {
                    double price = keyValue.Key;

                    if (Bars.BarsType.IsIntraday && (price > chartScale.MaxValue || price < chartScale.MinValue))
                    {
                        continue;
                    }

                    VolumeInfoItem vii   = keyValue.Value;
                    double         total = vii.up + vii.down + vii.neutral;
                    volumeMax = Math.Max(volumeMax, total);
                }
            }

            if (volumeMax.ApproxCompare(0) == 0)
            {
                return;
            }

            int viiPositions = 0;

            foreach (KeyValuePair <double, VolumeInfoItem> keyValue in sortedDicList[startIndexOf])
            {
                viiPositions++;

                VolumeInfoItem vii = keyValue.Value;

                double priceLower      = keyValue.Key - tickSize / 2;
                float  yLower          = chartScale.GetYByValue(priceLower);
                float  yUpper          = chartScale.GetYByValue(priceLower + tickSize);
                float  height          = Math.Max(1, Math.Abs(yUpper - yLower) - barSpacing);
                int    barWidthUp      = (int)((ChartPanel.W / 2) * (vii.up / volumeMax));
                int    barWidthNeutral = (int)((ChartPanel.W / 2) * (vii.neutral / volumeMax));
                int    barWidthDown    = (int)((ChartPanel.W / 2) * (vii.down / volumeMax));
                float  stationaryXpos  = chartControl.GetXByBarIndex(ChartBars, !Bars.IsTickReplay ? ChartBars.FromIndex : Math.Max(ChartBars.FromIndex, firstBarIdxToPaint));
                float  xpos            = chartControl.GetXByBarIndex(ChartBars, !Bars.IsTickReplay ? ChartBars.FromIndex : Math.Max(1, Math.Max(ChartBars.FromIndex, firstBarIdxToPaint)) - 1);

                RenderTarget.FillRectangle(new SharpDX.RectangleF(xpos, yUpper, barWidthUp, height), upBrush);
                xpos += barWidthUp;
                RenderTarget.FillRectangle(new SharpDX.RectangleF(xpos, yUpper, barWidthNeutral, height), neutralBrush);
                xpos += barWidthNeutral;
                RenderTarget.FillRectangle(new SharpDX.RectangleF(xpos, yUpper, barWidthDown, height), downBrush);

                if (!drawLines)
                {
                    continue;
                }
                // Lower line
                RenderTarget.DrawLine(new SharpDX.Vector2(stationaryXpos, yLower), new SharpDX.Vector2((ChartPanel.X + ChartPanel.W), yLower), lineBrushDx);

                // Upper line (only at very top)
                if (viiPositions == sortedDicList[startIndexOf].Count)
                {
                    RenderTarget.DrawLine(new SharpDX.Vector2(stationaryXpos, yUpper), new SharpDX.Vector2((ChartPanel.X + ChartPanel.W), yUpper), lineBrushDx);
                }
            }

            lineBrushDx.Dispose();
            upBrush.Dispose();
            downBrush.Dispose();
            neutralBrush.Dispose();
        }