トレーディングオーバーレイ
ポジション、注文、シグナルマーカー、トレードゾーンをチャート上に直接表示します。 手動取引とアルゴリズム取引のどちらのフローにも組み込めるよう設計されています。
トレーディングの無効化
トレーディングオーバーレイは既定で有効ですが、右クリックの注文メニューは無効です(1.3 以降)。
// Drop the entire trading subsystem (no orders, no positions, no overlay)
new Chart(host, { features: { trading: false } })
// Opt in to the right-click "Buy / Sell here" order menu
new Chart(host, { features: { tradingContextMenu: true } })
new ChartWidget(host, { chartOptions: { features: { tradingContextMenu: true } } }) メニューがなければ、チャート上でもブラウザー標準の右クリックが通常どおり動作します。
ポジション
chart.addPosition({
id: 'pos-1',
side: 'long',
entry: 65_200,
quantity: 0.5,
closedQuantity: 0.1, // partial-close band on the left edge
stopLoss: 64_800,
takeProfit: 66_000,
}) 注文
chart.addOrder({
id: 'ord-1',
side: 'sell',
type: 'limit',
price: 65_500,
quantity: 0.25,
}) 価格ラインをドラッグして変更します。変更は chart.on('orderModify', ...) で購読できます。
ライブ執行(アダプターの接続)
既定では、チャートは注文 / ポジションの意図(orderPlace、 orderModify、orderCancel、positionModify、 positionClose)をバックエンド向けに発行するだけで、自ら取引することはありません。 ExecutionAdapter を接続すると、チャートはそれらの意図をアダプターに渡し、
アダプターから返される正式な注文 / ポジションを描画します(アダプターが唯一の信頼できる情報源になります)。
import { PaperExecutionAdapter } from '@tradecanvas/chart'
chart.connectExecution(new PaperExecutionAdapter({ markPrice: 64_000 }))
chart.on('executionError', (e) => toast(e.payload.message))
// chart.disconnectExecution() 実際のブローカーや OMS と接続するには、ExecutionAdapter を実装します(DataAdapter と対になる構造です): placeOrder、modifyOrder、cancelOrder、 modifyPosition、closePosition に加え、orders / positions / fill / error イベントです。 PaperExecutionAdapter は、デモやテスト用に仮想的に約定させるサンドボックスです。
チャート上で注文とポジションを操作する
注文とポジションのラインの右端には小さなボタンがあります。× は注文をキャンセルするか
ポジションを決済し、⇅ はポジションをドテンします。損切りや利確のライン上の × は、
そのラインを削除します。これらは API と同じ意図(orderCancel、positionClose、 positionReverse、null を指定した positionModify)を発行するため、
接続済みのアダプターがそれを処理し、アダプターのないホストアプリにはイベントが届きます。
ボタンは、その上で離したときに動作します。押したまま外へずらした場合は何も起こりません。
どのボタンも setTradingConfig の lineButtons でオフにできます。
chart.setTradingConfig({ lineButtons: { reverse: false } }) // keep cancel, close and remove-stops
chart.cancelOrderIntent('ord-1')
chart.closePositionIntent('pos-1')
chart.reversePositionIntent('pos-1') // close, then the same size the other way
chart.modifyPositionIntent('pos-1', { stopLoss: null }) // null removes the stop 1 回の操作でドテンできるアダプターは reversePosition を実装します。
実装がなければ、チャートはポジションを決済してから、反対方向に成行注文を出します。
注文には stopLoss、takeProfit、timeInForce ('gtc' または 'day')を指定でき、これらはその注文で建てたポジションに引き継がれます。
アダプターの作者へ:PositionModifyIntent では、 stopLoss: null(または takeProfit: null)は削除を意味し、
フィールドがない場合はそのまま維持することを意味します。 intent.stopLoss ?? position.stopLoss のように書いたコードでは、ユーザーが削除した損切りが残ってしまいます。
チャート上の約定
約定はそれぞれのバーに小さなマークで表示されます。ポジションを建てた約定は塗りつぶし、
決済した約定は中抜きです。チャートはアダプターが報告した約定を記録し、約定の理由
('order'、'close'、'reverse'、'stopLoss'、 'takeProfit')と確定した損益を付けて executionFill を発行します。
chart.on('executionFill', (e) => {
const { side, price, quantity, reason, pnl } = e.payload
})
chart.addFill({ orderId: 'o-7', side: 'buy', price: 64_150, quantity: 1, time: Date.now() })
chart.getFills() // the latest 1000
chart.getRealisedPnl() // every fill's P&L since the last clearFills
chart.clearFills()
chart.setTradingConfig({ fillMarks: false }) // no marks 右クリックメニューと価格軸の「+」
チャートを右クリックすると、クリックされた部分('plot'、'pane'、 'priceAxis'、'timeAxis' のいずれか)と、その位置の価格と時刻を含む chartContextMenu が発行されます。features.priceAxisAddButton を有効にすると、
価格軸上にクロスヘアを追って動く「+」が表示され、押すとその価格を含む priceAxisAdd が発行されます。
const chart = new Chart(host, { features: { priceAxisAddButton: true } })
chart.on('chartContextMenu', (e) => {
const { area, x, y, price, time } = e.payload
openMyMenu(x, y)
})
chart.on('priceAxisAdd', (e) => openMyMenu(e.payload.x, e.payload.y, e.payload.price)) ChartWidget のメニューは、これらのイベントの上に作られています。プロット領域を右クリックすると、
その価格でのアラート、買いと売り(約定を待つ側なら指値、反対側なら逆指値)、注文チケット、水平線、
表示のリセット、描画の操作が並びます。価格軸ではスケールの切り替え、時間軸では表示のリセットと
日付への移動が並びます。独自の項目は chartMenuItems で追加できます
(API リファレンスを参照)。
注文チケットと口座パネル(ChartWidget)
ウィジェットのレシートボタンで、チャートの下に口座パネルが開きます。保有ポジションとその損益、
未約定の注文、これまでの約定と確定損益が表示され、各行から決済、ドテン、キャンセルができます。 新規注文では注文チケットが開きます。買いか売り、成行・指値・逆指値、数量、価格、
任意の損切りと利確、有効期限を指定します。入力中に注文をチェックし(買いの指値は市場価格より下、
損切りはエントリーに対して損失側に置く…)、リスクリワード比を表示します。発注すると orderPlace の意図が送られます。
const widget = new ChartWidget(host, {
trading: true, // default
accountPanel: true, // default when trading is on
})
widget.getChart().connectExecution(new PaperExecutionAdapter({ markPrice: 64_000 }))
widget.toggleAccountPanel(true)
// The panel follows ordersChange, positionsChange, executionFill and each tick. 約定マークはチャートに表示中のシンボルに属します。ウィジェットでシンボルを切り替えると、 次のシンボルはマークのない状態から始まります。
ドラッグで注文を作成
ドラッグできる注文ラインを 1 本作り、価格までドラッグして確定します。注文の種類(指値か逆指値か)は、
現在価格に対してどこでドロップしたかで判断されます。connectExecution と組み合わせると、
確定した下書きがすぐに約定します。
chart.startOrderDraft('buy') // draggable line at the latest close
chart.confirmOrderDraft() // emits orderPlace -> a connected adapter fills it
chart.cancelOrderDraft() ブラケット注文(ドラッグで発注)
ドラッグできるブラケット(エントリーに加えて、損切りと利確のゾーン)を作り、3 本のラインをドラッグして
エントリー、リスク、リワードを調整します。Enter(または「発注」ボタン)で確定し、 Esc でキャンセルします。ウィジェットでは、ツールバーの緑 / 赤の矢印でロング / ショートの
ブラケットを開始します。チャートはバックエンドが処理するための bracketPlace イベントを
1 つ発行するだけで、自ら注文を出すことはありません。
chart.startBracket('buy') // entry defaults to the latest close
chart.startBracket('sell', 64_800) // or pin the entry price
chart.on('bracketPlace', (e) => {
const { side, entry, stopLoss, takeProfit, riskReward } = e.payload
// submit to your OMS, then reflect fills back via chart.setOrders/setPositions
})
chart.confirmBracket() // same as Enter
chart.cancelBracket() // same as Esc 板情報(クリックで取引)
オプトインの板情報ラダーは、オーダーブックを価格の行と、買い / 売りの数量の列で表示します。
売り(ask)のセルをクリックするとその価格で買い、買い(bid)のセルをクリックするとその価格で売ります。 depthLadder: true で有効にし、widget.setDepth で板のデータを渡します。
クリックすると OMS 向けの orderPlace の意図が発行されます(チャート自身は取引しません)。
同じデータは、チャート上の板のオーバーレイにも使われます。
const widget = new ChartWidget(host, { depthLadder: true })
widget.setDepth({
bids: [{ price: 64_190, volume: 3.1 }, { price: 64_185, volume: 5.4 }],
asks: [{ price: 64_205, volume: 2.0 }, { price: 64_210, volume: 8.7 }],
})
widget.getChart().on('orderPlace', (e) => {
// { side, type: 'limit', price } — submit to your backend
}) 流動性ヒートマップ
オーダーブックのスナップショットを蓄積し、ローソク足の背後にヒートマップとして表示します。
各スナップショットは縦の帯になり、価格レベルごとに板に並ぶ数量が明るく表示されます(買いは緑、売りは赤)。
時間がたっても残り続ける流動性の壁が浮かび上がります。設定シート(または chart.setDepthHeatmapVisible)で切り替えます。widget.setDepth は
板が更新されるたびにスナップショットを記録します。
chart.setDepthHeatmapVisible(true)
chart.setDepthHeatmapConfig({ opacity: 0.7, capacity: 240 })
// each book update both draws the overlay/ladder and records a heatmap column
widget.setDepth(orderBook)
// low-level: chart.pushDepthSnapshot(orderBook) · chart.clearDepthHeatmap() シグナルマーカー
ボットやシグナル取引との連携で、オーバーレイ上に方向を示す矢印を配置できます。
chart.addSignalMarker({
id: 'sig-12',
time: bar.time,
price: bar.close,
direction: 'long',
confidence: 0.86,
source: 'momentum-bot',
label: 'EMA cross',
})
// A marker under the pointer, and a click on one
chart.on('signalMarkerHover', (e) => showNote(e.payload.marker, e.payload.x, e.payload.y)) // marker null: off it
chart.on('signalMarkerClick', (e) => openSignal(e.payload.marker)) ChartWidget では、ポインターの下にあるマーカーの横にメモを表示します。内容はラベルとソース、方向、 価格、信頼度、時刻です。
トレードゾーン
エントリー → エグジットを、損益で色分けした長方形と方向のバッジで可視化します。
chart.addTradeZone({
id: 'tz-1',
side: 'long',
entryTime: openedAt,
exitTime: closedAt,
entryPrice: 65_100,
exitPrice: 65_800,
status: 'closed',
}) ポジションラベルのトークン
チャート上のラベルをポジションごとにカスタマイズできます。positionLabel には
テンプレート文字列か、文字列を返す関数を指定します。
new ChartWidget(host, {
trading: true,
positionLabel: '{side} {qty} @ {entry} · {pnlSign}{pnlPct}%',
}) 使用できるトークン: {side}、{qty}、{openQty}、 {closedQty}、{entry}、{price}、 {pnl}、{pnlPct}、{pnlSign}。
損益グラデーションのカラーストップ
new ChartWidget(host, {
trading: true,
pnlThresholds: [
{ pnlPct: -0.02, color: '#ef4444' },
{ pnlPct: 0, color: '#94a3b8' },
{ pnlPct: 0.02, color: '#10b981' },
],
})