金融商品の検索

米国株式取引所へのほとんどのコネクター(たとえば Interactive BrokersPolygonIO など)は、IConnector.Connect メソッドで接続を確立した後、利用可能なすべての金融商品をクライアントへ転送しません。これは、米国の取引所で取引される金融商品の数が非常に多いためであり、ブローカーサーバーやデータソースの負荷を軽減するために行われます。

金融商品検索の基本

S# で金融商品を検索するには、マーケットデータの受信と同様に、サブスクリプション機構を使用します。このアプローチにより、金融商品を含むすべての種類のデータに対して統一されたコードを使用できます。

金融商品検索用サブスクリプションの作成

金融商品を検索するには、Subscription クラスのインスタンスを、フィルタリングパラメーターを含む SecurityLookupMessage メッセージに基づいて作成する必要があります。

// 検索用のフィルターオブジェクトを作成します
var lookupMessage = new SecurityLookupMessage
{
	// 検索条件を設定します
	SecurityId = new SecurityId
	{
		// 金融商品コードで検索します("AAPL*" のようなマスクを使用できます)
		SecurityCode = "AAPL",
		// 任意で、ボードコードを指定できます
		BoardCode = "NASDAQ"
	},
	// 金融商品の種類を指定できます
	SecurityType = SecurityTypes.Stock,
	// トランザクション ID を設定します
	TransactionId = Connector.TransactionIdGenerator.GetNextId()
};

// 金融商品検索用のサブスクリプションを作成します
var subscription = new Subscription(lookupMessage);

使用可能なフィルタリングパラメーター

SecurityLookupMessage メッセージでは、次の検索条件を設定できます。

  • SecurityId — 金融商品識別子。次を含みます。
    • SecurityCode — 金融商品コード、または金融商品コードのマスク(たとえば "AAPL" または "MS*")
    • BoardCode — 取引所ボードコード(たとえば ExchangeBoard.Nasdaq
  • SecurityType — 金融商品の種類(SecurityTypes.StockSecurityTypes.Future など)
  • SecurityTypes — 高度な検索用の金融商品種類の配列
  • Currency — 金融商品の取引通貨
  • ExpiryDate — 有効期限(デリバティブ用)
  • Strike — 権利行使価格(オプション用)
  • OptionType — オプションの種類(オプション用)
  • Name — 金融商品名、またはその一部
  • Class — 金融商品クラス

検索結果の処理

サブスクリプションを作成した後、金融商品を受信するためのイベントを購読し、リクエストを送信する必要があります。

// 金融商品受信イベントのハンドラー
private void OnSecurityReceived(Subscription subscription, Security security)
{
	if (subscription.SubscriptionMessage is not SecurityLookupMessage)
		return;
		
	Console.WriteLine($"銘柄が見つかりました: {security.Id} - {security.Name}, 種類: {security.Type}");
	
	// ここで金融商品をコレクションに追加するか、その他の処理を実行できます
	Securities.Add(security);
}

// 検索完了イベントのハンドラー
private void OnSubscriptionFinished(Subscription subscription)
{
	if (subscription.SubscriptionMessage is not SecurityLookupMessage)
		return;
		
	Console.WriteLine($"検索が完了しました。見つかった銘柄数: {Securities.Count}");
}

// サブスクリプションエラーのハンドラー
private void OnSubscriptionFailed(Subscription subscription, Exception error, bool isSubscribe)
{
	if (subscription.SubscriptionMessage is not SecurityLookupMessage)
		return;
		
	Console.WriteLine($"銘柄検索エラー: {error.Message}");
}

// イベントを購読します
Connector.SecurityReceived += OnSecurityReceived;
Connector.SubscriptionFinished += OnSubscriptionFinished;
Connector.SubscriptionFailed += OnSubscriptionFailed;

// 金融商品検索リクエストを送信します
Connector.Subscribe(subscription);

金融商品検索の完全な例

以下は、金融商品を検索するメソッドの完全な例です。

public void FindSecurities(string searchCode, SecurityTypes? securityType = null)
{
	// 金融商品検索用のオブジェクトを作成します
	var lookupMessage = new SecurityLookupMessage
	{
		SecurityId = new SecurityId
		{
			SecurityCode = searchCode,
			// 特定のボードで検索する必要がある場合
			// BoardCode = ExchangeBoard.Nyse.Code,
		},
		SecurityType = securityType,
		TransactionId = Connector.TransactionIdGenerator.GetNextId()
	};
	
	// サブスクリプションを作成します
	var subscription = new Subscription(lookupMessage);
	
	// 検索結果用のコレクションをクリアします
	_searchResults.Clear();
	
	// 結果を蓄積するための一時コレクション
	var foundSecurities = new List<Security>();
	
	// 金融商品受信用のサブスクリプション
	void OnSecurityReceived(Subscription sub, Security security)
	{
		if (sub != subscription)
			return;
			
		// 見つかった金融商品をコレクションに追加します
		foundSecurities.Add(security);
		Console.WriteLine($"見つかりました: {security.Id}, {security.Name}");
	}
	
	// 検索完了用のサブスクリプション
	void OnSubscriptionFinished(Subscription sub)
	{
		if (sub != subscription)
			return;
			
		// 結果をメインコレクションにコピーします
		_searchResults.AddRange(foundSecurities);
		
		Console.WriteLine($"検索が完了しました。見つかった銘柄数: {foundSecurities.Count}");
		
		// イベントの購読を解除します
		Connector.SecurityReceived -= OnSecurityReceived;
		Connector.SubscriptionFinished -= OnSubscriptionFinished;
		Connector.SubscriptionFailed -= OnSubscriptionFailed;
	}
	
	// サブスクリプションエラーの処理
	void OnSubscriptionFailed(Subscription sub, Exception error, bool isSubscribe)
	{
		if (sub != subscription)
			return;
			
		Console.WriteLine($"銘柄検索エラー: {error.Message}");
		
		// イベントの購読を解除します
		Connector.SecurityReceived -= OnSecurityReceived;
		Connector.SubscriptionFinished -= OnSubscriptionFinished;
		Connector.SubscriptionFailed -= OnSubscriptionFailed;
	}
	
	// イベントを購読します
	Connector.SecurityReceived += OnSecurityReceived;
	Connector.SubscriptionFinished += OnSubscriptionFinished;
	Connector.SubscriptionFailed += OnSubscriptionFailed;
	
	// 検索リクエストを送信します
	Connector.Subscribe(subscription);
}

WPF アプリケーションでの使用例

グラフィカルアプリケーションでは、金融商品の検索はボタンクリックハンドラーから呼び出されることがよくあります。

private void FindButton_Click(object sender, RoutedEventArgs e)
{
	// テキストフィールドから検索条件を取得します
	var searchText = SearchTextBox.Text;
	
	if (string.IsNullOrWhiteSpace(searchText))
	{
		MessageBox.Show("Enter a search criterion");
		return;
	}
	
	// 検索サブスクリプションを作成して送信します
	var lookupMessage = new SecurityLookupMessage
	{
		SecurityId = new SecurityId { SecurityCode = searchText },
		// インターフェイスで種類が選択されている場合
		SecurityType = SecurityTypeComboBox.SelectedItem as SecurityTypes?
	};
	
	var subscription = new Subscription(lookupMessage);
	
	// ここで読み込みインジケーターを表示できます
	LoadingIndicator.Visibility = Visibility.Visible;
	
	// リクエストを送信します
	Connector.Subscribe(subscription);
}

SecurityLookupWindow の使用

StockSharp は、金融商品検索用の既製ダイアログ SecurityLookupWindow も提供します。

private void ShowSecurityLookupWindow_Click(object sender, RoutedEventArgs e)
{
	var lookupWindow = new SecurityLookupWindow
	{
		// すべての金融商品を検索できるようにするか指定します
		// (コネクターがこの機能をサポートしている場合)
		ShowAllOption = Connector.Adapter.IsSupportSecuritiesLookupAll(),
		
		// 初期検索条件を設定します
		CriteriaMessage = new SecurityLookupMessage
		{
			SecurityId = new SecurityId { SecurityCode = "AAPL" },
			SecurityType = SecurityTypes.Stock
		}
	};
	
	// モーダルダイアログとしてウィンドウを表示します
	if (lookupWindow.ShowModal(this))
	{
		// ユーザーが選択を確定した場合、リクエストを送信します
		Connector.Subscribe(new Subscription(lookupWindow.CriteriaMessage));
	}
}

まとめ

StockSharp のサブスクリプション機構は、金融商品検索を含め、データを取得するための統一された方法を提供します。これにより、異なるコネクターやデータ型を扱う場合にも同じアプローチを使用でき、取引アプリケーションの開発が大幅に簡素化されます。