TWM Wiki

Description

Miscellaneous – Email, Debug, Autoscale & Visual Tools in TWM

Sending Emails

Sending emails from within the platform allows the user to receive trade alerts, risk warnings and status messages even when not sitting in front of the screen, which helps react faster to market events and monitor strategies with less time spent watching charts.

To send emails from code, the user must first configure an email (SMTP) account in TWM and then call SendMail in scripts.


Configure SMTP in Options

1. Open TWM and click on “Tools” (1) and then options (2)

Image


2. Click on “Email” to access the email settings

Image


3. In the Email panel, fill in:

- Host: SMTP server of the email provider.

- Port: SMTP submission port, usually 587 (TLS/STARTTLS) or 465 (SSL).

- Username: Full email address or login name used for SMTP authentication.

- Password: Account password or app‑specific password, depending on provider security.

- Test email: Any destination address for a quick test.

Image


4. Click Send (4) to verify the configuration; only proceed if the test email arrives successfully.

Image


Provider examples

Email providers uses their own settings, always verify the details with the mail provider, here are some examples:

- Microsoft 365 / Outlook

Host: smtp.office365.com, Port: 587 (TLS), Username: user@yourdomain.com

- Gmail / Google Workspace

Host: smtp.gmail.com, Port: 587 (TLS) or 465 (SSL), Username: full Gmail or Workspace address

When 2‑Step Verification is enabled, the user must create an app password in the Google Account and use that as the SMTP password.

- GoDaddy mail

Workspace Email commonly uses smtpout.secureserver.net; Microsoft 365 plans use smtp.office365.com

Port: 465 or 587, Username: full mailbox address, for example alerts@yourdomain.com

- Fastmail

Host: smtp.fastmail.com, Port: 465 (SSL) or 587 (TLS), Username: user@fastmail.com


Sending emails from code

Once an SMTP account is configured and the test email works, the user can send emails from scripts with:

SendMail("receiver@address.com", "subject", "body");


Debug Window

Use the clear debug command to clear the debug window located in New -> Debug at any time.

ClearDebug();

Autoscale

Both strategy and indicator plots can be assigned to an autoscale parameter globaly or individually. Autoscale allows the chart to zoom in/out the plot object automatically when the A button at the top of the Y-Axis of the chart is enabled.

public override void OnStateChanged()
{
if (State == State.SetDefaults)
{
// Will set autoscale for the entire indicator
IsAutoscale = true;
}
}

private void AddIndicators()
{
_maSlow = EMA(Low, PeriodSlow);

// Will set autoscale only for this specific plot
_maSlow.Plots[0].IsAutoscale = false;
}


Image



Drawing Arrows

You can draw arrows pointing in 4 directions. ArrowConnector property defines the point of the arrow that should be attached to the Y property which is in the example below is defined by High and Low prices of the current bar.

The tag property should be unique for each drawing object. If you place an object with the same tag, the old object with the same tag will be overwritten.

if (_enterShort)
Draw.Arrow(this, ArrowDirection.Down, CurrentBar + "Short", 0, High[0], ArrowConnector.End, Brushes.Red);

if (_enterLong)
Draw.Arrow(this, ArrowDirection.Up, CurrentBar + "Long", 0, Low[0], ArrowConnector.End, Brushes.Green);

public enum ArrowDirection
{
Left,
Down,
Right,
Up
}

public enum ArrowConnector
{
Start,
End
}


Coloring Bars

You can conditionally color any bar from code.

if (High[0] > High[1] && Low[0] < Low[1])
{
BarBrush = Brushes.Blue;
}

Adding Custom UI

It is possible for users to add custom UI to chart trader panel to be used from within the strategy/indicator code.

private Button _button;
private Button _button2;

public override void OnStateChanged()
{
if (State == State.SetDefaults)
{
// You might want to complete this line:
// e.g., Name = "YourScriptName";
}
else if (State == State.Configured)
{
Chart.ChartControl.Dispatcher.Invoke(() =>
{
var grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });

_button = new Button
{
Content = "Test2",
Height = 24,
Margin = new Thickness(2)
};

_button.Click += Button_Click;
grid.Children.Add(_button);
Grid.SetColumn(_button, 0);

_button2 = new Button
{
Content = "Test3",
Height = 24,
Margin = new Thickness(2)
};

_button2.Click += Button_Click2; // Now this uses the second handler
grid.Children.Add(_button2);
Grid.SetColumn(_button2, 1);

Chart.AddControl(grid);
});

Chart.ChartControl.MouseLeftButtonDown += MouseClicked;
}
}

private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
MessageBoxWindow.Show("Ok from Button 1");
}

private void Button_Click2(object sender, System.Windows.RoutedEventArgs e)
{
MessageBoxWindow.Show("Ok from Button 2");
}

//don't forget to unsubscribe from all events
public override void OnDisabled()
{

Chart.ChartControl.MouseLeftButtonDown -= MouseClicked;
_button.Click -= Button_Click;
_button2.Click -= Button_Click2;

}


Get Price on Click

It is possible to get the price value from chart at the point where the mouse is clicked, see below example.

public override void OnStateChanged()
{
if (State == State.SetDefaults)
{
SetDefaults();
SetParameters();
}
else if (State == State.Configured)
{
ClearDebug();
AddIndicators();

Chart.ChartControl.MouseLeftButtonDown += MouseClicked;
}
}

protected void MouseClicked(object sender, MouseButtonEventArgs e)
{
try
{
var price = Chart.FormatPrice(Chart.GetCurrentPrice());
MessageBox.Show(price);
}
catch (Exception exception)
{
Print(exception);
}
}


Disabling Plot Parameters in Optimization

During optimization the chart object gets disabled for faster execution. Therefore if you do set any plot parameters inside your OnStateChange method in your strategy you need to disable that for the optimizer.

private void InitializeIndicators()
{
_shortSMA = SMA(Close, ShortSMAPeriod);
_longSMA = SMA(Close, LongSMAPeriod);

if (!this.DataCalcContext.IsOptimization)
{
_shortSMA.Plots[0].Color = ShortSMAColor;
_longSMA.Plots[0].Color = LongSMAColor;
}
}


Addressing Date Time Issues

You can use our custom TWMProperty to create a more user friendly time picker for your parameters.

[TwmProperty]
[TwmTimeProperty]
[Display(Name = "Trade Start 1", GroupName = EntrySettings, Order = 14)]
public DateTime TradeStart1 { get; set; }

Below is an example of how to create a time filter in your TWM indicator or strategy with background coloring effect.

private const string TimeWindowSettings = "Time Settings";

[TwmProperty]
[Display(Name = "Trade Window 1", GroupName = TimeWindowSettings, Order = 56)]
public bool TradeWindow1IsOn { get; set; }


[TwmProperty]
[Display(Name = "Trade Start 1 (hour)", GroupName = TimeWindowSettings, Order = 57)]
public int Trade1StartHour { get; set; }

[TwmProperty]
[Display(Name = "Trade Start 1 (min)", GroupName = TimeWindowSettings, Order = 58)]
public int Trade1StartMin { get; set; }

[TwmProperty]
[Display(Name = "Trade End 1 (hour)", GroupName = TimeWindowSettings, Order = 59)]
public int Trade1EndHour { get; set; }

[TwmProperty]
[Display(Name = "Trade End 1 (min)", GroupName = TimeWindowSettings, Order = 60)]
public int Trade1EndMin { get; set; }

Trade1StartHour = 9;
Trade1StartMin = 30;
Trade1EndHour = 16;
Trade1EndMin = 30;

private void ColorInsideTimeWindow()
{
if (!TradeWindow1IsOn)
return;

var timeNow = ToTime(DateTime[0].Hour, DateTime[0].Minute);
var timeStart = ToTime(Trade1StartHour, Trade1StartMin);
var timeEnd = ToTime(Trade1EndHour, Trade1EndMin);

if (timeStart < timeEnd)
{
if (timeNow >= timeStart && timeNow <= timeEnd)
{
BackBrushAll = Brushes.DarkCyan;
}
}
else if (timeStart > timeEnd)
{
if (timeNow >= timeStart || timeNow <= timeEnd)
{
BackBrushAll = Brushes.DarkCyan;
}
}

}

private bool IsInsideTimeWindow()
{
if (!TradeWindow1IsOn)
return true;

var timeNow = ToTime(DateTime[0].Hour, DateTime[0].Minute);
var timeStart = ToTime(Trade1StartHour, Trade1StartMin);
var timeEnd = ToTime(Trade1EndHour, Trade1EndMin);

//Print("Now: "+ timeNow + " Start: " + timeStart + " End: " + timeEnd);

if (timeStart < timeEnd)
{
if (timeNow >= timeStart && timeNow <= timeEnd)
{
return true;
}
}
else if (timeStart > timeEnd)
{
if (timeNow >= timeStart || timeNow <= timeEnd)
{
return true;
}
}

return false;

}

private int ToTime(int hours, int minutes)
{
// Combine hours and minutes into an integer
int result = (hours * 100) + minutes;

// If the time is midnight (0000), return 1
return result == 0 ? 1 : result;
}

Necessary cookies help make the website usable by enabling basic functions such as consent storage, security protection, language preferences, authentication, and preserving the active navigation context.

  • Necessary cookies

    UserUUID

    Technical identifier used to manage and persist cookie consent preferences.

    Maximum storage duration: 12 Months | Type: Necessary cookies
    consent

    Stores your cookie consent choices and selected preferences.

    Maximum storage duration: 12 Months | Type: Necessary cookies
    site_mode

    Preserves the active navigation context, for example keeping the user in the standard website flow or the Start Trading flow when shared navigation elements are used.

    Maximum storage duration: Up to 30 Days | Type: Necessary cookies
    .AspNet.Consent

    Indicates whether the user has provided cookie consent.

    Maximum storage duration: 1 Year | Type: Necessary cookies
    .AspNetCore.Antiforgery

    Used to prevent CSRF attacks and protect form submissions and user data.

    Maximum storage duration: Session | Type: Necessary cookies
    .AspNetCore.Cookies

    Used to manage authentication information and signed-in sessions.

    Maximum storage duration: 1 Year | Type: Necessary cookies
    .AspNetCore.Culture

    Stores the user’s language and localization preferences.

    Maximum storage duration: 1 Year | Type: Necessary cookies

Functional cookies allow the website to remember preferences and support enhanced features or integrations such as Google services, maps, embedded media, or account-related personalization.

  • Functional Cookies

    LSOLH

    Used by Google to store session information and support service-related functionality.


    Maximum storage duration: Session | Type: Functional Cookies
    COMPASS

    Used by Google to remember settings and improve navigation across integrated services.

    Maximum storage duration: 6 Months | Type: Functional Cookies
    ACCOUNT_CHOOSER

    Remembers which Google accounts have been used on the device.

    Maximum storage duration: 1 Year | Type: Functional Cookies
    APISID

    Used by Google to store preferences and information when using integrated Google services such as Maps.

    Maximum storage duration: 2 Years | Type: Functional Cookies
    LSID

    Used by Google to store preferences while viewing pages that incorporate Google services.

    Maximum storage duration: 2 Years | Type: Functional Cookies
    NID

    Used by Google to remember preferences such as preferred language and interface settings.

    Maximum storage duration: 6 Months | Type: Functional Cookies
    SAPISID

    Used by Google services to support embedded content, maps, and account-related personalization.

    Maximum storage duration: 2 Years | Type: Functional Cookies
    __Host-GAPS

    Used by Google to support service preferences and related functionality on pages integrating Google services.

    Maximum storage duration: 2 Years | Type: Functional Cookies

Statistical cookies help us understand how visitors interact with the site, measure performance, and improve services. Depending on configuration, data may be processed in aggregated or pseudonymized form.

  • Statistical Cookies

    CLID

    Microsoft Clarity identifier used to distinguish visitors and support analytics reporting.


    Maximum storage duration: 1 Year | Type: Statistical Cookies
    MR

    Microsoft cookie used for analytics-related measurement and service improvement.

    Maximum storage duration: 7 Days | Type: Statistical Cookies
    SM

    Used by Microsoft Clarity to maintain the current analytics session.

    Maximum storage duration: Session | Type: Statistical Cookies
    ttcsid

    TikTok identifier used for event measurement, session attribution, and analytics reporting.

    Maximum storage duration: Varies by configuration | Type: Statistical Cookies
    ttcsid_D5GFV53C77U3VC0C2T50

    TikTok event and analytics cookie used for session-level attribution and measurement.

    Maximum storage duration: Varies by configuration | Type: Statistical Cookies

Marketing cookies are used for advertising, campaign attribution, conversion tracking, personalization, and cross-platform measurement by providers such as Google, Microsoft, Meta, and TikTok.

  • Marketing Cookies

    AID

    Used by Google to link activity across devices and improve ad attribution.


    Maximum storage duration: 1 Year | Type: Marketing Cookies
    ANONCHK

    Used by Microsoft Advertising to validate and support ad-related requests.

    Maximum storage duration: 10 Minutes | Type: Marketing Cookies
    MUID

    Microsoft advertising identifier used to recognize browsers across Microsoft domains.

    Maximum storage duration: 13 Months | Type: Marketing Cookies
    __Secure-3PSID, __Secure-3PAPISID, __Secure-3PSIDTS, __Secure-3PSIDCC

    Google advertising and personalization cookies used to build preference profiles and support ad delivery.

    Maximum storage duration: 2 Years | Type: Marketing Cookies
    ADS_VISITOR_ID

    Used by Google to identify visitors for advertising and attribution purposes.

    Maximum storage duration: 2 Years | Type: Marketing Cookies
    OTZ

    Used by Google to support ad personalization and service optimization.

    Maximum storage duration: 1 Month | Type: Marketing Cookies
    __Secure-1PAPISID, __Secure-1PSID

    Google cookies used to support more relevant ads and account-related ad security.

    Maximum storage duration: 2 Years | Type: Marketing Cookies
    IDE, DSID, FLC

    DoubleClick / Google Ads cookies used for campaign attribution, ad delivery, and remarketing.

    Maximum storage duration: Varies by cookie | Type: Marketing Cookies
    datr, fr, sb, xs

    Meta / Facebook cookies used for browser recognition, security, ad measurement, and personalization across Meta services and partner sites.

    Maximum storage duration: Varies by cookie | Type: Marketing Cookies
    odin_tt

    TikTok cookie used for campaign attribution, browser recognition, and advertising performance measurement.

    Maximum storage duration: Varies by cookie | Type: Marketing Cookies
    tt_chain_token

    TikTok cookie used for event attribution and campaign linkage across sessions.

    Maximum storage duration: Varies by cookie | Type: Marketing Cookies
    ttwid

    TikTok browser identifier used for attribution, advertising measurement, and remarketing support.

    Maximum storage duration: Varies by cookie | Type: Marketing Cookies
    NID, UULE

    Google cookies that may support ad personalization, localization, and service preference handling depending on the integration and browser state.

    Maximum storage duration: Varies by cookie | Type: Marketing Cookies
    SEARCH_SAMESITE

    Google cookie used to support secure cookie handling across requests and service interactions.

    Maximum storage duration: 6 Months | Type: Marketing Cookies
About cookies and consent

This website uses cookies and similar technologies to ensure its proper functioning and, with your consent, to support functionality, measure usage, improve performance, and provide advertising, attribution, or personalized content. The legal basis for the use of necessary cookies is the legitimate interest of the data controller (Art. 6(1)(f) GDPR), while functional, statistical, and marketing cookies are used only upon your explicit consent (Art. 6(1)(a) GDPR).

Cookies are small text files stored on your device to make the website work efficiently and improve your experience. Some cookies are placed directly by us, while others may be set by third-party services integrated into our pages.

Cookie categories
  • Necessary cookies: enable core site functionality such as consent storage, navigation context, language selection, authentication, and access to secure areas. These cannot be disabled.
  • Functional cookies: allow the website to remember settings and support integrations such as embedded or third-party services.
  • Statistical cookies: collect usage and performance data to help understand and improve the site.
  • Marketing cookies: support advertising, campaign attribution, personalization, and remarketing across providers and services.
Storage and consent management

Your cookie preferences are stored locally in a cookie named consent, valid for 12 months, and pseudonymously on our systems using a technical identifier (UserUUID), which does not allow direct identification of the user. A technical cookie named site_mode may also be used to preserve the current navigation context across pages. You may change or withdraw your consent at any time via the cookie settings button visible at the bottom left of the site.

Third-party cookies

Some cookies are provided by third-party services such as Google, Microsoft, Meta, and TikTok. These third parties may act as independent controllers for the data collected through their own technologies and services.

Your rights

You can withdraw or modify your consent at any time, delete cookies through your browser settings, and exercise your rights under Articles 15–22 GDPR (access, rectification, deletion, limitation, opposition, portability) by contacting us via the details provided in the Privacy Policy.

This Cookie Policy is aligned with Regulation (EU) 2016/679 (GDPR) and the ePrivacy Directive.