Untitled

Anonymous
plain_text
10/03/2026 12:47 PM
14.1 KB
1
Indexable
D:\Vela_TradingCharts\Vela>type playground\workspace.ts
// The workspace playground page: a 4-cell VelaWorkspace on live Binance data with the
// page's demo scripting engine and the full shared chrome ΓÇö topbar (symbol / timeframe /
// style / LAYOUT dropdowns, indicator picker, alerts, screenshot, object tree, settings),
// bottombar (range chips, clock, timezone), one keymap. Served straight from src/ (HMR).
//
// Vela ships no scripting engine ΓÇö `demo-engine.ts` is the page's own, written against
// the public port (see widget.ts's header). For Pine Script:
// `npm i @luxalgo/vela-pinets pinets` and `engines: { pine: () => new PineWorkerEngine() }`.
import type { Vela } from "../src";
import { VelaWorkspace } from "../src/workspace";
import { BinanceProvider } from "../src/data/providers/binance";
import { IBKRProvider } from "../src/data/providers/ibkr";
import { DemoEngine } from "./demo-engine";
import { playgroundStorage } from "./persistence";
import { addSampleMarks } from "./marks";

const ws = new VelaWorkspace("#workspace", {
  layout: "4",
  // The unified vocabulary: top-level chart options are every cell's DEFAULT,
  // `cells` overrides per cell. A cell's NAME is its durable identity (persistence,
  // sync groups, ws.cell(name)) ΓÇö DECLARATION ORDER fills the layout's slots, and
  // any entry is optional (an undeclared slot boots on the defaults above).
  symbol: "BTCUSDT", // bare = first declared provider; 'coinbase:BTC-USD' pins a venue
  timeframe: "60",
  cells: {
    btc: { symbol: "BTCUSDT", timeframe: "60" },
    eth: { symbol: "ETHUSDT", timeframe: "15" },
    sol: { symbol: "SOLUSDT", timeframe: "240" },
    bnb: { symbol: "BNBUSDT", timeframe: "D" },
  },
  providers: {
    binance: () => new BinanceProvider(),
    ibkr: () => new IBKRProvider(),
  },
  engines: { demo: () => new DemoEngine() }, // ONE instance per cell (a worker engine would get a thread each)
  defaultLanguage: "demo", // scripts added without a `language` run on the engine above
  // No script manifest: the indicators dialog lists the built-in catalog only.
  live: true,
  theme: "dark",
  autofocus: true, // the workspace IS the page ΓÇö shortcuts work from the first keystroke
  // The playground's CUSTOM persistence (shared with the widget page): the whole
  // workspace document ΓÇö layout, sync, timezone, and per cell the market, renderer
  // config, DRAWINGS and indicators ΓÇö survives a reload via localStorage.
  persist: true, // key 'vela-workspace' → 'vela-play:vela-workspace' in devtools
  storage: playgroundStorage(),
  settings: { hidden: ["advanced"] },
  // ΓöÇΓöÇ The rest of the CHART options (every cell's DEFAULT), at their defaults ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  // bars: 500,                      // history depth per cell
  // data: myBars,                   // offline OHLCV[] for every cell ΓÇö a `cells` entry can override
  // visibleRange: '3M',             // initial window per cell: '1D'…'5Y', 'YTD', 'ALL' or {from,to} ms
  // priceStyle: 'candles',          // default style of every cell ΓÇö a `cells` entry can override
  // volume: true,                   // the built-in volume columns, per cell; false opts out
  // logScale: false,                // logarithmic price scale, per cell
  // currentPriceLine: true,         // dashed line + axis chip at the latest price, per cell
  // upColor: '#089981',             // bullish candles (default: the palette's bullish green)
  // downColor: '#f23645',           // bearish candles (default: the palette's bearish red)
  // glow: 0,                        // neon glow on line series, 0..~0.6 ΓÇö WebGL2 cells only
  // animations: { zoom: true, pan: true, liveBar: false }, // eased zoom + inertial pan + forming-bar glide (true = 90 ms, or a duration in ms); false disables all
  // nativeBackend: 'auto',          // explicit 'canvas2d'/'webgl2' wins over the maxWebglCells policy
  // renderer: NativeRenderer,       // a custom IChartRenderer class for every cell
  // drawings: true,                 // per-cell tools config ΓÇö its `toolbar` key is ignored: the grid's
  //                                 // ONE shared bar replaces per-cell bars (see drawingToolbar)
  // (no `height` here: the grid sizes its cells)

  // ΓöÇΓöÇ The rest of the SHELL options, at their defaults ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  // timeframes: ['1', '5', '15', '30', '60', '240', 'D', 'W', 'M'], // topbar timeframe presets
  // timezone: 'Etc/UTC',            // display timezone (IANA), one zone for every cell
  // statusline: true,               // chrome: the per-cell status line
  // watermark: true,                // chrome: the per-cell symbol watermark
  // bottombar: true,                // chrome: the range-presets + timezone bar
  // topbar: {                       // COMPOSE the topbar: each side lists its VISIBLE
  //   left: ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo"],
  //   right: ["actions", "alerts", "panels", "screenshot"],
  // },
  //                                 // These values ARE the defaults ΓÇö an undeclared side keeps
  //                                 // them, so the option is pure opt-in. Entries render in
  //                                 // LIST ORDER; an id you omit disappears WITH its mobile
  //                                 // entry and its keyboard chord (mod+alt+S goes with
  //                                 // 'screenshot', `/` with 'indicators' ΓÇö Ctrl+Z/Y always
  //                                 // stay). 'actions' is the slot where contributed actions
  //                                 // flow; naming a contributed action's ID instead pins it
  //                                 // at that exact spot (its align/order are then ignored).
  //                                 // An explicit list is the side's COMPLETE contract: it
  //                                 // also freezes it ΓÇö chrome a future release adds won't
  //                                 // appear for a curating host. A plugin can also take a
  //                                 // slot over by registering an action under its id
  //                                 // ('indicators' | 'screenshot') ΓÇö see the plugin SDK.

  // ΓöÇΓöÇ The rest of the WORKSPACE options, at their defaults ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
  // sync: { viewport: true, crosshair: true }, // links between cells, per kind ('viewport' |
  //                                 // 'symbol' | 'timeframe' | 'crosshair'): true = all cells,
  //                                 // or {cellId: group} so only same-group cells follow
  // drawingToolbar: true,           // the ONE shared drawing toolbar (acts on the active cell)
  // maxWebglCells: 8,               // above this many cells, every cell renders canvas2d
  //                                 // (browser WebGL-context budget; glow unavailable there)
});

// The page shell follows the app theme — flip it from any cell's chart settings →
// Canvas → Theme (or `__ws.setTheme('light')` in the console); every LIVE cell relays
// the change, and cells minted by later layout switches are wired as they appear.
const syncShellTheme = (t: { background: string }): void => {
  document.body.style.background = t.background;
};
for (const cell of ws.cells()) cell.chart.on("theme:changed", syncShellTheme);
ws.on("cell:created", ({ id }) =>
  ws.cell(id)?.chart.on("theme:changed", syncShellTheme),
);
// Sample timeline marks (chart.marks) on every cell ΓÇö the ones alive now and those a
// later layout switch mints. Each waits for its own chart to paint, then spreads the
// marks over that chart's visible range (see marks.ts).
const seedMarks = (chart: Vela): void => {
  void chart.ready().then(() => addSampleMarks(chart));
};
for (const cell of ws.cells()) seedMarks(cell.chart);
ws.on("cell:created", ({ id }) => {
  const cell = ws.cell(id);
  if (cell) seedMarks(cell.chart);
});

// Handy for poking around from the browser console (and for the automated probes).
(window as unknown as { __ws: VelaWorkspace }).__ws = ws;

// ΓöÇΓöÇ State surface demo (uncomment to try) ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
// The workspace speaks the SAME state triplet and document format as the widget ΓÇö
// multi-cell here. `persist` above writes exactly this document; the calls below
// are how a host composes custom flows (server snapshots, share links, templates).
//
// // READ ΓÇö the WHOLE grid as one versioned document: layout, splitter tracks,
// // active cell, sync links, timezone, favorites, and per cell (live AND dormant)
// // the market, renderer config, user drawings, and indicator ledger.
// const snapshot = ws.getState();
// console.log('[state] workspace document:', snapshot);
//
// // EVENT ΓÇö fires debounced (~500ms) after any persistable change in ANY cell
// // (pan-synced viewports excluded; drawings, markets, layout, prefs included).
// const offState = ws.on('state:changed', () => {
//     console.log('[state] changed → active cell:', ws.getState().activeCellId);
// });
//
// // WRITE ΓÇö the whole grid rebuilds from the document (cells diff by IDENTITY ΓÇö the
// // names declared above; a layout id must be registered ΓÇö registerLayout ΓÇö before
// // applying). Untrusted-safe: malformed fields are dropped by the shared codec.
// setTimeout(() => {
//     const doc = ws.getState();
//     doc.layout = '2h'; // switch the grid…
//     const btc = doc.charts.find((c) => c.id === 'btc');
//     if (btc) btc.symbol = 'DOGEUSDT'; // …retarget the btc cell…
//     doc.sync = { viewport: true }; // …and link every cell's viewport
//     ws.applyState(doc);
//     offState();
// }, 5000);
//
// // CROSS-SHELL ΓÇö one format: a WIDGET document (layout '1', one `c1` cell)
// // applies here verbatim, and a workspace cell's state restores into a widget.
// // ws.applyState(widget.getState());
D:\Vela_TradingCharts\Vela>
Editor is loading...
Leave a Comment