交易品种搜索

大多数与美国股票交易所的连接器(例如 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.Stock, SecurityTypes.Future 等)
  • SecurityTypes — 用于高级搜索的工具类型数组
  • 货币 — 该工具的交易货币
  • ExpiryDate — 到期日(用于衍生品)
  • 行权价 — 期权的行权价
  • OptionType — 期权类型(适用于期权)
  • 名称 — 交易品种名称或其部分
  • — 交易品种类别

正在处理搜索结果

创建订阅后,您需要订阅事件以接收工具并发送请求:

// 交易品种接收事件处理器
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);
}

使用安全查找窗口

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 中的订阅机制提供了一种获取数据的统一方式,包括工具搜索。这允许对不同的连接器和数据类型使用相同的方法,从而显著简化了交易应用程序的开发。