Situation
You want to know how to create a single-instrument trading strategy that can open or close a position depending on the mouse clicks on the chart.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using ATCenterProxy.interop;
using System.Windows.Forms;         // Added

namespace PowerLanguage.Strategy
{
    [MouseEvents(true), IOGMode(IOGMode.Enabled)]
    public class Example_MarketOrdersWithMouseClicks : SignalObject
    {
        private IOrderMarket enterLong, exitLong;

        public Example_MarketOrdersWithMouseClicks(object _ctx) : base(_ctx) { }
        
        protected override void Create()
        {
            enterLong = OrderCreator.MarketNextBar(
                new SOrderParameters(Contracts.Default, EOrderAction.Buy));

            exitLong = OrderCreator.MarketNextBar(
                new SOrderParameters(Contracts.Default, EOrderAction.Sell));
        }

        protected override void CalcBar() { }

        protected override void OnMouseEvent(MouseClickArgs arg)
        {
            if (arg.buttons == MouseButtons.Left)
            {
                if ((arg.keys == Keys.Control) && (StrategyInfo.MarketPosition == 0))
                {
                    Output.WriteLine("{0} - {1} click + {2}: enter long.",
                        DateTime.Now.ToString("HH:mm:ss.fff"),
                        arg.buttons,
                        arg.keys);

                    enterLong.Send();
                }
                else if ((arg.keys == Keys.Shift) && (StrategyInfo.MarketPosition > 0))
                {
                    Output.WriteLine("{0} - {1} click + {2}: exit long.",
                        DateTime.Now.ToString("HH:mm:ss.fff"),
                        arg.buttons,
                        arg.keys);

                    exitLong.Send();
                }
            }
        }
    }
}

Output of the programming example

After a few clicks, the following text is printed to the Output Window:

07:01:46.409 - Left click + Control: enter long.
07:02:53.055 - Left click + Shift: exit long.
07:02:57.022 - Left click + Control: enter long.
07:03:46.248 - Left click + Shift: exit long.
07:03:50.948 - Left click + Control: enter long.
07:05:22.528 - Left click + Shift: exit long.
07:05:47.398 - Left click + Control: enter long.
07:07:40.408 - Left click + Shift: exit long.
07:07:47.284 - Left click + Control: enter long.

The example strategy looks like:

Example: sending MultiCharts .NET market orders with mouse clicks

Working with mouse clicks in MultiCharts .NET

Indicators and trading strategies can be programmatically controlled in MultiCharts .NET with mouse clicks. This enables things like turning a script on or off, reloading price data, or only calculating a script due to mouse clicks.

See working with mouse clicks and combining mouse clicks with keyboard keys to learn more about MultiCharts .NET’s mouse click features.

There are two requirements for using mouse clicks:

  • The MouseEvents attribute needs to be enabled;
  • The OnMouseEvent() method, which programmatically processes the mouse clicks (see PowerLanguage .NET Help, n.d.), needs to be implemented.

One way to use mouse clicks is to have them submit trading strategy market orders.

Trading strategy market orders in MultiCharts .NET

Implementing market orders in MultiCharts .NET trading strategies has three requirements (MultiCharts, 2013):

  • First, an IOrderMarket object needs to be declared (see line 13 in the example above);
  • Then this object needs to be instantiated (i.e., created in computer memory) in the Create() override method (see lines 19-23). Market orders can be created with the OrderCreator.MarketNextBar() method (for orders that should be send at the open of the next bar on which it was generated) or the OrderCreator.MarketThisBar() method (for submitting orders on the current bar close).
  • Submitting the order is done with its Send() method (see lines 39 and 48).

In the example a click with Control submits an enter long market order, while a click with Shift transmits an exit long order.

P.S. When intra-bar order generation is turned on, orders that are created as ‘next bar’ are actually send on the next tick (MultiCharts Wiki, 2012).

MultiCharts .NET programming example

The example begins with including the System.Windows.Forms namespace, which makes referencing the Keys and MouseButtons enumerations later on easier:

using System.Windows.Forms;         // Added

Then two MultiCharts .NET attributes are added:

[MouseEvents(true), IOGMode(IOGMode.Enabled)]

The MouseEvents attribute enables the processing of mouse clicks. And the IOGMode attribute set to IOGMode.Enabled turns intra-bar order generation on.

Creating market orders in MultiCharts .NET

The next part of the example creates the market orders. First, two IOrderMarket objects are declared:

private IOrderMarket enterLong, exitLong;

Then these are instantiated in the Create() override method:

protected override void Create()
{
    enterLong = OrderCreator.MarketNextBar(
        new SOrderParameters(Contracts.Default, EOrderAction.Buy));

    exitLong = OrderCreator.MarketNextBar(
        new SOrderParameters(Contracts.Default, EOrderAction.Sell));
}

protected override void CalcBar() { }

Both orders are created with the OrderCreator.MarketNextBar() method. This method is passed a new instance of the SOrderParameters struct with two arguments: the number of contracts per trade (set to Contracts.Default here) and an EOrderAction enumerator specifying the type of order (Buy and Sell).

The CalcBar() override method is an abstract method, which makes its implementation by a subclass mandatory (see Liberty & MacDonald, 2009). That is why CalcBar() is included even though it is empty (see line 26).

Send trading orders based on mouse clicks

The OnMouseEvent() method sends the market orders based on mouse clicks:

protected override void OnMouseEvent(MouseClickArgs arg)
{
    if (arg.buttons == MouseButtons.Left)
    {
        if ((arg.keys == Keys.Control) && (StrategyInfo.MarketPosition == 0))
        {
            Output.WriteLine("{0} - {1} click + {2}: enter long.",
                DateTime.Now.ToString("HH:mm:ss.fff"),
                arg.buttons,
                arg.keys);

            enterLong.Send();
        }
        else if ((arg.keys == Keys.Shift) && (StrategyInfo.MarketPosition > 0))
        {
            Output.WriteLine("{0} - {1} click + {2}: exit long.",
                DateTime.Now.ToString("HH:mm:ss.fff"),
                arg.buttons,
                arg.keys);

            exitLong.Send();
        }
    }
}

The arg variable contains the data from the MouseClickArgs struct (see line 28), which has several fields containing mouse click information. Two of these, buttons and keys, are used.

The first if statement (line 30) verifies whether the mouse button clicked is the left mouse button (MouseButtons.Left). The body of the if statement (lines 32-49), executed when the expression evaluates to true, consists out of two parts: submitting the market long order and submitting the exit long market order.

Submitting an enter long market order in MultiCharts .NET

The first part of this nested if statement is as follows:

if ((arg.keys == Keys.Control) && (StrategyInfo.MarketPosition == 0))
{
    Output.WriteLine("{0} - {1} click + {2}: enter long.",
        DateTime.Now.ToString("HH:mm:ss.fff"),
        arg.buttons,
        arg.keys);

    enterLong.Send();
}

See submit limit orders based on mouse click location to see how to use mouse clicks to send limit orders.

Two expressions are evaluated here: whether the keyboard key accompanying the mouse click (arg.keys) is the Control key (Keys.Control) and if the current market position (StrategyInfo.MarketPosition) is flat.

The Output.WriteLine() method is used to print information to the Output Window when both expressions evaluate to true. A string argument is passed in this method that has three values inserted with substitution parameters: the current computer DateTime formatted to a string, the clicked mouse button (arg.buttons), and the pressed down keyboard key during the mouse click (arg.keys).

After that the enterLong’s Send() method is called to submit the enter long market order (line 39).

Submitting an exit long market order in MultiCharts .NET

The second part of the OnMouseEvent() method is an else-if statement:

else if ((arg.keys == Keys.Shift) && (StrategyInfo.MarketPosition > 0))
{
    Output.WriteLine("{0} - {1} click + {2}: exit long.",
        DateTime.Now.ToString("HH:mm:ss.fff"),
        arg.buttons,
        arg.keys);

    exitLong.Send();
}

Two expressions are evaluated here: if the key that was pressed was a Shift key (Keys.Shift) and whether the strategy’s current position is long. In that latter case, the StrategyInfo.MarketPosition property returns a positive non-zero value.

When both evaluate to true, similar information as with the enter long order is printed to the Output Window and the exit long market order is submitted by calling its Send() method (line 48).

Key points:

  • Working with mouse events requires adding the MouseEvents attribute and implementing the OnMouseEvent() method;
  • Market orders first require the declaration of an IOrderMarket object, which then needs to be created in the Create() method. Order submitting is done by calling its Send() method;
  • When intra-bar order generation is enabled, orders that are set to ‘next bar’ are submitted on the next tick. This way multiple orders can be executed in one bar.
References

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

MultiCharts (2013). MultiCharts .NET Programming Guide (version 1.0). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.0.pdf

MultiCharts Wiki (2012, August 31). IntraBarOrderGeneration. Retrieved on August 23, 2014, from http://www.multicharts.com/trading-software/index.php/IntraBarOrderGeneration

PowerLanguage .NET Help (n.d.). Retrieved on May 16, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm

Visit Kodify for more helpful coding articles.