NexusFi: Find Your Edge


Home Menu

 





Implementing Custom Drawings


Discussion in MultiCharts

Updated
      Top Posters
    1. looks_one Jasonnator with 7 posts (4 thanks)
    2. looks_two yiman with 3 posts (1 thanks)
    3. looks_3 jplourd with 3 posts (0 thanks)
    4. looks_4 SteveW with 2 posts (1 thanks)
    1. trending_up 5,663 views
    2. thumb_up 6 thanks given
    3. group 5 followers
    1. forum 15 posts
    2. attach_file 1 attachments




 
Search this Thread

Implementing Custom Drawings

  #1 (permalink)
 
Jasonnator's Avatar
 Jasonnator 
Denver, Colorado United States
 
Experience: Intermediate
Platform: NT8 + Custom
Broker: NT Brokerage, Kinetick, IQFeed, Interactive Brokers
Trading: ES
Posts: 159 since Dec 2014
Thanks Given: 40
Thanks Received: 166

I have recently switched to MultiCharts and so far like the platform except for the drawing tools. One of my systems is based on patterns but there's no elegant way to draw a triangle or XABCD pattern in MultiCharts.

I started looking at the implementation of MC drawings located in the PLTypes.dll file and found the Arrow, TrendLine, and Text objects. I called MC support and asked if extending the built in drawing tools by modifying this file was in any way against their EULA. I also specifically asked about decompiling and they said it is not against the EULA as long as I have a license and the file in question is not obfuscated.

I pulled apart the dll and first looked in EPlotShapes.cs and added Triangle to the enum list.
Then I copied all of the related TrendLine files and modified the following files so as to support a triangle shape:

ITriangleObject.cs (added 3 ChartPoint properties: pointOne, pointTwo, pointThree)
ITriangleContainer.cs (Added 3 Create functions to support 3 ChartPoint objects)
Triangle.cs (added 3 ChartPoint properties, added a Height property)
TriangleCreator.cs (same as ITriangleContainer.cs)
TriangleObjectException.cs (basic renaming from intial file copying)

I backed up ActiveObject.dll, ATCenterProxy.interop.dll, PLTypes.xml, and PLTypes.dll then copied the new files into the installation folder. Here's the kicker, it worked. However, comma, the enum Triangle does not show up in MC's built in editor intellisense but DOES in visual studio. Booyah, or so I thought.


Here's where I could use some help:
The biggest rub is Triangle doesn't show up when right clicking on a chart on the Insert Drawing submenu. That effectively makes it only usable via code which is ok but being able to use it via the Insert Drawing submenu would be great.

Jason

Started this thread Reply With Quote

Can you help answer these questions
from other members on NexusFi?
Online prop firm The Funded Trader (TFT) going under?
Traders Hideout
ZombieSqueeze
Platforms and Indicators
My NT8 Volume Profile Split by Asian/Euro/Open
NinjaTrader
Futures True Range Report
The Elite Circle
New Micros: Ultra 10-Year & Ultra T-Bond -- Live Now
Treasury Notes and Bonds
 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Get funded firms 2023/2024 - Any recommendations or word …
59 thanks
Funded Trader platforms
37 thanks
NexusFi site changelog and issues/problem reporting
22 thanks
GFIs1 1 DAX trade per day journal
22 thanks
The Program
20 thanks
  #2 (permalink)
 
Jasonnator's Avatar
 Jasonnator 
Denver, Colorado United States
 
Experience: Intermediate
Platform: NT8 + Custom
Broker: NT Brokerage, Kinetick, IQFeed, Interactive Brokers
Trading: ES
Posts: 159 since Dec 2014
Thanks Given: 40
Thanks Received: 166

Everything compiles but I ran into a bit of a problem with PLStudiesProxy.dll where the actual drawing logic needs to be. I am working with MultiCharts and hopefully they will allow me to implement this for them so everyone can have a triangle tool.

Started this thread Reply With Quote
  #3 (permalink)
 
Jasonnator's Avatar
 Jasonnator 
Denver, Colorado United States
 
Experience: Intermediate
Platform: NT8 + Custom
Broker: NT Brokerage, Kinetick, IQFeed, Interactive Brokers
Trading: ES
Posts: 159 since Dec 2014
Thanks Given: 40
Thanks Received: 166


So MC basically came back and said that implementing this idea would require "profound" changes in MC. I ended up using tool bar buttons with custom functionality underneath. It's not optimized or uber efficient but it works. I uploaded while I was still tinkering but it should give anyone interested a decent place to start. Code attached...

StartCalc function
 
Code
        protected override void StartCalc()
        {
            if (!toolBarEnabled)
            {
                toolBarEnabled = true;
                ChartToolBar.AccessToolBar(toolBar =>
                {
                    var label = new Label()
                    {
                        Text = "Advanced Patterns",
                        TextAlign = ContentAlignment.MiddleCenter
                    };

                    buttonTriangle = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Draw Triangle",
                        Enabled = true
                    };

                    buttonPattern = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Draw Pattern",
                        Enabled = true
                    };

                    buttonClear = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Clear Points"
                    };

                    buttonRemoveAll = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Remove All"
                    };

                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(label));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonTriangle));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonPattern));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonClear));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonRemoveAll));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(pointCountLabel));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    buttonTriangle.Click += OnTriangleClick;
                    buttonPattern.Click += OnPatternClick;
                    buttonClear.Click += OnClearButtonClick;
                    buttonClear.Click += OnRemoveAllButtonClick;
                });
            }


        private void AddItem2ToolStrip(ToolStrip toolBar, ToolStripItem item)
        {
            item.Tag = this;
            toolBar.Items.Add(item);
        }
        }
I wanted to draw shapes interactively so I am handling mouse clicks. Don't foget to add [MouseEvents(true), SameAsSymbol(true), RecoverDrawings(false)]
 
Code
        protected override void OnMouseEvent(MouseClickArgs arg)
        {
            base.OnMouseEvent(arg);
            try
            {
                switch (arg.buttons)
                {
                    case MouseButtons.Left:
                        {
                            MouseClick = arg;
                            if (!buttonTriangle.Enabled)
                            {
                                pointList.Add(ClickToChartPoint(arg));
                                OnDrawClick();
                                if (pointList.Count == 3)
                                {
                                    _validTriangle = true;
                                    DrawTriangle(pointList);
                                    ResetTriangleButton();
                                }
                            }
                            if (!buttonPattern.Enabled)
                            {
                                pointList.Add(ClickToChartPoint(arg));
                                OnDrawClick();
                                if (pointList.Count == 5)
                                {
                                    DrawPattern(pointList);
                                    ResetPatternButton();
                                }
                            }
                            break;
                        }

                    case MouseButtons.Right:
                        {
                            break;
                        }

                    default:
                        break;
                }
            }
            catch (Exception e)
            {
            }
        }

And here is how I am drawing a triangle
 
Code
private void DrawTriangle(List<ChartPoint> chartPoints)
        {
            try
            {
                DrwTrendLine.Create(chartPoints[0], chartPoints[1]);
                DrwTrendLine.Active.Color = myPen.Color;
                DrwTrendLine.Active.Size = (int)myPen.Width;
                DrwTrendLine.Create(chartPoints[1], chartPoints[2]);
                DrwTrendLine.Active.Color = myPen.Color;
                DrwTrendLine.Active.Size = (int)myPen.Width;
                DrwTrendLine.Create(chartPoints[2], chartPoints[0]);
                DrwTrendLine.Active.Color = myPen.Color;
                DrwTrendLine.Active.Size = (int)myPen.Width;

                CustomDraw(_context);

                ResetTriangleButton(); // reenable to triangle button
                pointList.Clear(); // don't need the points anymore
                OnDrawClick(); // just updates a label on the toolbar (for testing mostly)

                _validTriangle = true;
                requireAdd = true;
            }
            catch (Exception e)
            {
                Alerts.Alert("Error in DrawTriangle: {0}", e.Message);
                ResetTriangleButton();
                pointList.Clear();
                OnDrawClick();
            }
        }

        // helper draw function
        private void CustomDraw(DrawContext dc)
        {
            try
            {
                var pointFs = new List<PointF>();
                var path = new GraphicsPath();

                foreach (var chartPoint in pointList)
                {
                    pointFs.Add(ChartCustomDraw.Environment.ChartPoint2Point(chartPoint));
                }

                float b = pointFs[0].X;
                int bn = (int)b;

                pointFs.Add(ChartCustomDraw.Environment.ChartPoint2Point(pointList[0]));
                //dc.graphics.InterpolationMode = InterpolationMode.Low;

                path.AddLines(pointFs.ToArray());

                dc.graphics.DrawPath(myPen, path);
                //dc.graphics.DrawLines(myPen, pointFs.ToArray());

                if (requireAdd)
                {
                    requireAdd = false;
                    graphicPaths.Add(path);
                }
            }
            catch (Exception)
            {
            }
        }
My Draw function, pretty simple
 
Code
private DrawContext _context;
public void Draw(DrawContext context, EDrawPhases phase)
        {
            _context = context;
            //CustomDraw(context);
        }

Attached Files
Elite Membership required to download: __AdvancedPatterns.Indicator.CS
Started this thread Reply With Quote
Thanked by:
  #4 (permalink)
 yiman 
London
 
Experience: Intermediate
Platform: ninjatrader, multicharts, MT4
Broker: IB, PFG Best
Trading: 6E, EMD, TF
Posts: 265 since Jul 2009
Thanks Given: 111
Thanks Received: 158

how do i use this in multicharts please. This would be agreat addition for MC as i use triangles alot.

Cheers




Jasonnator View Post
So MC basically came back and said that implementing this idea would require "profound" changes in MC. I ended up using tool bar buttons with custom functionality underneath. It's not optimized or uber efficient but it works. I uploaded while I was still tinkering but it should give anyone interested a decent place to start. Code attached...

StartCalc function
 
Code
        protected override void StartCalc()
        {
            if (!toolBarEnabled)
            {
                toolBarEnabled = true;
                ChartToolBar.AccessToolBar(toolBar =>
                {
                    var label = new Label()
                    {
                        Text = "Advanced Patterns",
                        TextAlign = ContentAlignment.MiddleCenter
                    };

                    buttonTriangle = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Draw Triangle",
                        Enabled = true
                    };

                    buttonPattern = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Draw Pattern",
                        Enabled = true
                    };

                    buttonClear = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Clear Points"
                    };

                    buttonRemoveAll = new Button
                    {
                        Dock = DockStyle.Fill,
                        Text = "Remove All"
                    };

                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(label));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonTriangle));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonPattern));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonClear));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(buttonRemoveAll));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    AddItem2ToolStrip(toolBar, new ToolStripControlHost(pointCountLabel));
                    AddItem2ToolStrip(toolBar, new ToolStripSeparator());
                    buttonTriangle.Click += OnTriangleClick;
                    buttonPattern.Click += OnPatternClick;
                    buttonClear.Click += OnClearButtonClick;
                    buttonClear.Click += OnRemoveAllButtonClick;
                });
            }


        private void AddItem2ToolStrip(ToolStrip toolBar, ToolStripItem item)
        {
            item.Tag = this;
            toolBar.Items.Add(item);
        }
        }
I wanted to draw shapes interactively so I am handling mouse clicks. Don't foget to add [MouseEvents(true), SameAsSymbol(true), RecoverDrawings(false)]
 
Code
        protected override void OnMouseEvent(MouseClickArgs arg)
        {
            base.OnMouseEvent(arg);
            try
            {
                switch (arg.buttons)
                {
                    case MouseButtons.Left:
                        {
                            MouseClick = arg;
                            if (!buttonTriangle.Enabled)
                            {
                                pointList.Add(ClickToChartPoint(arg));
                                OnDrawClick();
                                if (pointList.Count == 3)
                                {
                                    _validTriangle = true;
                                    DrawTriangle(pointList);
                                    ResetTriangleButton();
                                }
                            }
                            if (!buttonPattern.Enabled)
                            {
                                pointList.Add(ClickToChartPoint(arg));
                                OnDrawClick();
                                if (pointList.Count == 5)
                                {
                                    DrawPattern(pointList);
                                    ResetPatternButton();
                                }
                            }
                            break;
                        }

                    case MouseButtons.Right:
                        {
                            break;
                        }

                    default:
                        break;
                }
            }
            catch (Exception e)
            {
            }
        }

And here is how I am drawing a triangle
 
Code
private void DrawTriangle(List<ChartPoint> chartPoints)
        {
            try
            {
                DrwTrendLine.Create(chartPoints[0], chartPoints[1]);
                DrwTrendLine.Active.Color = myPen.Color;
                DrwTrendLine.Active.Size = (int)myPen.Width;
                DrwTrendLine.Create(chartPoints[1], chartPoints[2]);
                DrwTrendLine.Active.Color = myPen.Color;
                DrwTrendLine.Active.Size = (int)myPen.Width;
                DrwTrendLine.Create(chartPoints[2], chartPoints[0]);
                DrwTrendLine.Active.Color = myPen.Color;
                DrwTrendLine.Active.Size = (int)myPen.Width;

                CustomDraw(_context);

                ResetTriangleButton(); // reenable to triangle button
                pointList.Clear(); // don't need the points anymore
                OnDrawClick(); // just updates a label on the toolbar (for testing mostly)

                _validTriangle = true;
                requireAdd = true;
            }
            catch (Exception e)
            {
                Alerts.Alert("Error in DrawTriangle: {0}", e.Message);
                ResetTriangleButton();
                pointList.Clear();
                OnDrawClick();
            }
        }

        // helper draw function
        private void CustomDraw(DrawContext dc)
        {
            try
            {
                var pointFs = new List<PointF>();
                var path = new GraphicsPath();

                foreach (var chartPoint in pointList)
                {
                    pointFs.Add(ChartCustomDraw.Environment.ChartPoint2Point(chartPoint));
                }

                float b = pointFs[0].X;
                int bn = (int)b;

                pointFs.Add(ChartCustomDraw.Environment.ChartPoint2Point(pointList[0]));
                //dc.graphics.InterpolationMode = InterpolationMode.Low;

                path.AddLines(pointFs.ToArray());

                dc.graphics.DrawPath(myPen, path);
                //dc.graphics.DrawLines(myPen, pointFs.ToArray());

                if (requireAdd)
                {
                    requireAdd = false;
                    graphicPaths.Add(path);
                }
            }
            catch (Exception)
            {
            }
        }
My Draw function, pretty simple
 
Code
private DrawContext _context;
public void Draw(DrawContext context, EDrawPhases phase)
        {
            _context = context;
            //CustomDraw(context);
        }


Reply With Quote
  #5 (permalink)
 
Jasonnator's Avatar
 Jasonnator 
Denver, Colorado United States
 
Experience: Intermediate
Platform: NT8 + Custom
Broker: NT Brokerage, Kinetick, IQFeed, Interactive Brokers
Trading: ES
Posts: 159 since Dec 2014
Thanks Given: 40
Thanks Received: 166

You create a new indicator and modify the shell with the code in this post. The indicator will initiate a tool bar which is where the custom drawing tools are located. This is very beta and is more of a proof of concept. It can (and should) be significantly improved with try/catch and other error checking. The mouse events are also not very efficient but do work. It is a little quirky in that you have to do things like click in the chart, then click your points. If you can step through with a debugger (attach to process), it will help you understand how things are working.

Started this thread Reply With Quote
  #6 (permalink)
 yiman 
London
 
Experience: Intermediate
Platform: ninjatrader, multicharts, MT4
Broker: IB, PFG Best
Trading: 6E, EMD, TF
Posts: 265 since Jul 2009
Thanks Given: 111
Thanks Received: 158


Jasonnator View Post
You create a new indicator and modify the shell with the code in this post. The indicator will initiate a tool bar which is where the custom drawing tools are located. This is very beta and is more of a proof of concept. It can (and should) be significantly improved with try/catch and other error checking. The mouse events are also not very efficient but do work. It is a little quirky in that you have to do things like click in the chart, then click your points. If you can step through with a debugger (attach to process), it will help you understand how things are working.

Thanks

Reply With Quote
Thanked by:
  #7 (permalink)
 
SteveW's Avatar
 SteveW 
Vancouver, BC, Canada
 
Experience: Intermediate
Platform: Ninja
Broker: Optimus/Rithmic
Trading: ES
Posts: 13 since Jan 2011
Thanks Given: 50
Thanks Received: 32

MC.NET 9.1 -- Has anyone found a way to draw a shaded geometric shape (polygon... whatever) anchored at X,Y that will scroll with prices and not disappear when scrolling? I can draw a trendline or group of them to form the outline of a box and it will scroll with prices and not disappear, but holy cow batman I'm stumped on getting a shaded rectangle to have the same behavior.

-steve

Reply With Quote
  #8 (permalink)
 yiman 
London
 
Experience: Intermediate
Platform: ninjatrader, multicharts, MT4
Broker: IB, PFG Best
Trading: 6E, EMD, TF
Posts: 265 since Jul 2009
Thanks Given: 111
Thanks Received: 158


SteveW View Post
MC.NET 9.1 -- Has anyone found a way to draw a shaded geometric shape (polygon... whatever) anchored at X,Y that will scroll with prices and not disappear when scrolling? I can draw a trendline or group of them to form the outline of a box and it will scroll with prices and not disappear, but holy cow batman I'm stumped on getting a shaded rectangle to have the same behavior.

-steve



I made a request in 2010 so if you are lucky and you make the request now it might be ready for MC.net in 2020 :-)
All you MC or MC net users please get onto the project management forum and add your name to the list of people who want the ability to draw triangles.

Reply With Quote
  #9 (permalink)
 
SteveW's Avatar
 SteveW 
Vancouver, BC, Canada
 
Experience: Intermediate
Platform: Ninja
Broker: Optimus/Rithmic
Trading: ES
Posts: 13 since Jan 2011
Thanks Given: 50
Thanks Received: 32

see title

Reply With Quote
Thanked by:
  #10 (permalink)
 jojojo 
FrankfurtGermany
 
Experience: Beginner
Platform: Tradestation
Posts: 40 since Oct 2010
Thanks Given: 4
Thanks Received: 7


I got an error . Toolbar can not be build.

Reply With Quote




Last Updated on September 9, 2016


© 2024 NexusFi™, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Privacy Policy - Downloads - Top
no new posts