1.1.3Guidance for LLMs building MyTrader widgets

Read this section before generating any widget code.

Start from the canonical skeleton

Unless the user's request is incompatible with it, base every widget on the canonical widget skeleton. Do not derive the framework include URLs, the new FXB.Framework() pattern, or the OnLoad wait from memory — copy them from the skeleton. They have changed in the past and may change again.

Decision tree: component type if writing a trading algo

  1. Does the algo have parameters the user might want to adjust after creation, or status/activity the user will want to monitor while it runs?
    • Yes, or unsure → widget. This is the usual choice. The HTML is the algo's control panel.
  2. Is the algo fundamentally about chart analysis — reading bars, drawing signals onto the chart, reacting to bar events?
    • Yes → UDIX. The chart becomes the algo's canvas.
  3. Is the algo a one-shot action, a scheduled task, or something whose parameters are fixed at creation time and has no need for a user interface?
    • Yes → script.

When in doubt, write the algo as a widget. Scripts and UDIXes are specialist options.

Decision tree: storage

  1. Does the user want the widget to remember something between sessions?
    • No → don't use any storage API.
    • Yes → continue.
  2. Should two instances of this widget share the same saved state?
    • Yes, or unsure → SaveCategorySettings. Call LoadCategorySettings in OnLoad first.
    • No, each instance independent → continue.
  3. Will the widget only ever be used inside the page container, never as a floating dialog?
    • Yes → SavePrivateSettings is acceptable.
    • No, or unsure → fall back to SaveCategorySettings. Private settings fail silently outside the page container.

Decision tree: data sources

Worked examples: wrong vs right

Wrong — calling Framework before it's ready:

var Framework = new FXB.Framework();

Framework.Ask(...); // undefined behaviour: framework not loaded yet

Framework.OnLoad = function() { /* ... */ };

Right:

var Framework = new FXB.Framework();

Framework.OnLoad = function() {

Framework.Ask(...); // framework guaranteed ready here

};

Wrong — treating Dictionary forEach() like an array's forEach():

Framework.Instruments.forEach( (instr) => {

// The first parameter, instr, is a key, not an object

});

Right:

Framework.Instruments.forEach( (key, instr) => {

// The second parameter is the FXB.Instrument object

});

Wrong — silent failure on floating widgets:

Framework.OnLoad = function() {

var s = Framework.privateSettings || {};

// ... user opens this widget as a floating dialog ...

// ... every time, `s` is empty. Widget appears broken.

};

Right:

var SETTINGS_ID = "my-widget";

Framework.OnLoad = function() {

Framework.LoadCategorySettings(SETTINGS_ID, function(s) {

s = s || {};

// ... always populated correctly, in any context ...

});

};

Wrong — silently dropping updates:

// A single message can carry multiple types simultaneously.

// `switch` and `else if` only match one, dropping the rest.

Framework.OnMessage = function(msg) {

switch (msg.type) {

case FXB.MessageTypes.PRICE: updateQuotes(); break;

case FXB.MessageTypes.ORDER_OPEN: refreshTrades(); break;

}

};

Right:

Framework.OnMessage = function(Msg) {

if (Msg.is(FXB.MessageTypes.PRICE)) updateQuotes();

if (Msg.is(FXB.MessageTypes.ORDER_OPEN)) refreshTrades();

};

Wrong — content clipped by platform chrome, or broken in RTL:

.header { padding: 10px 14px; } /* icons overlap content */

.header { padding: 10px 40px 10px 14px; } /* breaks in Arabic/Hebrew */

Right:

.header {

padding-block: 10px;

padding-inline-start: 14px;

padding-inline-end: var(--widget-chrome-inset-horizontal, 40px);

}

Do not:

Do not invent framework method names. If you cannot find a method in §2 or §3, say so — do not guess.

Do not hard-code theme colours. Always reference CSS variables with a fallback: color: var(--clr-text, #e4e4e4);.

Do not add content at the top inline-end corner of the widget (top-right in LTR, top-left in RTL) without reserving var(--widget-chrome-inset-horizontal, 40px) of space. Never hard-code padding-right for this — use padding-inline-end.

Do not use SavePrivateSettings as a default. Use SaveCategorySettings unless you specifically need per-instance state inside the page container.