Examples

1.1 Examples

The Sway Charts Pro platform contains examples of scripts, of a widget, and of a UDI (but not specifically a UDIX). You can use these as a starting point in addition to this guide.

The Run Script widget lets users without programming experience nevertheless create scripts from common actions such as placing trades, and then save those scripts for future use, make them accessible as icons in the software's banner etc.

The External Widget contains a simple HTML example of a widget which displays a configurable market, current prices for that selected market, and a button for opening the platform's standard deal ticket.

The screen for adding a UDI to a trading chart includes an example UDI.

1.2 Framework access

All the features of the Sway Charts Pro framework are provided via a single base object. This is accessed slightly differently in widgets versus scripts and UDIXes.

In a script or UDIX, there is automatically a Framework object which gives you access to Sway Charts Pro. For example: Framework.SendOrder()

In a widget, you need to do four things in the widget's web page:

· Include the framework Javascript and CSS

· Create an instance of the framework

· Wait for the framework to become available

· Don't reload!

1.2.1 Linking to the framework's Javascript and CSS in a widget

Scripts and UDIXes have automatic access to the framework. A widget needs to include the following references in its HTML (usually in the <head>):

<script src="https://proapi.swaycharts.io/scripts/widget-js"></script>

<link rel="stylesheet" type="text/css" href="https://proapi.swaycharts.io/css/widget-css"/>

1.2.2 Creating an instance of the framework in a widget

Scripts and UDIXes automatically have a Framework object. A widget needs to declare a new instance of the framework, in its page's Javascript, rather than having one provided for you automatically:

<script>

// Create an instance of the framework

var Framework = new Sway.Framework();

1.2.3 Waiting for the framework to become available in a widget

As described in more detail below, widgets must not use any features in the framework until it signals that it is ready by calling the OnLoad() function in your Framework object. Scripts and UDIXes can start using their Framework object as soon as they start running.

1.2.4 Reloading or navigation in widgets

A widget must not navigate to another page, or reload itself. This will break its communication with the framework.

For example, if your widget submits a form, it must do so using something like Ajax to send the data, rather than doing a full page POST which causes a reload or navigation of your widget page.

1.3 Browser environment

Widgets, scripts, and UDIXes have normal access to the browser's Javascript environment. For example, they can use setInterval() or setTimeout() to carry out delayed actions, and they can use XMLHttpRequest to collect external data (though see below).

Scripts and UDIXes run as web workers. Therefore, there is no web page for them to interact with, and web workers also don't have access to some browser features such as localStorage. But, because they are web workers, scripts and UDIXes can use importScripts() to include external code – subject to standard browser security as described below.

Widgets, scripts, and UDIXes can create web workers to offload complex tasks (in the case of scripts and UDIXes, web workers creating other web workers). In other words, the browser environment makes it possible to have fully multi-threaded processing, with time-consuming tasks done in the background.

Nothing in Sway Charts Pro is allowed (or able) to use browser modals such as alert() and confirm(). Web workers don't have access to these features, and widgets are prevented from using them by the sandboxing of their iframe. The framework provides alternatives such as Ask() which you can use instead of browser modals – but please note that these are asynchronous.

You can use standard features of your browser to inspect and debug your code. For example, you can insert the debugger; keyword in your Javascript to pause your code in the browser's Developer Console.

1.4 Asynchronous operation

Most operations in the framework are asynchronous. The most obvious example is placing a trade: you send a trading request and you provide a callback function (or "completion handler", or whatever term you prefer) which the framework later calls when the action completes. For example:

Framework.SendOrder(orderDefinition, function(MsgResult) {

// Function called asynchronously by the framework when the order succeeds or fails

});

Another example would be asking the user a question by displaying the framework's standard Ask() dialog:

Framework.Ask("Are you sure?", function (Msg) {

// Called asynchronously by the framework

});

This example is in fact slightly more complicated than it looks. Your asynchronous callback from Ask() gets called twice, not once. The second call is the result; the user's response. The first call is an update which gives you the ID of the dialog, giving you the ability to cancel the dialog yourself – for example, if the user takes too long to decide.

And some types of asynchronous callback can get called multiple times. For example, if you issue a request for candle data then – unless you specifically say that you don't want streaming – your callback function will get called multiple times: with an initial batch of candles, and then with each update as the price changes and the current candle is modified or a new candle is formed. For example:

Framework.RequestCandles(candleDef, function(Msg) {

// Called repeatedly, until you terminate it with TerminateCandleRequest()

});

1.5 Javascript Promises

For every function in the framework which uses an asynchronous callback, there are two versions: one which issues a Promise, and one which takes a more traditional callback function. For example, the code to display a dialog to select an instrument can be written in either of the following ways:

// Traditional version

Framework.SelectInstrument(function(instrumentId) {

// Called asynchronously by the framework when the user selects a market, or cancels

});

// Version using Promise (and optional arrow function)

Framework.pSelectInstrument().then( (instrumentId) => {

// Called asynchronously by the framework when the user selects a market, or cancels

});

The framework uses a simple naming convention where the "standard" version of the function is something like SelectInstrument() and the Promise version has a p prefix such as pSelectInstrument().

Promises in the framework always settle by fulfilling, never by rejecting. For example, a trading request settles by fulfilling regardless of whether it succeeded or failed, with a parameter describing the success or failure result.

There can be subtle differences between the standard and Promise versions of functions. For example – as described in the previous section – RequestCandles() issues multiple, repeated, streaming callbacks as price changes modify the current candle or start a new one. But a Promise can only settle once; it can't have multiple callbacks. Therefore, pRequestCandles() is always treated as a static, non-streaming request.

1.5.1 Async functions and await syntax

The existence of Promises also means that it's possible to use Javascript await syntax, instead of the callback functions – or then() – which are used in this document, and generated by the Run Script widget.

Scripts are automatically run inside an async function. Therefore, it's possible to write code such as the following:

var result = await Framework.pSendOrder({"tradingAction": Sway.OrderTypes.FLATTEN});

Framework.EndScript();

It's not necessary to declare an async function and then pass execution into that:

async function MyAsyncFunction()

{

var result = await Framework.pSendOrder({"tradingAction": Sway.OrderTypes.FLATTEN});

Framework.EndScript();

}

MyAsyncFunction();

1.6 Component lifecycle

1.6.1 Script lifecycle

Scripts run forever until they call Framework.EndScript(), or the user shuts them down. They don't simply run "from top to bottom" of their code and then automatically terminate. This is because most operations in the framework are asynchronous, and the script may be waiting for an action to complete. The script needs to tell the framework when it has finished.

Consider the following example:

Framework.Ask("Are you sure?", function (Msg) {

// Called asynchronously by the framework

});

Framework.EndScript();

This won't work. The script will create the ask dialog, but then immediately terminate (also destroying the dialog) before it has got a response. This script should instead be written as follows:

Framework.Ask("Are you sure?", function (Msg) {

// Called asynchronously by the framework

// … do something based on the user's response

// And, finally, tell the framework that we're done

Framework.EndScript();

});

// When execution gets here, we're waiting for the user's response to the Ask().

// We don't want to terminate.

1.6.2 UDIX lifecycle

The lifecycle of a UDIX is simply tied to the chart on which it is running. A UDIX cannot remove itself from its trading chart; only the user can do this.

1.6.3 Widget lifecycle

Widget lifecycle is a little more complicated because a widget is a web page and there are two separate events: loading of the HTML page, and loading of the framework.

Widgets should (normally) have an OnLoad() function. This is called by the framework when it has finished loading, and your code should not try to use any part of the framework – retrieving data, carrying out actions such as placing trades – before the framework says it is ready by calling your OnLoad().

For example, the following code is not safe and won't work:

// Create an instance of the framework

var Framework = new Sway.Framework();

// OnLoad handler

Framework.OnLoad = function() { … Called asynchronously. Framework is now ready };

// **WON'T WORK**. This is executed immediately, before the framework has

// had a chance to set itself up, and before it has done a callback into OnLoad().

Framework.Ask(…);

If the user has added your widget into the Sway Charts Pro page container, then the widget runs until the user switches to another page. You can't "close" your widget in this context (which would leave a blank space in the page).

If the user has loaded your widget as a dialog or floating panel, then you can choose to close the window. The framework's CancelDialog() function will close the window (and will have no effect if your widget has been added into the page container).

1.6.3.1 Permanent widgets

By default, widgets in the page container are unloaded when the user navigates to a different page of the app's configuration. (They can save state and later reload it in order to provide a seamless transition between pages.)

However, it is possible for a widget to keep running after a change of the active page. Such widgets are also always reloaded on restart, even if they are not on the active page.

This mechanism is designed for trading algos (and for similar widgets such as the Excel RTD) which need to keep providing services even if they are not on the active page. It should only be used where necessary. Asking to run permanently, rather than saving state and reloading as the user switches between pages, can affect the performance of the whole Sway Charts Pro app.

A widget specifies that it needs to run permanently by returning mustRemain:true in its state. The widget must implement OnGetState(). For example:

Framework.OnGetState = function()

{

return {

// Keeps the widget open, and reloads it immediately on app startup even if

// not on the active page

mustRemain: true,

// Any other state which the widget wants to store/report

};

};

1.7 External data and hosting

Widgets, scripts, and UDIXes can use the standard features of the browser environment to collect external data. For example, you can use XMLHttpRequest to collect data from remote servers, or make websocket connections.

Scripts and UDIXes are web workers, and therefore they can use importScripts() to load external code. For example, you can host the Javascript for a script externally, and then run it within Sway Charts Pro using a single line of code:

importScripts("https://www.myserver.com/myscript.js");

However, all use of external resources is subject to standard browser security restrictions (which it's not possible for Sway Charts Pro to override, even if wanted to):

· For XMLHttpRequest, the remote server must put CORS headers on its response. If it doesn't, the browser will block the response.

· All requests must be made over secure connections (https:// or wss://). Sway Charts Pro is hosted at an https:// address, and standard browser security prevents anything inside it making calls to insecure addresses. You cannot link to resources at http:// addresses or request data from http:// addresses.

Similarly, if you host a widget externally rather than pasting its HTML into the External Widget, then the URL for your widget must be https://, not http:// (and you obviously must not set any X-Frame-Options header on your page).

1.8 Account capabilities

The features which the framework can provide depend on the capabilities of the trading back-end/account which Sway Charts Pro is logged into. For example, some accounts support trailing stops whereas others do not. Some accounts can only provide the historic trades on the account, not the historic credit movements.

Perhaps most importantly, some accounts support "hedging" – a buy order and then a sell order for the same market create two separate open trades in that market rather than cancelling each other out – whereas other accounts are "netting" and only ever report a single net position (or no position) in a market.

You can inspect what the back-end system supports using the features information in the Framework.Account.

1.9 Data representations and standards

The framework uses some standard representations of data:

· The framework makes widespread use of a standard dictionary/hashtable class, Sway.utils.Dictionary().

· All dates/times are UTC and expressed as a number of milliseconds since January 1st 1970. The framework provides functions for converting between UTC and different time zones.

· Time zones are represented as a structure consisting of an offset, in minutes added to UTC, and a dstMode which defines a daylight-savings schedule: 0 = none, 1 = US schedule, 2 = European schedule, 3 = Australian schedule. For example, New York time is defined as {offset: -300, dstMode: 1}.

· Regardless of the back-end system which it is logged into, the framework represents all trading volumes, such as the volume of an Sway.Order, as cash/units, such as 10,000, rather than as a figure in lots such as 0.10. You can convert between cash/units and lots using the contractSize of an Sway.Instrument.

· All candle data in Sway Charts Pro is based on bid prices. Volume – where available from the broker's back-end system – may be either real traded volume or tick pseudo-volume (i.e. MT4-style volume where the "volume" is a count of the number of price changes in the period).

· All chart timeframes for candle data, such as M1 or H4, are expressed as a number of seconds, e.g. 3600 for H1. Sway Charts Pro uses 604800 for weekly (W1) and 2592000 for monthly (MN1).

1.10 Future additions to the framework

There will be future additions to the framework. The web version of Sway Charts Pro will automatically update, but the mobile/tablet app will require user intervention.

The framework has a RELEASE property, currently 1. This will be incremented in future versions, and this guide will note where functions/features require a compatibility level greater than 1.

If your code uses new features of the framework it may need to check the RELEASE level and warn if the mobile/tablet app has not been updated – that the feature you are trying to use is not available.

1.10.1 Undocumented members of the framework

You may notice – for example, through the browser's Developer Console – that there are objects and properties in the Framework which are not described in this guide. These are not safe to use. Backward compatibility and consistent behaviour are only guaranteed for things which are covered in this guide.

Last updated