QUANTRESEARCHER STUDIO · C# AUTHORING

読みやすいコードで、
ストラテジーを書く。

1つのRobotクラスで記述し、SMA・EMA・RSI・ボリンジャーバンド・MACD・ATRをシンプルな呼び出しで更新できます。コールバックと注文の動作を確認しながら学べます。

Robot[Parameter]コールバック注文ヘルパー

01実行モードと注文の検索

ReplayContext は次の読み取り専用 Boolean プロパティを提供します。通常の Studio 実行では、いずれか一つだけが true です。実行モードを提供しないカスタムホストでは RunMode == StrategyRunMode.Unknown となり、五つとも false です。

プロパティtrue になる場合
context.IsPaperLightspeed Paper など、ブローカーのシミュレーション/デモ口座での実行
context.IsLiveブローカーの実口座での実行
context.IsBacktest単独の履歴バックテスト
context.IsOptimize単独の最適化の各試行
context.IsResearchResearch の学習・検証・アウトオブサンプルの各試行

最適化と Research では IsBacktest は false です。データ配信元ではなく実行目的を示し、開始・終了・派生バーのコールバックでも同じモードを参照できます。Windows と Ubuntu のコマンドライン実行でも同じ判定を使用します。

C# · QR strategy API
if (context.IsPaper) Print("Paper execution");
var orders = context.PendingOrders.Where(x => x.Label == "maker");
var positions = context.Positions.Where(x => x.Label == "maker");
var firstOrder = context.PendingOrders.FirstOrDefault(x => x.Label == "maker");

Where は一致する全要素を返します。一件だけ取得する場合は FirstOrDefault を使用し、null を確認してください。Studio のストラテジーコンパイラーは LINQ を自動的にインポートします。明示的な using System.Linq; も引き続き使用できます。ラベル省略時は null なので、x.Label == "" はコンパイルできますが null には一致しません。ラベルなしの検索には string.IsNullOrEmpty(x.Label) を使用します。context.PendingOrders の注文は context.CancelOrder(order.Id) で取消要求できます。context.Positions は建玉ハンドルを返します。ブローカーの未約定注文一覧は当該ストラテジー所有の注文ですが、建玉には他のストラテジーや手動取引の数量が含まれる場合があります。

エディターの候補では context.PendingOrders と context.Positions を使用します。ラベル検索、ラムダ変数、実行モード、Symbol.TickSize、Symbol.TimeZone、Symbol.NormalizePrice(...)、context.Bars / context.Quotes の過去観測値にも対応します。旧名の TradingPositions と TradingPendingOrders は互換性のため残しますが、主要な候補には表示しません。候補は API 記述支援であり、コンパイル確認には Validate C# を使用してください。

02クイックスタート

Strategies → New strategyで新規ソースを開き、次の完全な例を入力します。Save source…またはCtrl+Sで保存し、Validate C#、Use this code in backtestの順に進み、Quoteデータを選択します。数量、資金、費用、実行フィード、期間を確認してから実行してください。

検証時にストラテジー型が検出されます。複数の対象型がある場合は目的の型を選びます。以前の完全修飾型名のテキスト欄への入力は不要です。ソースファイルの保存と、検証済みライブラリースナップショットの作成は別の操作です。

C# · QR strategy API
using QuantResearch.Engine;
using QuantResearch.Strategies;

namespace QuantResearcherExamples;

public sealed class EmaRsiExample : Robot
{
    [Parameter("Quantity", Group = "Trading", DefaultValue = 1,
        MinValue = 1, MaxValue = 10000, Step = 1)]
    public int Quantity { get; set; }

    public override void OnQuote(ReplayContext context, Quote quote)
    {
        ExponentialMovingAverage fast = Indicators.ExponentialMovingAverage(quote.Bid, 20);
        ExponentialMovingAverage slow = Indicators.ExponentialMovingAverage(quote.Bid, 50);
        RelativeStrengthIndex rsi = Indicators.RelativeStrengthIndex(quote.Bid, 14);

        if (!fast.IsReady || !slow.IsReady || !rsi.IsReady) return;

        decimal target = fast.Close > slow.Close && rsi.Close < 70m ? Quantity : 0m;
        SetTargetPosition(quote.Symbol, target);
    }
}

この学習用の例は、指定数量のロングまたはフラットを目標にします。起動時には注文せず、Quoteのたびに新規ポジションを積み増す処理ではありません。三つのインジケーターをすべて更新してから準備完了を確認するため、長い期間の計算も継続してウォームアップできます。閾値は記述例であり、収益性を示すものではありません。まず一つのシンボルをリプレイで使い、数量単位を確認してください。複数シンボルでは、届いたシンボルごとに独立した判断を行います。

この例にOnStartは不要です。初期化が必要なら、public override void OnStart(ReplayContext context)を一つ記述します。確定足を使う場合はOnBarClosed(ReplayContext context, BarClose bar)へ処理を移し、bar.Closeとbar.Symbolを使用します。期間は観測回数であり、経過分数や日数ではありません。

03検証済みコードへの切替

Execution のインスタンスで Apply validated updates automatically を有効にすると、明示的な検証の成功後、対象インスタンスを制御された停止・起動で更新します。旧ランタイムの終了コールバックでは取引コマンドを無効にし、Studio が自身の未約定注文を取り消して確認した後、新しい実行を開始します。建玉と互換性のあるパラメーターは保持し、private 変数、管理注文の追跡状態、インジケーターは初期化します。OnStart は現在の口座状態で再実行します。取消と競合した約定は建玉として残し、更新処理では決済しません。private 状態がコード更新をまたいで保持されることを前提にしないでください。通常の注文照合がストラテジーを自動再開することはありません。

04パラメーター

編集可能な設定は、公開されたインスタンスの自動プロパティに[Parameter]を付けて宣言します。get; set;はともにpublicで、対応C#型はint、decimal、double、bool、stringです。

C# · QR strategy API
[Parameter("Enabled", Group = "Core", DefaultValue = true)]
public bool Enabled { get; set; }

[Parameter("Threshold", Group = "Signal", DefaultValue = "0.50",
    MinValue = "0.00", MaxValue = "1.00", Step = "0.05")]
public decimal Threshold { get; set; }

各パラメーターには明示的な初期値が必要です。最小値、最大値、Stepは数値型だけに指定します。Stepは画面の増減幅だけでなく、許容値の間隔として検証されます。decimalの属性値はカルチャに依存しない文字列で指定できます。0.05mのようなdecimalリテラルはC#属性引数には使えません。

プロパティ名が、大文字と小文字を区別する保存設定のキーになります。属性の表示名とGroupは画面の整理に使われ、キー名は変更しません。パラメーターはOnStartより前に設定されます。複数項目間の制約はOnStartで確認できます。EffectiveParametersとParameterSchemaは検証済み入力を表し、実行中にプロパティを変更しても保存リクエストを書き換えません。

static、nullable、enum、任意のオブジェクト、インデクサー、独自アクセサー、init専用のプロパティは、このAPIのパラメーター宣言として扱いません。宣言できるパラメーターは最大128個です。ソース変更で以前の検証は無効になり、編集中のコンパイル診断だけでは実行可能状態になりません。

Symbolプロパティは任意です。コールバックではquote.Symbol、trade.Symbol、bar.Symbolを、対象一覧にはSymbolsを使います。シンボルを省略した成行注文は現在のイベントを利用します。起動時に省略する場合は対象が一つである必要があります。複数対象ではシンボルを明示してください。ストラテジーのシンボルは正確なアプリケーション内の別名であり、口座IDや固定列挙型ではありません。

05ライフサイクルとコールバック

RobotはResearchStrategyを継承し、protectedなContext、Positions、PendingOrders、Symbols、Indicators、Buy、Sell、Printと注文ヘルパーを提供します。特記がないものはpublic overrideで実装します。

コールバック引数利用できる情報・用途
OnStartReplayContext contextパラメーター設定後の初期化。架空の現在価格はありません。
OnBarOpenedReplayContext context, BarOpen bar始値が利用可能になります。
OnBarClosedReplayContext context, BarClose bar確定したOHLCVが利用可能になります。
OnTradeReplayContext context, Trade trade観測された取引価格と任意の数量。
OnQuoteReplayContext context, Quote quoteBid/Askと任意の各サイド数量。
OnInformationReplayContext context, InformationEvent information利用可能になったニュース・財務情報。
OnFxRateReplayContext context, FxRate rate明示的な換算レート。
OnFuturesSettlementReplayContext context, FuturesSettlement settlement明示的な先物清算。
OnStockSplitReplayContext context, StockSplit split明示的な株式分割。
OnDividendEntitlementReplayContext context, DividendEntitlement entitlement配当権利の観測。
OnDividendPaymentReplayContext context, DividendPayment payment配当支払の観測。
OnStopReplayContext context、またはprotectedな引数なしoverride起動成功後の読取専用終了処理。中断・失敗時も対象です。

既定のOnEvent(context, MarketEvent)は、型に対応するコールバックへ振り分けます。OnTick(context, MarketEvent)はTrade/Quoteを受け取り、OnTrade/OnQuoteへ振り分けます。汎用メソッドをoverrideすると、その振り分けも担当します。型別フックも呼びたい場合だけ、base実装をちょうど一度呼びます。一つの観測を重複処理しないよう、通常は一つの階層を使ってください。

引数なしOnStartはありません。通常、OnStopはどちらか一つの形式だけをoverrideします。OnStartが失敗した場合は、その途中までの初期化を自身で後始末します。従来のOnFinish(context)は正常終了時だけ、OnStopの前に呼ばれます。終了処理では発注・訂正・取消できません。履歴終端で強制決済されるわけではありません。

注文・約定・ポジション通知

OnOrderUpdate(ReplayContext context, StrategyOrderUpdate update)は、同じ引数の名前付きメソッドへ振り分けます。対象はOnOrderSubmitted、OnOrderAccepted、OnOrderAcknowledged、OnOrderReplaced、OnOrderTriggered、OnOrderPartiallyFilled、OnOrderFilled、OnOrderCancelled、OnOrderExpired、OnOrderRejected、OnOrderUnknownです。

OnFill(ReplayContext context, StrategyFill fill)は実際の約定を報告します。OnPositionChanged(ReplayContext context, StrategyPositionUpdate update)は数量・取得原価の変化を報告し、該当するOnPositionOpened、OnPositionClosed、OnPositionReversedへ振り分けます。評価価格が動くだけではポジション遷移になりません。反転は一つの遷移であり、架空の中間フラット状態を作りません。

通知のStampには、Source、ObservedAt、任意のOccurredAt、利用可能なローカル/ブローカー識別子があります。リプレイ、ローカル要求、応答、照合を区別してください。注文送信は約定ではなく、取消拒否も元の注文自体の拒否とは限りません。CommandKindを確認します。

C# · QR strategy API
public override void OnFill(ReplayContext context, StrategyFill fill)
{
    Print("FILL", fill.Symbol, fill.Side, fill.Quantity, fill.Price,
        fill.Stamp.OccurredAt);
}

これはRobotクラス内に置くメソッド例です。Printはカルチャに依存しない形式で実行のLogへ出力し、取引状態を変更しません。コールバックは同期処理です。コンテキストやコマンド用ハンドルを背景スレッド用に保持したり、非同期処理が自動で待機されると仮定したりしないでください。ワーカーは実行・終了を管理しますが、悪意あるコード用のセキュリティサンドボックスではありません。

06インジケーター

その時点で観測した値を渡すだけで、インジケーターを利用できます。戻り値は現在のスナップショットで、Robotが計算履歴を保持します。専用の初期化クラスや履歴キューを別途用意する必要はありません。

以下は利用者向けシグネチャです。コンパイラーが供給する任意の呼出位置情報は省略しています。価格・計算結果はdecimal、期間・Countはintです。

C# · QR strategy API
SimpleMovingAverage SimpleMovingAverage(decimal value, int period, string? key = null)
ExponentialMovingAverage ExponentialMovingAverage(decimal value, int period, string? key = null)
RelativeStrengthIndex RelativeStrengthIndex(decimal value, int period, string? key = null)
BollingerBands BollingerBands(decimal value, int period = 20, decimal deviations = 2m, string? key = null)
MovingAverageConvergenceDivergence MovingAverageConvergenceDivergence(
    decimal value, int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9, string? key = null)
AverageTrueRange AverageTrueRange(
    decimal high, decimal low, decimal close, int period = 14, string? key = null)

Indicators.RelativeStrengthIndex(quote.Bid, 14)のように、Indicatorsを通して呼び出します。

戻り値型メンバー準備完了・計算規則
SimpleMovingAverageClose, Period, Count, IsReadyローリング窓の算術平均。Period個で準備完了。
ExponentialMovingAverageClose, Period, Count, IsReady最初のPeriod個の算術平均をシードとし、その後のalphaは2 / (Period + 1)。
RelativeStrengthIndexClose, Period, Count, IsReady上昇・下落幅をWilder方式、alpha=1 / Periodで平滑化。Countは変化数。RSI 14は15価格で準備完了。
BollingerBandsClose, Middle, Upper, Lower, Deviations, Period, Count, IsReadyMiddle/CloseはSMA。幅は正のDeviations × 母標準偏差。Period個で準備完了。
MovingAverageConvergenceDivergenceClose, Line, Signal, Histogram, FastPeriod, SlowPeriod, SignalPeriod, Count, IsReadyLine/Closeは短期EMA−長期EMA。Signalは準備済みLineのEMA。HistogramはLine−Signal。
AverageTrueRangeClose, Period, Count, IsReadyTrue RangeをWilder方式で平滑化。Period個の高値・安値・終値で準備完了。

SMA、EMA、Bands、ATRのウォームアップ中の値は、途中までのシード/窓を表します。全期間を前提にする売買条件では必ずIsReadyを確認してください。RSIは上昇・下落平均がともに0なら50、下落平均だけ0なら100、上昇平均だけ0なら0です。最初の価格ではCountは0で、その後の価格変化でシードを作ります。途中の値を完成したRSIと混同しないでください。

MACDはfastPeriod < slowPeriodを必要とします。価格EMAはともにSMAシードを使い、長期EMAの準備完了後からSignalへLineを渡します。全体の準備完了はslowPeriod + signalPeriod - 1価格で、既定の12/26/9では34価格です。長期EMAの準備前はLine/Signal/Histogramが0で、Signalの準備前は途中のSignalです。共通のIsReadyを確認します。

ATRはmax(high - low, abs(high - previousClose), abs(low - previousClose))を使用し、最初の範囲はhigh−lowです。low <= close <= highを満たす入力が必要です。実際に利用可能になった確定OHLCを渡します。

C# · QR strategy API
public override void OnBarClosed(ReplayContext context, BarClose bar)
{
    BollingerBands bands = Indicators.BollingerBands(bar.Close, 20, 2m);
    MovingAverageConvergenceDivergence macd =
        Indicators.MovingAverageConvergenceDivergence(bar.Close, 12, 26, 9);
    AverageTrueRange atr = Indicators.AverageTrueRange(bar.High, bar.Low, bar.Close, 14);

    if (!bands.IsReady || !macd.IsReady || !atr.IsReady) return;
    Print(bands.Middle, bands.Upper, bands.Lower, macd.Line, macd.Signal, atr.Close);
}

これはRobotクラスに置く、発注しない別の例です。OnBarOpenedで未来の高値・安値・終値を読むためには使えません。Bandsの標準偏差は母分散と倍精度の平方根計算を使います。別ライブラリーとシードや数値演算の規則が違えば、ビット単位で同じ値になるとは限りません。

履歴の識別と上限

呼出位置、入力式、インジケーター種類・設定、シンボル、イベント種類ごとに履歴を分けます。複数シンボルのQuoteは独立し、BarOpenとBarCloseも別系列です。ローカル変数を書いても、イベントごとに履歴が作り直されるわけではありません。

準備完了判定や注文待ちによるreturnより前に、必要なすべてのインジケーターを更新してください。条件付きで呼ぶ場合は、実際に渡した観測だけが数えられます。同じイベントで同一系列を再度呼んでも二重更新せず、異なる入力を渡すとエラーになります。同じ時刻でも別イベントの場合があります。

共通ヘルパーを通す系列は、短い明示的なkeyで識別できます。別の論理系列には別キーを使います。キーを同じにしてもシンボルやイベント種類は統合されません。期間・設定の変更は別系列になります。履歴はリプレイ/ライブ起動ごとにリセットされ、ライブのコールバックごとのコンテキスト再接続では保持されます。未来の履歴や期間前のウォームアップを自動ロードしません。

期間は1~1,000,000ですが、Robot全体で最大4,096系列、設定値容量の合計1,000,000という共通上限があります。MACDは各構成期間を容量に計上します。明示キーは最大256文字です。Quote、Trade、BarOpen、BarClose内で呼び出し、OnStartで架空の価格を使って初期化しないでください。不正入力や数値オーバーフローはエラーになります。

07成行注文・指値注文

Robotのdecimal型ヘルパーは、longのローカル注文IDを返します。

C# · QR strategy API
SubmitMarketOrder(OrderSide side, string symbol, decimal quantity,
    string? label = null, decimal? stopLossPips = null, decimal? takeProfitPips = null,
    string? comment = null)

SubmitMarketOrder(OrderSide side, decimal quantity,
    string? label = null, string? comment = null)

SubmitLimitOrder(OrderSide side, string symbol, decimal quantity, decimal targetPrice,
    string? label = null, decimal? stopLossPips = null, decimal? takeProfitPips = null,
    DateTimeOffset? expiresAt = null, string? comment = null)

シンボル省略型はRobot上にあり、label/commentを受け取りますがpip保護の引数はありません。シンボルを明示するdecimal型メソッドはcontextにもあります。

C# · QR strategy API
long orderId = SubmitMarketOrder(Buy, quote.Symbol, 1m,
    label: "Entry", comment: "Observed quote signal");

これはコールバック内部の記述例です。無条件に各観測で注文せず、信号・ポジション管理の条件を適用してください。Buy/SellはRobotのOrderSide定数です。数量は正で、商品の数量単位を使用します。成行に目標価格や未約定期限はありません。指値のtargetPriceは絶対価格です。期限省略はGTC、明示期限はリプレイのGTDで、指定時点を含まない期限になります。

double型の別名メソッドもlongを返します。

C# · QR strategy API
ExecuteMarketOrder(OrderSide tradeType, string symbolName, double volume,
    string? label = null, double? stopLossPips = null, double? takeProfitPips = null,
    string? comment = null)

PlaceLimitOrder(OrderSide tradeType, string symbolName, double volume, double targetPrice,
    string? label = null, double? stopLossPips = null, double? takeProfitPips = null,
    DateTimeOffset? expiration = null, string? comment = null)

値はdecimalの実行モデルへ変換されます。非有限値や表現できない値は拒否されます。入力がdecimalならdecimalメソッドを使ってください。二つのAPIでexpirationとexpiresAtという引数名が異なる点にも注意してください。

その他の対応注文設定には、下位のcontextメソッドがあります。

C# · QR strategy API
long SubmitOrder(string symbol, OrderSide side, decimal quantity,
    OrderType type = OrderType.Market, decimal? limitPrice = null, decimal? stopPrice = null,
    TimeInForce timeInForce = TimeInForce.Gtc, DateTimeOffset? expiresAt = null)

こちらはシンボルが最初の引数で、便利メソッドのラベル・保護引数はありません。注文種類や有効期間の対応はリプレイ/ブローカーで異なります。context.ReplaceOrder(long orderId, decimal quantity, decimal? limitPrice = null, decimal? stopPrice = null)は総数量と指定価格を変更し、null価格は現在値を保持します。context.CancelOrder(long orderId)は残注文を取り消します。不明・終了済みIDはfalseです。ライブでは観測済みブローカーIDも必要になります。

目標ポジション

SetTargetPosition(string symbol, decimal desired)はRobotのprotectedヘルパーです。desiredは新規注文量ではなく、符号付き純ポジションの目標です。正がロング、負がショート、0がフラットです。自身が管理する未約定数量を含め、取消応答を待ち、不明な送信の予約を保持します。最新の判断はOrderStateで確認できます。関係のない注文を取り消しません。ライブの純ポジションには手動注文や別ストラテジーが含まれることがあり、シンボル一致だけでは独占所有になりません。

08ポジションと未約定注文

Positionsは純ポジションのIReadOnlyList<TradingPosition>、PendingOrdersは利用者の未約定要求のIReadOnlyList<TradingPendingOrder>です。観測情報と保護された操作ハンドルであり、両建ての独立チケットではありません。

型主なメンバー・操作
TradingPositionnullableなId、EntryPrice、Currency、ラベル/コメント。Symbol、符号付きQuantity、Side、LabelState、保護距離/価格。long? Close()。
TradingPendingOrderId、Symbol、Side、Type、総数量、nullableな約定/残数量、価格、ラベル/コメント、有効期間/期限。bool Cancel()。
両方ModifyStopLossPips(double?)、ModifyTakeProfitPips(double?)、decimal型のModifyStopLossPipsDecimal(decimal?)、ModifyTakeProfitPipsDecimal(decimal?)。戻り値はbool。

各コールバックで新しいポジションハンドルを取得します。Closeは反対売買の成行要求であり、即時約定の保証ではありません。古い・変化済みのハンドルは拒否され、保護注文を含む既存未約定注文を確認してから新しい決済を要求します。同じハンドルへの繰り返しCloseは以前の要求を返します。

ライブ数量が不明な場合はHasFilledQuantity、FilledQuantityOrNull、RemainingQuantityOrNullを確認し、不明を0に置き換えないでください。ラベルはローカルな帰属情報で、LabelStateはUnknown/Homogeneous/Mixedです。変更には制御可能で曖昧でないポジション識別が必要です。

RobotのPendingOrdersは、リプレイの付属保護子注文を除きます。診断には生のcontext.PendingOrdersを利用できますが、保護は所有元ポジションから操作します。保護変更へのnullは解除/省略で、指定距離は正です。未対応の機能は要求を黙って捨てずエラーにします。

09Pipsと保護注文

pipは明示的な価格距離で、最小価格ティックとは別です。pip距離を使う前に正のPipSizeを設定します。シンボル、通貨、小数桁から推測しません。PipSizeが0.01で20pipsなら、価格グリッド調整前の距離は0.20です。これは算術例であり、その通貨の全商品に適用する慣例ではありません。

リプレイのSL/TPは、純ポジションの世代に紐づく数量削減専用の逆指値/指値です。建玉約定後に開始し、後続観測から約定対象になります。実際の取得原価と価格グリッドへの外向き調整で水準が決まるため、StopLossPrice/TakeProfitPriceを確認します。部分決済で兄弟注文を縮小し、フラットで取り消し、保護約定は関連する建玉注文の残りも取り消します。古い保護が新たに反転・再建玉することはありません。

矛盾する保護・所有宣言は拒否されます。全体変更は純ポジションに作用し、架空の独立チケットには作用しません。ギャップ後の逆指値は閾値を越えて約定する場合があります。確定OHLCVから足の中の価格経路は分からず、BarOpen実行で安値が閾値を割っただけでは約定根拠になりません。明示的な株式分割方針では未約定注文と保護を解除し、調整済み注文を勝手に作りません。

現在のライブ記述層は、ブローカー側の付属SL/TP、pip保護の変更、GTDに非対応です。該当要求は明示的に失敗します。保護なし注文へ置き換えたり、リプレイ保護をブローカー保持の保護と表示したりしません。

10データと約定タイミング

イベントコールバック時に利用できる情報
BarOpen始値だけ。未来の高値・安値・終値・最終出来高はありません。
BarClose確定Open、High、Low、Close、Volume。約定価格を提供しません。
TradePrice、Volume、HasVolume。不明な数量と0は区別します。
QuoteBid、Ask、Midpoint、任意のBidSize/AskSize。
InformationEvent情報源、識別子、指標、公表・取得・利用可能時刻。
FxRate直接観測された換算レート。注文を約定しません。

MarketEventはUTCのTimestamp、正確なSymbol、元ストリーム内のSequenceを持ちます。contextはCurrentEvent、全体のEventOrdinal、Portfolio、生のPendingOrders、CancellationToken、任意のLiveAccountを公開します。同時刻でもordinalが異なる場合があります。起動・照合では現在のマーケットイベントがない場合があります。

リプレイは会計・評価、期限、対象となる既存注文をマーケットコールバックより前に処理し、安定した境界で通知を配信します。OnStartからの注文は最初の対象観測を利用できます。

新規デスクトップリクエストでは現在Quoteの成行約定が有効です。Quote実行を選び、現在届いたQuoteと同じシンボルへ成行を送ると、残るサイド数量の範囲で買いAsk/売りBidになります。送信メソッドの戻り前に会計・ポジションは更新され、通知は遅延配信されるのでコールバックへ再帰的には入りません。既存注文が先に数量を消費し、GTC残は待機、IOC残は取消になります。付属保護は後続の対象観測を待ちます。

他の注文・実行フィードには、それぞれの後続観測の規則が適用されます。他シンボルのQuote、キャッシュ価格、確定OHLC、情報イベントは現在Quoteとして利用できません。設定を解除すると従来の次観測成行モデルに戻り、古い保存リクエストは元の意味を保持します。履歴終端での信号は、未約定注文や保有ポジションを残す場合があります。

商品の実行フィードは一つ選びます。EventVolume流動性にはTradeの数量やQuoteのサイド数量が必要で、不明数量を作りません。Unboundedはリプレイの仮定です。手数料、契約乗数、企業行動、証拠金モデルが会計に影響し、ResearchLedgerでは純資産が負になる場合があります。

異通貨リプレイには明示的な履歴FXと許容経過時間が必要です。時間設定はレート取得機能ではなく、未来や今日の参考レートで過去を補いません。情報イベントのSnapshotFetchedUtcとPublicationApproximationは利用可能時刻の意味が異なります。返された公表日だけでは、改訂後の値が当時も存在した証明になりません。

期間指定やResearch区間は、以前のウォームアップを自動ロードせず、状態・ポジションを持ち越さず、最後の強制決済も行いません。研究の各区間は新規状態で始まります。コールバックに届いた観測だけを使ってください。独自の有限履歴にはRollingWindow<T>があります。Robotに暗黙のプロバイダークライアントや無制限の履歴Barsは付属しません。

11ライブ実行の対応範囲

リプレイとライブは関連するコールバック型を使いますが、根拠と対応機能は異なります。コンパイル/バックテスト成功は、ブローカーの受付試験や取引所認証ではありません。

プロバイダー/情報源現在の範囲
Saxo OpenAPI株式、FX Spot、対応CFD、期日のある先物。正確な契約と口座権限が必要です。
Interactive BrokersClient Portal Web APIまたはGateway/TWSソケットによる株式。ソケットには別途導入した公式C# APIを使います。
Lightspeed Connect対応株式の発注。利用権を持つ別のマーケットデータが必要です。
Databento live明示的に選ぶ最良気配・取引・取引状態のフィード。注文ブローカーではありません。

現在のデスクトップの商品範囲でオプションは非対応です。BloombergとTrading Technologiesは利用できません。名称の掲載は、すべての市場、口座、注文、購読に対応することを意味しません。

現在のConnect/Applyは口座照合を行います。ストラテジーStartと確認済みの手動Submitは明示操作で、以前の独立したRisk/Arm手順はありません。Quote元時刻が古いという理由だけでは直接実行を停止しませんが、時刻、遅延警告、不正価格、切断、未来時刻、取引状態、契約の確認は残ります。口座照合の経過時間は別です。古いリスクポリシーを明示的に選ぶAPI利用者には、そのポリシーが適用されます。

Live確認と該当する認可は引き続き必要です。owner/developmentのセッション設定は、一般顧客の商用ライセンスや本番発行者の構成ではありません。接続だけで発注せず、証拠金、権限、数量、市場規則はブローカーが判断します。最小数量に合わせて利用者の数量を勝手に増やしません。

ライブのOnOrderSubmittedはローカル要求で、Acknowledgedはコマンド応答であり約定証明ではありません。ブローカーIDが未確認なら取消・訂正できない場合があります。不明な結果や未約定一覧からの欠落は照合し、無条件に再送しないでください。手動とストラテジーは口座純ポジションを共有します。停止・切断だけで全注文取消が確認されたとはいえません。JournalとストラテジーLogは別の役割です。

12ストラテジーのサンプル

Moving average crossover

Fast/slow SMA crossover with separate timeframe-minute parameters. Register once in OnStart; completed candles update automatically; prior selected replay data or compatible live history warms the averages. Supports bars, bid quotes or trades. Any minute interval from 1 to 1440 is supported. Averages are compared as entered; equal settings stay flat.

ストラテジー型
StudioExamples.MovingAverageCrossover
ソースファイル
MovingAverageCrossover.cs
C# · MovingAverageCrossover.cs
Download .cs
using System;
using QuantResearch.Engine;
using QuantResearch.Strategies;
namespace StudioExamples;
// Independently authored educational example. No profitability or execution guarantee.
// Register once in OnStart: completed candles update both SMAs automatically.
// Prior selected replay data and compatible live history warm indicators automatically.
// IsReady protects against insufficient history; OnBarClosed runs once per candle.
// Choose separate timeframes in minutes. No Update call is needed.
// SetTargetPosition handles pending orders; bar-based orders fill on a later eligible observation.
public sealed class MovingAverageCrossover : Robot
{
    private BarIndicator<SimpleMovingAverage> sma_fast = null!;
    private BarIndicator<SimpleMovingAverage> sma_slow = null!;

    [Parameter("Symbol", Key = "Symbol", Group = "Trading", DefaultValue = "DEMO")]
    public string SymbolName { get; set; } = "DEMO";

    // Keep Symbol metadata bound to this configured instrument in every callback.
    protected override string? SymbolNameOverride => SymbolName;

    [Parameter("Quantity", Group = "Trading", DefaultValue = 1, MinValue = 1, MaxValue = 1000000, Step = 1)]
    public int Quantity { get; set; } = 1;

    [Parameter("Fast", Group = "Signal", DefaultValue = 10, MinValue = 1, MaxValue = 1000, Step = 1)]
    public int Fast { get; set; }

    [Parameter("Slow", Group = "Signal", DefaultValue = 30, MinValue = 1, MaxValue = 1000, Step = 1)]
    public int Slow { get; set; }

    [Parameter("Fast timeframe minutes", Group = "Timeframe", DefaultValue = 1, MinValue = 1, MaxValue = 1440, Step = 1)]
    public int FastTimeframeMinutes { get; set; } = 1;

    [Parameter("Slow timeframe minutes", Group = "Timeframe", DefaultValue = 1, MinValue = 1, MaxValue = 1440, Step = 1)]
    public int SlowTimeframeMinutes { get; set; } = 1;

    public override TimeSpan BarTimeframe => TimeSpan.FromMinutes(FastTimeframeMinutes);

    public override void OnStart(ReplayContext context)
    {
        sma_fast = Indicators.SimpleMovingAverage(TimeSpan.FromMinutes(FastTimeframeMinutes), Fast, SymbolName);
        sma_slow = Indicators.SimpleMovingAverage(TimeSpan.FromMinutes(SlowTimeframeMinutes), Slow, SymbolName);

        if (string.IsNullOrWhiteSpace(SymbolName) || SymbolName != SymbolName.Trim())
            throw new ArgumentException("Set Symbol to the selected data symbol.");
        // Compare the configured averages as entered; equal settings stay flat.
    }
    public override void OnBarClosed(ReplayContext context, BarClose bar)
    {
        if (bar.Symbol != SymbolName) return;
        if (!sma_fast.IsReady || !sma_slow.IsReady) return;

        if (sma_fast.Close > sma_slow.Close)
        {
            SetTargetPosition(SymbolName, Quantity); // Buy up to the desired position.
        }
        else
        {
            SetTargetPosition(SymbolName, 0m); // Sell the long position and stay flat.
        }
    }

}

ソースは1つずつ開いて検証してください。各サンプルはRobotを直接継承します。ZIPには個別のストラテジーとテンプレートを収録しています。

ソースの確認

SHA-256 · d8c5258cbf1e6e751afc109425ba1e8a6c4c190b1f2b5079fff3bd759acce71e

ソースマニフェストを保存

ソース集には15のライブラリー例と2つの開始用テンプレートがあります。すべて直接Robotを継承するストラテジークラスです。各ソースを個別に開き、入力モデルに合うパラメーターとデータで検証してください。

ソース目的/入力
DemoRoundTrip.cs基本的な新規・決済のライフサイクル。
BuyAndHold.cs起動時に建玉。履歴終端にポジションが残る場合があります。
EventObserver.cs読取専用のイベント観測。
MovingAverageCrossover.cs確定足と履歴保持SMAによるトレンド。
MeanReversion.cs確定足の過去窓z-score。
ChannelBreakout.cs過去確定足の高値・安値チャネル。
TradeMomentum.cs観測取引によるモメンタム。
QuoteMomentum.csスプレッド・数量条件付き気配中値モメンタム。
MultiSymbolTrend.cs二つのシンボルの独立した確定足トレンド。
MultiTimeZoneSessionTrend.cs名前付きローカル時間帯内の取引観測。
QuoteTradeConfirmation.csQuote/Trade観測を組み合わせ、一つの実行フィードを選択。
PassiveBidAskLadder.cs未約定要求を管理する数量上限付き指値ラダー。
NewsFilteredMovingAverage.cs利用可能なニュースで条件付けする確定足トレンド。
JQuantsStatementForecast.cs明示的な財務諸表・価格ルール。学習済み機械学習ではありません。
JQuantsFundamentalForecast.cs明示的な財務指標・価格ルール。学習済み機械学習ではありません。
TypedCallbackObserver.cs型別コールバックを観測する読取専用テンプレート。
MyStrategy.cs編集用の空のテンプレート。

これらはプログラミング例で、収益性を検証済みのシステムではありません。タイムゾーンを使う信号が取引所休日カレンダーを備えるとは限りません。信号の鮮度条件だけでは、既存GTC注文が取り消されるわけではなく、ストラテジーによる取消が必要です。

13既存ソースの移行

  1. ソースを保存し、導入したリリースで開き直して検証します。別リリースのコンパイル済み成果物を再利用しないでください。
  2. Indicatorsなどの便利機能にはRobotを直接継承します。既存ResearchStrategyコードは、その明示的なAPIを継続利用することもできます。
  3. 自作SMA/EMA/RSIのキューを置き換える際は、入力、シード、ウォームアップを一致させます。すべてのインジケーター更新を準備完了判定・早期returnより前に置きます。
  4. 必要ならSymbolパラメーターを保持し、またはevent.Symbol/Symbolsを利用します。別名からブローカー契約を推測しないでください。
  5. 過去結果と比較するときは現在Quote設定を確認します。約定時点の違いで損益は大きく変わります。注文判断時のPrintを過去の約定と読み替えないでください。
  6. 新しいライブラリー例を開くと書き直されたソースを取得できます。エディター復元は既存の文書を保持し、更新でカスタムコードを上書きしません。

Save source/Ctrl+Sはファイル保存、Validate C#は実行用ライブラリースナップショットの作成です。ディスク上の競合は通知し、無断で上書きしません。比較にはソース、データ識別、設定、保存証跡を保持してください。

14トラブルシューティング

症状確認事項
インジケーターが準備完了しないreturnより前に必要な観測を供給します。RSI 14は15価格、既定MACDは34価格です。イベント種類と履歴長も確認します。
入力重複・矛盾エラー別系列には別の呼出位置/明示キーを使います。一つの系列は一イベントにつき一入力です。
起動時にインジケーターが使えないOnStartや情報・状態通知ではなく、Quote/Trade/Barコールバックで呼びます。
信号があるのに注文しない対象、パラメーター、目標・未約定状態、口座/契約、履歴を確認します。
注文が約定しない実行フィード、時点、後続観測、流動性、指値/逆指値、期限、セッションを確認します。確定足は約定の根拠になりません。
損益が想定と違うTrade Historyと判断ログ、現在Quote設定、数量、資金、手数料、乗数、FXを比較します。
保護が拒否されるリプレイではPipSize、ホストでは対応機能を確認します。現在のライブ付属pip保護は非対応です。
決済・訂正・取消に失敗最新ハンドルと確認済みIDを読み、未約定・所有状態を確認し、ライブを照合します。
SharpeがN/AResultsのカードにマウスを合わせます。日次数、非正の純資産、分散0、統計不足などで未定義になります。
古い結果に約定履歴がない記録を有効にして再実行します。保存結果は後から補完しません。
SDK・ハッシュ・検証が不一致同じリリースの完全なパッケージを使い、ソースを再検証します。整合性検査を回避しません。
通知数上限に達する再帰的・無条件の注文ループを除き、同期コールバックの処理を有限にします。

問い合わせにはリリース、操作、ソース/型、対象データと期間、機密情報を除いた診断を添えます。APIキー、パスワード、口座の生の識別子を含めないでください。

15ダウンロード・バージョン

オフライン版 · MARKDOWN

コードのそばにリファレンスを。

このリファレンスを保存し、ローカルで検索・参照できます。

APIガイドを保存 ↓
サンプルソース · C# / ZIP

実行できるソースから始める。

ライブラリーのストラテジー、イベント観測用サンプル、空のRobotテンプレートと必要データの説明。

全サンプルを保存 ↓

本M71リファレンスはStrategy APIプロトコルバージョン1と現在のソース記述用機能を説明します。過去のコンパイル済みストラテジーとのバイナリ互換性や、他社API全体の実装を約束しません。導入したアセンブリでソースを再コンパイルしてください。

アーカイブのソース識別は公開版と一致する必要があります。お客様のストラテジー、データ、認証情報、プロバイダー利用権は含みません。動作依存関係、任意SDK、ソフトウェア通知は、口座権限や商取引上の条件とは別です。

16M73: 時間足指定と起動時の指標準備

OnStart で fast = Indicators.SimpleMovingAverage(TimeSpan.FromMinutes(5), 20); のように登録します。戻り値は BarIndicator<SimpleMovingAverage> です。完成した5分足20本を使い、自動更新されます。EMA・RSI・ボリンジャーバンド・MACD・ATR も同じ TimeSpan 指定に対応します。C# の 5m は小数値であり5分ではありません。複数銘柄を選ぶ場合は symbol: を指定します。

Robot のバーコールバックは、約定または気配データからも自動生成されます。既定は1分足で、public override TimeSpan BarTimeframe => TimeSpan.FromMinutes(5); により変更できます。既定の気配足は Bid、約定足は実約定価格です。UTC基準で区切り、空の期間や未完成の最終足は作りません。約定価格は実際の実行用データを使います。

ライブ開始時はブローカーから互換性のある過去足を取得し、指標だけを準備します。過去データで売買コールバックは実行しません。取得中と完了後の本数・準備状況が画面に表示されます。最大500本、全体30秒の制限があり、価格基準・時間足が一致しない場合や履歴不足の場合は新しい完成足で継続します。必ず IsReady を確認してください。手動の Create… / Update API は従来通りで、自動履歴取得には TimeSpan オーバーロードを使用します。

詳しくは [時間足・履歴準備の仕様(英語)](TIMEFRAME_INDICATORS_M73.md) を参照してください。

17時間足を設定できるサンプル(M74)

9種類の指標サンプルは OnStart で時間足付き指標を登録し、ライブ開始時に互換性のある履歴バーで自動ウォームアップします。MovingAverageCrossover の FastTimeframeMinutes と SlowTimeframeMinutes で短期・長期の時間足を個別に設定できます。他の8種類は TimeframeMinutes、初期値は1分です。検証後、各実行画面のパラメーターで変更してください。履歴が不足する場合は必要な確定バーが揃うまで待ちます。新しいサンプルは Strategy library から開いてください。保存済みユーザーコードは書き換えません。詳しくは[サンプルガイド](TIMEFRAME_SAMPLES_M74.md)をご覧ください。

18リプレイ開始前の自動ウォームアップと確定足コールバック(M75)

OnStart で登録した時間足付き指標は、選択済みデータに開始日より前の価格があれば自動でウォームアップします。Backtest / Optimize は Date From より前、Research は学習・検証・OOS の各区間より前の価格を使います。各区間は独立して初期化され、未来の価格は使いません。ウォームアップ中は売買コールバックを呼ばず、約定・損益・資産曲線・ドローダウン・Sharpe・イベント数にも含めません。履歴不足時は IsReady が true になるまで待ちます。

BarTimeframe に判定用の時間足を設定すると、より細かい OHLC 入力の場合も含めて、確定した足ごとに OnBarClosed が1回呼ばれます。時間足付き指標はその直前に更新されます。サンプルの lastDecision 判定は不要になりました。OnQuote / OnTrade / OnTick は選択期間内の各観測で引き続き呼ばれます。詳細は[ウォームアップとコールバック](REPLAY_WARMUP_M75.md)をご覧ください。

19時間足インジケーターの最適化 (M76)

サンプルは1~1440の任意の整数分に対応します。最小値1・刻み15の範囲は1、16、31、…です。一般的な時間足に絞る場合はValuesで1、5、15、30、60などを指定してください。足の基準は固定UTC起点(0001-01-01)で、1日を割り切れない間隔でも日付変更時に短縮されません。既存の1日を割り切る時間足の境界は変わりません。OHLC入力は選択した足の境界内に収まる必要があります。

MovingAverageCrossoverはFastとSlowを入力どおり比較し、同じ期間や逆順でも実行できます。同じ設定ならポジションを持ちません。長い時間足・期間では準備に十分な履歴が必要です。エラーなく完了しても取引がなく、スコア0になる場合があります。

最適化に失敗した場合は、原因となった候補のパラメーターと実際のエラーを表示します。連動してキャンセルされた候補の情報で原因を隠しません。新しいサンプルはStrategy libraryから開いてください。保存済みのユーザーコードは変更しません。

20無効な最適化候補と大きな探索空間 (M77)

OptimizeとResearchは、取引開始前のパラメーター検証で拒否された組合せを自動的にスキップします。OnStartでArgumentExceptionを投げた場合は、理由付きの採点対象外試行(skipped_invalid)として保存します。無効候補は最良候補・遺伝的探索の親・検証候補に選びません。実行中のエラーはContinueOnFailure設定に従います。

ResultsのSKIPPED INVALIDで件数を表示し、Search trialsでは各試行のパラメーター、理由、フォールドと段階を確認できます。Researchでは同じ組合せでも訓練・検証・OOSの別試行を個別に数えます。有効候補がないフォールドはスキップして次へ進みます。OOS候補の選び直しは行わず、欠けたフォールドがあれば全体OOS損益合計を表示しません。

変化させるパラメーターは最大128個です。Geneticでは、10,000,000通りを超える候補空間も全列挙せずに探索できます。Geneticはその中の一部を探索し、全組合せをメモリーに展開しません。MaximumEvaluationsはスキップを含む最大試行数(1~10,000)のままです。世代数と時間制限も適用します。Gridは全組合せが試行予算内に収まる必要があります。個別パラメーターの宣言範囲外の値は、実行前に入力欄で修正してください。

21長時間の実行とデータ準備の並列化(M78)

Backtest、Optimize、Research のフォームでは、ワークフロー・探索・各候補の自動タイムアウトを撤廃しました。停止したい場合は Cancel task を選択してください。評価件数と世代数の上限は引き続き適用されます。日別ファイルの検証・準備は、PC の論理プロセッサ数を上限として最大16個のワーカーで並列実行します。この上限は同時実行中の候補間で共有されます。進捗は処理済みファイル数を示します。再生順序、破損検証、過去データのみを使うウォームアップは維持されます。速度はCPUとストレージに依存します。

プログラムから指定するタイムアウトの既定値は Timeout.Infinite(ミリ秒指定で -1)です。ワーカーには Timeout.InfiniteTimeSpan を指定できます。既存の保存済みリクエストやCLIで明示された正のタイムアウト値は有効です。Studio のフォームから実行すると、古いリクエストを読み込んだ場合も自動期限のない新しいリクエストが作成されます。

22入力データの再利用と保存済みパラメーター(M79)

Studio は同じ起動セッション内で、検証済みデータ、リプレイ用コピー、日付範囲ごとの入力を Backtest・Optimize・Research 間で再利用します。ファイルが変更された場合は再検証します。正確な開始・終了日時とウォームアップ設定を区別するため、Research の異なる期間が混ざることはありません。再起動後の初回は準備が必要です。各ワーカーの整合性確認は継続します。準備済みキャッシュの未使用部分は 32 GiB/256 件を上限とし、実行中の入力は利用終了まで保持します。

Results の Strategy name はクラス名のみを表示します。# of Trades は約定数です。新規・決済・分割約定をそれぞれ数え、Trade History と一致します。往復取引の組数ではありません。保存済み結果を選択して Parameters タブを開くと、実行時の有効なパラメーターを確認できます。Optimize は最良候補、Research は各 OOS フォールドを表示し、画面の損益・約定数に対応する最終フォールドを明示します。有効値を保存していない旧結果は、送信した値であることを表示します。現在編集中のコードや設定は保存済み結果に影響しません。詳細は [キャッシュと Results](DATA_CACHE_RESULTS_M79.md) を参照してください。

23指値注文セットの自動更新(M91)

従来のRefreshLimitOrders(quote, RefreshEveryQuotes, orders => { ... })も利用できます。現在の組み込みPassiveBidAskLadderは後述のM93方式を使用します。コールバックではorders.Add(side, quantity, price)で価格と数量を指定します。最初の有効な気配で注文セットを作成し、以後は設定した気配数ごとに更新します。送信待ちの予約、取消要求、完了通知の追跡はエンジンが処理します。手動注文、他のストラテジー、このセット以外の注文は取り消しません。

既存の全注文の取消・完了を確認してからコールバックを呼ぶため、取消中に約定があっても最新ポジションで数量を計算できます。送信承認だけでは約定とみなしません。取消拒否・結果不明・未確認の注文は予約を保持し、自動再送しません。ライブでは未約定一覧から消えただけでは完了とみなしません。未確認の場合は照合してから再開してください。未約定一覧に一度も現れずに全約定・失効・送信拒否が確定した注文にも対応します。

context.Positionsはcontext.TradingPositionsと同じ純ポジションを返す簡潔な名前です。従来の名前も使用できます。ライブの純ポジションには手動や他のストラテジーの取引が含まれる場合があります。数量取得のために研究用Portfolio会計を要求しません。

段数、価格間隔、数量、更新頻度、在庫上限は引き続きストラテジーパラメーターです。独自の注文ID辞書や取消監視ループは不要です。Studioを開き直して更新済みの組み込みサンプルを選択してください。利用者が編集したコピーは保持されます。

24気配コールバックの指値注文を標準で自動管理(M93)

RobotはOnQuote内の同一銘柄の指値注文を標準で自動管理します。OnStartでManageLimitOrdersを呼ぶ必要はなく、OnStart自体も省略できます。通常のcontext.SubmitLimitOrderは実際のローカル注文IDを返します。

最初の指値送信でその銘柄の管理を開始します。標準の更新間隔は同一銘柄の20回の気配です。前回の注文の取消・完了をすべて確認してから、最新の建玉で次の気配判断を実行します。未確認・結果不明・部分約定・取消拒否や一覧から消えた注文は予約を保持し、自動再送しません。無効な気配では更新間隔前でも既存セットの取消を開始します。最初の無効な気配からの指値送信は送信前に拒否します。

PassiveBidAskLadderのRefreshEveryQuotesパラメーターは引き続き設定できます。任意のpublic override int LimitOrderRefreshQuotes => RefreshEveryQuotes;で更新間隔を指定します。この上書きを忘れても標準の20回で自動管理が有効です。間隔は正の整数で、開始時に読み取ります。時間間隔ではなく気配の回数です。

指値を使う前の成行・逆指値のみのストラテジーには全気配を渡します。指値管理の開始後はOnEvent/OnTick/OnQuote全体が更新間隔・取消確認に従います。同じ判断処理内で成行も使う場合、その判断も同じ頻度になります。指標、バー・取引・注文ライフサイクルの処理は継続します。手動注文、他インスタンス、OnStart・バー・取引・ライフサイクルからの注文はこの気配セットの対象外です。

独立した永続的な指値や別銘柄の指値を気配処理から管理する上級者向けのコードは、public override bool AutomaticallyManageLimitOrders => false;で明示的に通常の注文管理を選べます。既存のRobotストラテジーで同一銘柄の気配指値を使う場合も標準動作が変わるため、この方針を確認してください。自動管理中の別銘柄の指値は送信前に拒否します。

従来のManageLimitOrdersは銘柄別の任意設定として残り、同一銘柄の指値限定という従来の制約を維持します。RefreshLimitOrdersもそのまま利用できますが、同一銘柄で直接指値と混在させることはできません。Studioを開き直し、更新済みの組み込みサンプルを選んでください。保存済みパラメーター名と編集済みコピーは保持されます。

25CFDチャート・ラダー建玉・履歴損益(M94)

IBKR株式CFDの履歴は、ブローカーが返すUnderConIdを使って同一通貨の原株を確認し、その株式の時間帯で読み込みます。チャートには原株のデータであることを明記します。注文は選択したCFDのままです。市場データの利用権限は引き続き必要です。

PassiveBidAskLadderの標準値はRefreshEveryQuotes=1、TickSize=0です。0はcontext.PriceTickSize(Symbol)で設定済みの商品価格刻みを使います。価格刻みが不明な場合はTickSizeを指定してください。正の値は独自の丸め・段間隔を維持します。保存済みの値は変更されないため、新しい標準動作を使う場合は1と0を設定してください。

既存のネット建玉が同方向の内側の段を占有します。2段・各1000の場合、1000の買い建玉なら買い2段目と売り1・2段目だけを提示します。2000の買い建玉なら買い注文を追加しません。500の部分約定なら買い1段目の残量は500です。売りも対称で、建玉の縮小で枠が空きます。MaximumInventoryも適用します。口座のネット建玉には手動や他ストラテジーの建玉も含まれます。

サンプルはエンジンのLimitOrderRefreshOnlyOnChange設定を使い、価格・建玉・注文状態が同じ間は取消を繰り返しません。更新時は既存の管理対象注文の取消・完了確認を待ち、最新の気配と建玉で再計算します。結果不明の注文は予約を維持し、手動注文や他インスタンスには触れません。RefreshEveryQuotesは秒数ではなく気配回数です。一般のRobotでは時間など他の条件を使う場合があるため、この設定の標準はfalseです。

約定履歴にPnLとCurrency列を追加しました。Saxoが返す口座通貨の実現損益をそのまま表示し、未提供値は空欄にします。価格からの推計や追加の手数料調整は行いません。更新後はStudioを開き直して最新の組み込みサンプルを選んでください。編集済みソース・保存済み設定・実行中ストラテジーは自動変更しません。

26指値更新・建玉明細(M95)

PassiveBidAskLadderは変更対応ホストで注文IDを維持し、変更が必要な価格・数量だけを更新します。変更確認まで次の更新を待ち、拒否・結果不明の変更を自動再送しません。手動注文や他ストラテジーの注文は対象外です。変更非対応時は取消確認後に再設定します。部分約定の残量を再計算し、約定数量が不明な場合は元の総数量を維持する価格変更だけを許可します。数量変更には取消確認が必要です。組み込みサンプルを選び直してください。

NormalizeLimitPriceはブローカーの価格帯別・指値別の刻みを適用します。TickSize=0は各価格帯の有効な刻みで段を作成し、正のTickSizeも最後にブローカー規則に従って買いを切り下げ・売りを切り上げます。

建玉画面はブローカーが返す個別建玉を約定時刻順に表示します。ID・数量・建値を保持し、合計が現在のネット建玉と一致する場合だけ明細として表示します。IBKRなど個別建玉を提供しない接続ではネット建玉と明示します。決済・目標数量変更はNet positions and actionsから従来のネット建玉単位で確認してください。

Saxoの確認済み全約定で過去の注文価格が取得できない場合は、不明値のまま実際の約定情報を保持します。元の注文内容で補完せず、他の項目の矛盾は引き続き検出します。部分約定や未約定注文には適用しません。履歴のSide列をEntry side(建玉方向)に変更し、PnLは最も近い整数(ちょうど半分はゼロから遠い側)・桁区切りカンマで表示します。保存値と並べ替えは元の小数値を保持します。

建玉の縮小・反転で同方向の注文枠が増える場合は、その方向だけ取消確認を待って再計算します。未確認の数量削減と新規注文が重なることを防ぎ、反対側の既存注文は維持します。

27約定別表示と接続中の復旧(M96)

IBKRの建玉画面では取得可能な約定を時刻順に表示し、反対売買による減少をFIFOで割り当てます。約定訂正は表示用の最新リビジョンを使い、生の記録は変更しません。同時刻は約定ID順です。ブローカーの税務上の個別ロットを示すものではありません。Gateway/TWSの履歴範囲外の残高はUnattributed balanceとして日時・価格を補完せず表示します。ネット建玉によるリスク管理と決済操作は従来どおりです。

IBKRで新たな口座エクスポージャーが出現した場合、対応契約の正確なIDを読み取り専用で解決してカタログに追加し、一度だけ再取得します。ストラテジーの使用銘柄は自動追加しません。未対応契約や再取得失敗では取引を停止します。

接続中に障害が発生してもOrdersから最後に確認済みの注文IDを指定して取消できます。口座・接続・注文を再確認し、手動で選択した注文だけが対象です。結果不明の変更記録は保持し、結果不明の取消は重複送信しません。新規注文と変更には先に口座照合が必要です。

Saxoの各新規・変更操作に固有の安定したx-request-idを付け、15秒以内の意図的な価格往復が重複検出される問題を防ぎます。新規・変更に対するHTTP 409は拒否として記録します。保存済みの同種Unknown記録も明示的な口座照合で元の記録を保持したまま更新できます。取消や通信結果不明には適用しません。照合後にOrders・Journalを確認してストラテジーを明示的に再開してください。更新による注文送信や実行中アプリの終了は行いません。

28個別建玉の決済と損益(M97、Saxoは下記M98で更新)

Positionsの個別行を右クリックしClose positionを選ぶと、その行の残数量だけを反対売買する確認画面が開きます。ネット買い100のうち残数量60の行なら売り60、目標残高40です。税務ロットの指定ではなく、実際のロット割当はブローカーに従います。ネットと反対方向の行やネット数量を超える行はこの操作では決済できません。送信前に口座・行・残数量・約定履歴を再確認し、変化があれば再確認を要求します。未確定注文や同方向の未約定手動決済がある場合は重複送信しません。

PnLとCurrency列を追加しました。個別行の推定損益はブローカーの時価、約定価格、符号付き残数量、契約倍率から銘柄通貨で計算し、手数料等を含みません。ネット行はブローカー報告損益です。価格や通貨が不明な場合は空欄です。表示のみ整数に四捨五入し、桁区切りはカンマです。

同じシンボルでも異なる商品種別を追加する際は、CDI_CfdOnStockのような重複しないストラテジー用エイリアスを追加前に提案します。先物は限月も含みます。既存マッピングとブローカーシンボルは変更しません。コードやパラメーターでは表示されたエイリアスを使用してください。更新後はStudioを開き直してください。

29Saxo個別ID決済・気配表示・注文照合(M98)

Saxoの個別行でClose positionを選ぶと、ブローカーのPositionIdを指定した関連成行注文で決済します。反対方向の両建てやネット残高ゼロも対象とし、確認画面に決済後のネット数量を表示します。片側だけの決済はネットリスクを増やす場合があります。送信前に個別建玉と口座のネッティング設定を再取得します。日末ネッティングと対応するForceOpen建玉が対象です。ロック・関連注文・非対応設定がある場合は停止し、ネット注文への置換や他注文の取消は行いません。IBKRの約定別行は従来どおり残数量によるネット縮小です。

DOMとティックChartは口座照合と独立した表示経路を使います。IBKRは気配コールバックを保存し、Saxoはブローカーの制限に従い約1秒間隔で取得します。市場ウィンドウは最大毎秒4回更新し、同一ブローカー時刻の価格変化も受信時刻順に表示します。鮮度判定は元の観測時刻を維持します。過去足の更新周期と取引の照合・リスク判定は別です。

IBKRの取消Acknowledgedは正確な完了注文の証拠から照合できます。通常注文の変更では不要なDeltaNeutralOrderTypeを空にし、報告された10363の非ASCII検証エラーは拒否として扱います。該当する保存済みUnknownも元の証拠を残して照合できます。Saxoの変更HTTP 404は明示的なOrderNotFound拒否、または同じ注文の確定終了証拠がなければUnknownを維持します。注文が一覧にないだけでは結果を確定せず、自動再送しません。

Studioを開き直し、Reconcile accountで対象注文を照合してください。検証はオフラインの模擬応答で行い、実口座の注文は操作していません。詳細は[M98ガイド](POSITION_ID_AND_QUOTES_M98.md)を参照してください。

30ストリーミング気配と建玉更新(M99)

SaxoのDOMとティックChartはInfoPriceのプッシュ配信を利用します。要求間隔は100ミリ秒ですが、実際の配信間隔はSaxoの契約・権限によって決まります。IBKRソケットとDatabentoは従来からプッシュ配信です。画面は最大毎秒10回更新します。過去足と口座・注文照合の周期は別です。M98のSaxo表示用ポーリングを置き換えます。

PositionsのPnLは新鮮な気配に追従します。買建玉はBid、売建玉はAskで評価し、残数量と契約倍率を用いて商品通貨で表示します。手数料・金利を含まない推計値で、整数に丸めます。計算根拠はホバーで確認できます。古い・不正な気配ではブローカー由来の値に戻します。選択行と建玉数量は維持します。

既に口座カタログへ登録された建玉は、ストラテジー入力へ追加せずClose positionを実行できます。口座・数量・権限・市場データ・未確定要求の確認は継続します。稼働中ラダーは自分の注文の終了証拠を引き続き確認し、確定約定・取消で予約を解除します。建玉がゼロへ戻った後の気配で再提示できます。停止・異常終了したストラテジーは明示的な再起動が必要です。詳細とCDIの証拠の制約は[M99ガイド](STREAMING_POSITIONS_M99.md)を参照してください。

31カタログ起動と注文要求の復旧(M100)

カタログのメタデータ索引を保存し、次回起動時は変更のない区画の情報を再利用します。ティック本体は必要になるまで読み込みません。取込・メタデータ編集・アンロードや復元で索引を無効化します。探索と保持期限の管理はバックグラウンドで進め、ResultsやExecutionなど関係のないページは利用できます。データに依存するページは探索完了を待ち、実際の利用時には引き続きファイルを検証します。

Prepared・Acknowledged・Unknownの要求は、共通の自動照合処理でブローカーの確定証拠を確認します。受付応答だけで取消完了や約定を断定しません。注文を再送したり、ストラテジーを自動再起動したりすることはありません。ユーザー操作はバックグラウンドの読取より優先します。IBKRの要求IDがない応答は、前の応答の終了を確認してから次の読取を開始し、遅延応答の混在と意図しない切断を防ぎます。証拠の矛盾やジャーナル保存失敗は引き続き表示します。詳細は[M100ガイド](CATALOGUE_RECOVERY_M100.md)を参照してください。

32銘柄ごとの価格正規化(M118)

Symbol.NormalizePrice(price, OrderSide.Buy) は指値を切り下げ、OrderSide.Sell は切り上げます。省略可能な levelsAway(0〜10000)で、有効な刻みをたどって外側へ進めます。ライブでは価格帯別・指値専用の刻み、リプレイでは設定済みの固定刻みを使用します。注文は送信しません。戻り値が正の場合だけ注文に使用してください。刻みの情報がない場合はエラーになります。ストップ注文用の正規化ではありません。既存の Symbol.NormalizeLimitPrice は引き続き利用できます。複数銘柄や文字列の Symbol パラメーターがある場合は Symbols.GetSymbol(alias).NormalizePrice(...) を使用します。

33保存設定を維持する SymbolName(M119)

PassiveBidAskLadder の C# 文字列プロパティを SymbolName に変更しました。[Parameter("Symbol", Key = "Symbol", ...)] により保存キー・表示名・既定値は従来のまま維持されます。保存済みパラメーターや最適化設定は Symbol キーを引き続き使います。SymbolNameOverride => SymbolName により、起動時やタイマー処理でも Symbol.TickSize、Symbol.TimeZone、Symbol.NormalizePrice は指定銘柄を参照します。選択されていない銘柄へのフォールバックはありません。購読や注文の送信先は変更しません。既存ソースは保存されるため、新しい組み込みサンプルを選択・検証して利用してください。

34組み込みサンプルの API 表記 (M120)

組み込みの単一銘柄サンプルは文字列パラメーターを SymbolName に統一し、Key = "Symbol" で保存キーを維持します。SymbolNameOverride により Symbol.TickSize、Symbol.TimeZone、Symbol.ToLocalTime(...)、Symbol.NormalizePrice(...) を直接利用できます。MultiSymbolTrend は SymbolName と OtherSymbol を使い、Symbol は各コールバックの銘柄を参照します。空のテンプレートは銘柄パラメーターを持ちません。MultiTimeZoneSessionTrend の AsiaTimeZone / AmericaTimeZone は従来どおり明示的なセッション設定です。保存済みユーザーソースは書き換えません。

35Last(offset) による過去の観測値

context.Bars.Open.Last(10) は最新から 10 個前のバー始値、context.Quotes.Bid.Last(8) は 8 個前の気配値を返します。Last(0) は現在のコールバックに渡される値を含む最新値、Last(1) はその直前です。offset は分・秒ではなく観測数です。履歴は銘柄とストラテジーの実行ごとに分離され、バックテストとライブ実行で利用できます。

C# · QR strategy API
public override void OnBarOpened(ReplayContext context, BarOpen bar)
{
    if (context.Bars.Open.TryLast(10, out decimal openTenBarsAgo))
        Print($"Current open={bar.Open}, ten openings ago={openTenBarsAgo}");
}

public override void OnQuote(ReplayContext context, Quote quote)
{
    if (context.Quotes.Bid.Count > 8)
    {
        decimal bidEightQuotesAgo = context.Quotes.Bid.Last(8);
        Print($"Current bid={quote.Bid}, eight quotes ago={bidEightQuotesAgo}");
    }
}

各系列は最大 4,096 件を保持します。開始直後は Count または TryLast(offset, out value) で件数を確認してください。Last は負数または取得できない offset に対して例外を返します。TryLast は履歴不足なら false、負数なら例外です。欠損値の補間・未来データの参照は行いません。実行・再起動・コードの自動切替時には履歴が空から始まります。過去データの自動ダウンロードや、インジケーター専用のウォームアップ履歴の取り込みは行いません。

context.Quotes は Bid、Ask、nullable の BidSize / AskSize、UTC の Time を提供します。context.Bars はバー開始時の Open と Time を提供します。確定バーは別系列の context.Bars.Closed.Open/High/Low/Close/Volume/Time を使います。確定系列の index は揃っており、未確定バーの最終 OHLCV は公開しません。Closed.Time は確定値が利用可能になった時刻です。ネイティブのバーコールバックは元のバー履歴、Robot が生成したバーコールバックはその時間足の履歴を使います。気配値履歴は両コールバックから参照できます。

通常は現在のイベントの銘柄を参照します。別の選択済み銘柄は context.GetQuotes("GOOG") / context.GetBars("GOOG") で指定できます。開始時に複数銘柄がある場合は明示指定が必要です。従来の bar.Open、quote.Bid、quote.Ask は decimal のままで、既存の計算とインジケーター呼び出しを維持します。履歴は更新されるビューなので、ストラテジーのコールバック内で参照してください。

気配値履歴のウォームアップと実行時エラー

TryLast(offset, out value) の戻り値は bool です。TryLast(offset) だけのオーバーロードはありません。Last(0) は現在の気配値を含むため、Last(1500) には対象銘柄の気配値が1,501件必要です。起動ごとに履歴は空から始まり、チャートの履歴はコピーされません。両方の値がそろうまでは注文処理の前で return します。

C# · QR strategy API
if (!context.Quotes.Bid.TryLast(1500, out var referenceBid)
    || !context.Quotes.Ask.TryLast(1500, out var referenceAsk))
    return;
var reference = side == OrderSide.Buy ? referenceBid : referenceAsk;

新しく検証したソースの実行時エラーには、例外の種類、メッセージ、コールバック、ソースファイル名と行番号が表示されます。古い検証済みアセンブリに行情報がない場合は再検証してください。機密情報はマスクされ、注文が自動で再送されることはありません。

36JPX寄付きオークションの履歴リプレイ(M174)

context.SupportsJpxAuctionReplay は、選択した全銘柄が明示的な JpxAuction データを使用する履歴リプレイの場合に true です。現在のPaper/Live接続では利用できません。通常の気配・ローソク足・最初の約定から寄付き約定を推測しません。

OnJpxAuctionSession、OnJpxMarket、OnReplayTimer をオーバーライドします。セッション参照には日付別の未調整前日終値、呼値、対象銘柄の根拠を渡します。市場メッセージには状態、空売り規制、識別済み寄付き約定、最大10段の板を保持します。同一メッセージの約定判定は更新前の板を用い、その後に板更新を適用します。

OnStart で ConfigureJpxAuctionReplay(symbol, options) を設定します。SubmitOpeningAuctionLimitOrder(side, symbol, quantity, price, expiresAt) は寄付き専用の研究用指値です。有効期限は排他的で、最初の識別済み寄付き約定後に未約定注文を取り消します。決済は既存建玉を減らすGTC指値・成行に限定します。ScheduleReplayTimer(symbol, due, key) はデータ範囲を超えて時計を進めません。銘柄ごとの CoverageThrough により、他銘柄の長いデータを使って終了済み銘柄の決済を作ることを防ぎます。

.jpx.csv の列は timestamp,jpxKind,symbol,payload、種類は session と market です。payloadは対応するAPI型のJSON、時刻はUTCオフセット付きです。参照情報・状態・板・寄付き識別を保持した元データが必要です。不正な行を読み飛ばしてメッセージの連続性を壊すことはせず、インポートを失敗させます。

板数量によるキュー順位は推定です。貸株可否、個別注文の順位、仮想注文による寄付き価格への影響は証明しません。未解消建玉を最終時刻で強制決済しません。QR Studio標準の評価損益・ドローダウンは標準会計の時価評価であり、元シミュレーターの板を使った清算価値や評価不能件数とは異なります。約定結果と決済済み損益を区別して確認してください。

37同一銘柄の気配・約定データ(M186)

単一銘柄の戦略では、具体的な戦略クラスに次を宣言できます。

C# · QR strategy API
[SingleSymbolData(MarketDataKinds.Quote | MarketDataKinds.Trade,
                  MarketDataKinds.Quote, "SymbolName")]

引数は、許可する市場データ種別、必須の種別、銘柄を指定する Text パラメーターの保存キーです。この例は Quote を必須とし、同一銘柄の Trade を任意で追加できます。両方を必須にする場合は第2引数も MarketDataKinds.Quote | MarketDataKinds.Trade にします。この属性は継承されません。宣言のない戦略の複数銘柄対応は従来どおりです。

Backtest・Optimize・Research とデータ選択画面で、異なる銘柄の混在、必須種別の不足、非対応種別、銘柄メタデータの矛盾、SymbolName やその探索候補とデータ銘柄の不一致を拒否します。同一銘柄・同一種別の重複しない日別ファイルは組み合わせられます。実際の実行期間にも必須データが必要です。刻み値が未設定のファイルには、他の選択ファイルで一意に定義された値を使用できます。矛盾する値は拒否し、不明な値を推測しません。

同一銘柄のQuote・TradeはUTC時系列順で統合し、両方のコールバックを配信します。指値の約定ソースにはTradeを選択します。M204以降の Market orders use fresh quotes を有効にすると、成行は有効なAskで買い、Bidで売り、各側の数量・価格鮮度・セッション状態を検証します。受動指値は後続のTradeで約定を判定します。この設定を使わない場合は、選択した執行フィードを全注文種別に使用します。データ欠落やセッション終端の架空約定は作りません。Tradeデータだけではキュー順位や全板を証明できません。

M191以降のResultsのTrade HistoryはFIFOで対応付けた往復取引です。Fill time/priceは建て、Close time/priceは対応する決済を示します。部分決済は複数行になる場合があり、Realized P&Lは各対応数量の手数料前損益です。生の約定記録も保持します。未決済数量に架空の決済を付けません。DDは記録済みの連続ポジションのMAEで、FIFOロットごとの損失ではありません。保存はUTC、表示は選択したタイムゾーンです。

38ライブ気配と注文コマンドの時刻 (M208)

ライブ実行では、注文のブローカー応答を待つ間も、外部フィードのレコードを各戦略へ元の順序で通知します。戦略コールバックと送信直前の検証は直列で実行します。準備済みコマンドの順序、保守的な注文予約、価格の鮮度・認証・リスクの再検証を維持し、ブローカーへのコマンド送信は同時に1件だけです。結果が不明な場合は送信を停止し、再送しません。価格待ちになった時点で未送信の注文目標は失効させ、復帰時に再送しません。

管理型ラダーは、自身の注文変更が確認されるまでユーザーの OnQuote を保留することがあります。この待機はフィード通知の遅延とは別です。受信からコールバックまでの時間を短縮しても、ネットワークの往復時間や先行コマンドの待ち時間は残ります。タイミングログは同じコマンドID同士で比較してください。

Quote.ReceivedUtc は、そのレコードの最終バイトを含むフィード読み取りが完了した時点のローカル UTC です。解析や戦略への通知より前に記録します。ProviderEventUtc、ProviderReceivedUtc、ProviderSentUtc は Databento の ts_event、ts_recv、ts_out をそれぞれ公開します(DateTimeOffset の精度は100 ns)。既存の Quote.Timestamp の意味は変わりません。Databento では ts_recv です。

StrategyOrderUpdate.Timing の SendStartedUtc は検証と送信待ちの後、トランスポート書き込み直前の時刻、SendCompletedUtc は書き込みの正常完了時刻、ResponseReceivedUtc は対応する WebSocket メッセージ全体の受信読み取り完了時刻です。CommandId で個別のコマンドと対応させます。OS・NICのパケット時刻や取引所の約定時刻ではありません。応答受信が書き込み処理の完了より早い場合もあります。

時刻はすべて nullable です。過去データのリプレイ、未対応のコネクター、記録できなかった段階では空のままです。照合時刻を応答受信時刻として代用しません。遅れて届いた正確な応答による更新は注文の再送を行わず、重複通知でも元の受信時刻を変更しません。指値目標の提出だけでは実際の送信を意味しないため、注文更新の時刻を参照してください。プロバイダーとPCの時刻差の比較には時計同期が必要です。