StockSharpグラフィカルフレームワークを使用して取引ロボットを作成します。 パート2





StockSharpプラットフォームを使用して取引ロボットを作成することについて引き続き話します。 最初の資料では、プロジェクトの作成と取引システムの主要要素の描画を扱いました。 サイクルの最終資料では、取引戦略を直接実装します。



ポートフォリオパネルの作成



ツールバーと同様に、ログパネルを作成します。 これを行うには、別のUserControlをXAMLフォルダーに追加します。 PortfolioGridControlという名前を付けます。 PortfolioGrid要素を追加します。



<UserControl x:Class="ShellNew.XAML.PortfolioGridControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:xaml="http://schemas.stocksharp.com/xaml" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <xaml:PortfolioGrid x:Name="PortfolioGrid" /> </UserControl>
      
      





PortfolioGridControlコンストラクターで、新しいポートフォリオの出現のイベントと、Connectorでの新しいポジションの出現のイベントにサブスクライブする必要があります。



 public PortfolioGridControl() { InitializeComponent(); MainWindow.Instance.Connector.NewPortfolio += PortfolioGrid.Portfolios.Add; MainWindow.Instance.Connector.NewPosition += PortfolioGrid.Positions.Add; }
      
      





したがって、新しいポートフォリオを作成すると、ポートフォリオパネルに表示され、ポートフォリオパネルに新しいポジションが表示されると、更新されます。



MainWindowの中央部分で、作成されたPortfolioGridControlパネルを追加します。



 <dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs"> <!--  --> <dxlc:LayoutGroup Header="Securities"> <myxaml:SecurityGridControl x:Name="SecurityPanel" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Portfolios"> <myxaml:PortfolioGridControl x:Name="PortfolioGridControl" /> </dxlc:LayoutGroup> </dxlc:LayoutGroup>
      
      





実行して確認します:







ポートフォリオのタブがあります。



注文パネルの作成



S#.APIの注文バーには、注文の発行、注文の取り消し、再登録の機能があります。 ツールバーと同様に、オーダーパネルを作成し、別のUserControlをXAMLフォルダーに追加します。 OrderGridControlという名前を付けます。 OrderGrid要素を追加します。



 <UserControl x:Class="ShellNew.XAML.OrderGridControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:xaml="http://schemas.stocksharp.com/xaml" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <xaml:OrderGrid x:Name="OrderGrid" /> </UserControl>
      
      





OrderGridには、OrderRegistering登録イベント、OrderReRegistering再登録イベント、およびOrde​​rCancelingキャンセルイベントがあります。



ハンドラーを作成しましょう:



 <UserControl x:Class="ShellNew.XAML.OrderGridControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:xaml="http://schemas.stocksharp.com/xaml" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <xaml:OrderGrid x:Name="OrderGrid" OrderRegistering="OrderGrid_OnOrderRegistering" OrderReRegistering="OrderGrid_OnOrderReRegistering" OrderCanceling="OrderGrid_OnOrderCanceling" /> </UserControl>
      
      





要求登録イベントハンドラーで、商品、ポートフォリオ、市場データのデータソースを指定する必要があるOrderWindowウィンドウを作成します。 私たちの場合、それはすべてConnectorです。



その後、ShowModalメソッドでOrderWindowを呼び出します。 このウィンドウで[OK]ボタンが押された場合、RegisterOrderメソッドを使用して、コネクタを介して登録します。



 private void OrderGrid_OnOrderRegistering() { var newOrder = new OrderWindow { Title = "Order registering", Order = new Order(), SecurityProvider = MainWindow.Instance.Connector, MarketDataProvider = MainWindow.Instance.Connector, Portfolios = new PortfolioDataSource(MainWindow.Instance.Connector), }; if (newOrder.ShowModal(this)) MainWindow.Instance.Connector.RegisterOrder(newOrder.Order); }
      
      





イベント再登録イベントハンドラーでは、すべてを同じ方法で行います。 この場合にのみ、Orderオブジェクトがイベントに到達します。これは再登録が必要な注文です。 したがって、OrderWindowでは、 Order = order.ReRegisterClone(newVolume: order.Balance)



を指定して、OrderWindowウィンドウのフィールドに入力します。



その後、ShowModalメソッドでOrderWindowを呼び出します。 このウィンドウで[OK]ボタンがクリックされた場合、ReRegisterCloneメソッドを使用して、コネクタを介してアプリケーションを再登録します。 古いアプリケーションはキャンセルする必要があり、新しいアプリケーションは設定する必要があります。



 private void OrderGrid_OnOrderReRegistering(Order order) { var window = new OrderWindow { Title = "Order re-registering", SecurityProvider = MainWindow.Instance.Connector, MarketDataProvider = MainWindow.Instance.Connector, Portfolios = new PortfolioDataSource(MainWindow.Instance.Connector), Order = order.ReRegisterClone(newVolume: order.Balance) }; if (window.ShowModal(this)) MainWindow.Instance.Connector.ReRegisterOrder(order, window.Order); }
      
      





キャンセルイベントハンドラーでは、CancelOrderメソッドを呼び出して、キャンセルする必要がある注文を渡します。



 private void OrderGrid_OnOrderCanceling(Order order) { MainWindow.Instance.Connector.CancelOrder(order); }
      
      





OrderGridに注文を表示するには、OrderGridControlコンストラクターで、新しい注文が発生したときのイベントと登録エラーイベントをサブスクライブし、これらのイベントをOrderGridに転送する必要があります。



 public OrderGridControl() { InitializeComponent(); MainWindow.Instance.Connector.NewOrder += OrderGrid.Orders.Add; MainWindow.Instance.Connector.OrderRegisterFailed += OrderGrid.AddRegistrationFail; }
      
      





MainWindowの中央部分で、作成されたOrderGridControlパネルを追加します。



 <dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs"> <!--  --> <dxlc:LayoutGroup Header="Securities"> <myxaml:SecurityGridControl x:Name="SecurityPanel" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Portfolios"> <myxaml:PortfolioGridControl x:Name="PortfolioGridControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Orders"> <myxaml:OrderGridControl x:Name="OrderGridControl" /> </dxlc:LayoutGroup> </dxlc:LayoutGroup>
      
      





実行して確認します:







独自のトランザクションパネルの作成



ツールバーと同様に、独自のトランザクションのパネルを作成します。 XAMLフォルダーに、別のUserControlを追加します。 MyTradeGridControlという名前を付けます。 MyTradeGrid要素を追加します。



 <UserControl x:Class="ShellNew.XAML.MyTradeGridControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:xaml="http://schemas.stocksharp.com/xaml" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <xaml:MyTradeGrid x:Name="MyTradeGrid" /> </UserControl>
      
      





MyTradeGridControlのコンストラクターで、新しい独自のトランザクションの出現のイベントをサブスクライブし、それをMyTradeGridに転送する必要があります。



 public MyTradeGridControl() { InitializeComponent(); MainWindow.Instance.Connector.NewMyTrade += MyTradeGrid.Trades.Add; }
      
      





MainWindowの中央部分で、作成されたOrderGridControlパネルを追加します。



 <dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs"> <!--  --> <dxlc:LayoutGroup Header="Securities"> <myxaml:SecurityGridControl x:Name="SecurityPanel" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Portfolios"> <myxaml:PortfolioGridControl x:Name="PortfolioGridControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Orders"> <myxaml:OrderGridControl x:Name="OrderGridControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="MyTrades"> <myxaml:MyTradeGridControl x:Name="MyTradeGridControl" /> </dxlc:LayoutGroup> </dxlc:LayoutGroup>
      
      





実行して確認します:







戦略を持つパネルを作成する



これまでのすべてのパネルと同じ方法で戦略パネルを作成します。 XAMLフォルダーに、別のUserControlを追加します。 StrategyControlという名前を付けます。 LayoutControlを使用して、画面を2つの部分に分割します。 左側には、ローソク足チャートのあるタブと戦略統計のあるタブがあります。



 <dxlc:LayoutGroup Orientation="Vertical"> <dxlc:LayoutGroup View="Tabs" Name="StatistisAndChartLayoutGroup"> <dxlc:LayoutGroup Header="Chart"> <xaml:Chart x:Name="Chart" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Statistic"> <dxlc:LayoutItem VerticalAlignment="Stretch" dxlc:LayoutControl.AllowHorizontalSizing="True" > <xaml:StatisticParameterGrid x:Name="StatisticParameterGrid" MaxHeight="2000"/> </dxlc:LayoutItem> <dxlc:LayoutItem VerticalAlignment="Stretch" > <xaml:EquityCurveChart x:Name="EquityCurveChart" /> </dxlc:LayoutItem> </dxlc:LayoutGroup> </dxlc:LayoutGroup> </dxlc:LayoutGroup>
      
      





ここでは、StatisticParameterGridを使用して戦略統計を表示し、EquityCurveChartを使用して損益グラフを表示します。 StatisticParameterGridは、MaxHeight値を設定する必要があります。設定しないと、アプリケーションは起動しません。



右側では、PropertyGridExで戦略のプロパティを構成します。 戦略を開始および停止するためのボタンも配置されます。



 <dxlc:LayoutGroup View="Group" dxlc:LayoutControl.AllowHorizontalSizing="True" dxlc:DockLayoutControl.Dock="Right" Orientation="Vertical"> <dxlc:LayoutItem VerticalAlignment="Stretch"> <xaml:PropertyGridEx x:Name="PropertyGridEx" /> </dxlc:LayoutItem> <dxlc:LayoutItem VerticalAlignment="Stretch" Height="20"> <dx:SimpleButton x:Name="StartStrategyButton" Content="Start strategy" ToolTip="Start strategy" Click="StartStrategyButton_Click" /> </dxlc:LayoutItem> <dxlc:LayoutItem VerticalAlignment="Stretch" Height="20"> <dx:SimpleButton x:Name="StopStrategyButton" Content="Stop strategy" ToolTip="Stop strategy" Click="StopStrategyButton_Click" /> </dxlc:LayoutItem> </dxlc:LayoutGroup>
      
      





完全なコード:



 <UserControl x:Class="ShellNew.XAML.StrategyControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" xmlns:xaml="http://schemas.stocksharp.com/xaml" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" mc:Ignorable="d"> <dxlc:LayoutControl> <dxlc:LayoutGroup Orientation="Vertical"> <dxlc:LayoutGroup View="Tabs" Name="StatistisAndChartLayoutGroup"> <dxlc:LayoutGroup Header="Chart"> <xaml:Chart x:Name="Chart" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Statistic"> <dxlc:LayoutItem VerticalAlignment="Stretch" dxlc:LayoutControl.AllowHorizontalSizing="True" > <xaml:StatisticParameterGrid x:Name="StatisticParameterGrid" MaxHeight="2000"/> </dxlc:LayoutItem> <dxlc:LayoutItem VerticalAlignment="Stretch" > <xaml:EquityCurveChart x:Name="EquityCurveChart" /> </dxlc:LayoutItem> </dxlc:LayoutGroup> </dxlc:LayoutGroup> </dxlc:LayoutGroup> <dxlc:LayoutGroup View="Group" dxlc:LayoutControl.AllowHorizontalSizing="True" dxlc:DockLayoutControl.Dock="Right" Orientation="Vertical"> <dxlc:LayoutItem VerticalAlignment="Stretch"> <xaml:PropertyGridEx x:Name="PropertyGridEx" /> </dxlc:LayoutItem> <dxlc:LayoutItem VerticalAlignment="Stretch" Height="20"> <dx:SimpleButton x:Name="StartStrategyButton" Content="Start strategy" ToolTip="Start strategy" Click="StartStrategyButton_Click" /> </dxlc:LayoutItem> <dxlc:LayoutItem VerticalAlignment="Stretch" Height="20"> <dx:SimpleButton x:Name="StopStrategyButton" Content="Stop strategy" ToolTip="Stop strategy" Click="StopStrategyButton_Click" /> </dxlc:LayoutItem> </dxlc:LayoutGroup> </dxlc:LayoutControl> </UserControl>
      
      





StrategyControlコンストラクターで、ConnectorをPropertyGridExのデータソースとして設定し、ほぼすべてのコントロールで同様のアクションを実行しました。



 public StrategyControl() { InitializeComponent(); PropertyGridEx.SecurityProvider = MainWindow.Instance.Connector; PropertyGridEx.Portfolios = new PortfolioDataSource(MainWindow.Instance.Connector); }
      
      





何らかの形で戦略をコントロールに移す必要があります。 これを行うには、StrategyControlでBindStraregyメソッドを作成します。これにより、戦略が取得され、ローカル変数にリンクが保存され、PropertyGridExおよびStatisticParameterGridで戦略が設定されます。



SetChartメソッドを使用して、Chartローソク足のチャートを戦略に転送します;その後、GetChartメソッドを使用してChart戦略を取得できます。 また、戦略のコネクタを設定します。



 private Strategy _strategy; public void BindStraregy(Strategy strategy) { _strategy = strategy; PropertyGridEx.SelectedObject = strategy; StatisticParameterGrid.Parameters. AddRange(_strategy.StatisticManager.Parameters); _strategy.SetChart(Chart); _strategy.Connector = MainWindow.Instance.Connector; }
      
      





損益のスケジュールを使用する場合、戦略が開始および停止することを考慮する必要があります。おそらく数回、戦略を開始するたびに詩をクリアする必要があります。 このために、まずEquityCurveChartをクリアするResetEquityCurveChartメソッドを作成します。 その後、EquityCurveChartのグラフィック要素を作成する必要があります。それらは、線の名前、色、タイプを指定できます。



その後、戦略のPnL変更イベントをサブスクライブし、このイベントのハンドラーで、EquityCurveChartの損益グラフに新しい値を描画します。



 private void ResetEquityCurveChart() { EquityCurveChart.Clear(); var pnl = EquityCurveChart. CreateCurve("PNL", Colors.Green, ChartIndicatorDrawStyles.Area); var unrealizedPnL = EquityCurveChart. CreateCurve("unrealizedPnL", Colors.Black, ChartIndicatorDrawStyles.Line); var commissionCurve = EquityCurveChart .CreateCurve("commissionCurve", Colors.Red, ChartIndicatorDrawStyles.Line); _strategy.PnLChanged += () => { var data = new ChartDrawData(); data.Group(_strategy.CurrentTime) .Add(pnl, _strategy.PnL) .Add(unrealizedPnL, _strategy.PnLManager.UnrealizedPnL ?? 0) .Add(commissionCurve, _strategy.Commission ?? 0); EquityCurveChart.Draw(data); }; }
      
      





[スタート]ボタンをクリックするためのイベントハンドラーで、このメソッドを呼び出します。 また、戦略の状態をリセットして実行します。



 private void StartStrategyButton_Click(object sender, RoutedEventArgs e) { ResetEquityCurveChart(); _strategy.Reset(); _strategy.Start(); }
      
      





[停止]ボタンをクリックするためのイベントハンドラーで、戦略を停止します。

private void StopStrategyButton_Click(オブジェクト送信者、RoutedEventArgs e):



 { _strategy.Stop(); }
      
      





MainWindowの中央部分で、作成されたStrategyControlパネルを追加します。



 <dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs"> <!--  --> <dxlc:LayoutGroup Header="Securities"> <myxaml:SecurityGridControl x:Name="SecurityPanel" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Portfolios"> <myxaml:PortfolioGridControl x:Name="PortfolioGridControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="Orders"> <myxaml:OrderGridControl x:Name="OrderGridControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="MyTrades"> <myxaml:MyTradeGridControl x:Name="MyTradeGridControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="MarketDepth"> <myxaml:MarketDepthControl x:Name="MarketDepthControl" /> </dxlc:LayoutGroup> <dxlc:LayoutGroup Header="SimpleStrategyControl"> <myxaml:StrategyControl x:Name="SimpleStrategyControl" /> </dxlc:LayoutGroup> </dxlc:LayoutGroup>
      
      





戦略作成



たとえば、単純なローソク足戦略を作成することを検討してください。 彼女はろうそくが成長している場合(緑)に買い、ろうそくが減少している場合(赤)に売ります。



プロジェクトに別のフォルダーを作成しましょう-すべての戦略をそこに保存します。 このフォルダーで、新しいクラスを作成し、SimpleStrategyと呼びます。 すべてのS#戦略は、戦略戦略の基本クラスから継承する必要があります。



 public class SimpleStrategy : Strategy {}
      
      





戦略ではキャンドルを使用しているため、パブリックプロパティCandleSeriesを作成し、戦略のコンストラクターでデフォルト値に設定します。



 public class SimpleStrategy : Strategy { public CandleSeries Series { get; set; } public SimpleStrategy() { Series = new CandleSeries(typeof(TimeFrameCandle), new Security(), TimeSpan.FromSeconds(15)) { BuildCandlesMode = MarketDataBuildModes.Build }; } }
      
      





ここでは、CandleSeriesのローソク足が15秒間隔(TimeSpan.FromSeconds(15))でTimeFrameCandleになることを示しました。 CandleSeriesの場合、BuildCandlesModeローソク足作成モードを指定できます。 キャンドルを作成することを示しました(MarketDataBuildModes.Build)。 デフォルトでは、ティックから構築されますが、他のデータ型を指定できます。



CandleSeriesをパブリックプロパティにしたため、CandleSeriesは前の段落で説明したPropertyGridExからさらにカスタマイズできます。 すべての戦略には、オーバーライドできるメソッドがあります。OnStartedメソッドをオーバーライドする必要があります。 戦略を開始する前に呼び出され、開始状態を事前に設定できます。



 protected override void OnStarted() { _connector = (Connector)Connector; Series.Security = Security; _connector .WhenCandlesFinished(Series) .Do(ProcessCandle) .Apply(this); _connector.SubscribeCandles(Series); base.OnStarted(); }
      
      





ここで、CandleSeriesの場合、PropertyGridExで指定されたツールを定義します。 次に、完成したろうそくを処理するためのルールを作成します。 ルールでは、完成した各ろうそくを処理するメソッドを指定します-この場合、これはProcessCandleメソッドです。 後で説明します。 すべての設定が完了したら、SubscribeCandlesメソッドを使用して、コネクターのCandleSeriesのキャンドルの外観をサブスクライブします。 この場合、ProcessCandleメソッドには戦略のメインロジックが含まれています。



 private void ProcessCandle(Candle candle) { if (!IsRealTime(candle)) return; if (candle.OpenPrice < candle.ClosePrice && Position <= 0) { RegisterOrder(this.BuyAtMarket(Volume + Math.Abs(Position))); } else if (candle.OpenPrice > candle.ClosePrice && Position >= 0) { RegisterOrder(this.SellAtMarket(Volume + Math.Abs(Position))); } }
      
      





まず、ろうそくがリアルタイムで構築されているのか、歴史的なものであるのかを判断する必要があります。 キャンドルが歴史的なものである場合、無視します。 すべての戦略がこれを必要とするわけではありません。たとえば、メガネに基づく戦略はこれを必要としません。メガネは常にリアルタイムで進むためです。 ろうそくが「リアルタイム」であるか歴史的であるかを判断する普遍的な方法はありません。各戦略では、要件に応じてこの問題を個別に解決する必要があります。 この場合、ろうそくが閉じる時間とコネクター内の時間を単純に比較し、ろうそくが特定の遅延を超えない場合、ろうそくはリアルタイムの状態になります。



 private bool IsRealTime(Candle candle) { return (Connector.CurrentTime - candle.CloseTime).TotalSeconds < 10; }
      
      





次に、それがどのような種類のろうそくであるか、そして戦略の現在の位置は何かを見ます。 ローソクが成長している場合、ポジションが0に等しい場合、PropertyGridExで設定されたボリュームの成行注文でポジションを開きます。 ローソクが成長し、位置が0未満の場合、位置を「反転」します。



 if (candle.OpenPrice < candle.ClosePrice && Position <= 0) { RegisterOrder(this.BuyAtMarket(Volume + Math.Abs(Position))); }
      
      







ろうそくを弱めるために反対のことを行います。



 else if (candle.OpenPrice > candle.ClosePrice && Position >= 0) { RegisterOrder(this.SellAtMarket(Volume + Math.Abs(Position))); }
      
      





現時点では、戦略は機能する準備ができています。 前の段落でBindStraregyメソッドを使用して作成したSimpleStrategyControlに渡す必要があります。 MainWindowコンポーネントの初期化直後に、MainWindowコンストラクターでこれを行います。



 SimpleStrategyControl.BindStraregy(new SimpleStrategy());
      
      







実行して確認します:











戦略は機能し、取引が行われますが、これまでのところ、チャート上にろうそくや取引はありません。



戦略からチャートにろうそくと取引を追加する



SetChartメソッドを使用した戦略パネルに関する段落では、チャートキャンドルのチャートを戦略に裏切りました。 戦略のOnStartedメソッドでは、チャートが戦略に設定されているかどうかを確認し、設定されている場合はチャートを初期化し、新しい独自のトランザクションの出現とローソク足の変化のイベントにもサブスクライブします。



 protected override void OnStarted() { _connector = (Connector)Connector; if (this.GetChart() is Chart chart) { InitChart(chart); NewMyTrade += DrawMyTrade; _connector.CandleSeriesProcessing += CandleSeriesProcessing; } Series.Security = Security; _connector .WhenCandlesFinished(Series) .Do(ProcessCandle) .Apply(this); _connector.SubscribeCandles(Series); base.OnStarted(); }
      
      





InitChartチャートの初期化メソッド:



 private ChartCandleElement _chartCandleElement; private ChartTradeElement _tradesElem; private Chart _chart; private void InitChart(Chart chart) { _chart = chart; _chart.GuiSync(() => { _chart.ClearAreas(); var candlesArea = new ChartArea(); _chart.AddArea(candlesArea); _chartCandleElement = new ChartCandleElement(); _chart.AddElement(candlesArea, _chartCandleElement); _tradesElem = new ChartTradeElement { FullTitle = "Trade" }; _chart.AddElement(candlesArea, _tradesElem); }); }
      
      





ここで、ローカル変数にChartへのリンクを保存します。 スケジュールをクリアします。 また、ろうそくや取引のチャート要素を作成してチャートに転送します。 Construction _chart.GuiSync(()=> {...}); メインスレッドでスケジュールを初期化するために必要です。



CandleSeriesProcessingチャートを使用して、チャート上にキャンドルを描画します。



 private void CandleSeriesProcessing(CandleSeries candleSeries, Candle candle) { var data = new ChartDrawData(); data.Group(candle.OpenTime) .Add(_chartCandleElement, candle); _chart.Draw(data); }
      
      





ここでは、コネクタのCandleSeriesProcessingイベントからキャンドルを取得し、ChartDrawDataを作成してチャートに表示します。 時間データを示します。Group(candle.OpenTime)、ろうそくをチャートのろうそく要素に追加する必要があることを示します.Add(_chartCandleElement、candle);。 そして、グラフィックは新しいデータを描画する必要があることを示します。



トランザクションに対して同様のアクションを実行します。



 public void DrawMyTrade(MyTrade myTrade) { var data = new ChartDrawData(); data.Group(myTrade.Trade.Time) .Add(_tradesElem, myTrade); _chart.Draw(data); }
      
      





実行して確認します:







簡単な結論



複雑でプロフェッショナルな外観のアプリケーションを作成するために、多くの時間を費やす必要はありません。 数時間にわたって、直接取引とアルゴリズム取引を設定、表示する機能を備えた本格的なアプリケーションを作成しました。

あなた自身の取引プログラムを作成しようとすることを恐れないでください。 この記事がこの問題に慣れるのに役立つことを願っています。



著者 :イワン・ザルートキー



All Articles