mirror of
https://github.com/DevExpress/netcore-winforms-demos.git
synced 2025-12-22 17:39:24 +00:00
296 lines
16 KiB
C#
296 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Windows.Forms;
|
|
using DevExpress.Utils;
|
|
using DevExpress.Utils.Drawing;
|
|
using DevExpress.Utils.Svg;
|
|
using DevExpress.XtraBars;
|
|
using DevExpress.XtraCharts;
|
|
using DevExpress.XtraEditors.Controls;
|
|
|
|
namespace DevExpress.StockMarketTrader {
|
|
public partial class StockChartUC : UserControl {
|
|
const string PriceSeriesName = "Price";
|
|
const string VolumeSeriesName = "Volume";
|
|
const int MinCandleCount = 20;
|
|
|
|
readonly List<PeriodItem> periods = new List<PeriodItem>() { new PeriodItem("1 Week", 5), new PeriodItem("2 Week", 10), new PeriodItem("1 Month", 20) };
|
|
bool isSelection = false;
|
|
bool isDrawing = false;
|
|
int daysCount = 105;
|
|
FinancialIndicator draggingIndicator;
|
|
ConstantLine trendlineBorder;
|
|
|
|
XYDiagram Diagram { get { return (XYDiagram)stockChart.Diagram; } }
|
|
Series PriceSeries { get { return stockChart.Series[PriceSeriesName]; } }
|
|
FinancialSeriesViewBase PriceSeriesView { get { return (FinancialSeriesViewBase)PriceSeries.View; } }
|
|
SideBySideBarSeriesView VolumeSeriesView { get { return (SideBySideBarSeriesView)stockChart.Series[VolumeSeriesName].View; } }
|
|
|
|
public StockChartUC() {
|
|
InitializeComponent();
|
|
InitializeAdvancedIndicators();
|
|
barStaticItemAdvancedIndicators.LeftIndent = 11;
|
|
barStaticItemPeriod.LeftIndent = 11;
|
|
this.stockChart.LookAndFeel.StyleChanged += LookAndFeel_StyleChanged;
|
|
LookAndFeel_StyleChanged(null, null);
|
|
}
|
|
void LookAndFeel_StyleChanged(object sender, EventArgs e) {
|
|
XYDiagram xYDiagram = stockChart.Diagram as XYDiagram;
|
|
CustomAxisLabel customAxisLabel = xYDiagram.AxisY.CustomLabels[0];
|
|
customAxisLabel.BackColor = Skins.CommonSkins.GetSkin(stockChart.LookAndFeel).SvgPalettes[ObjectState.Normal].GetColor("Gray");
|
|
customAxisLabel.TextColor = Skins.CommonSkins.GetSkin(stockChart.LookAndFeel).SvgPalettes[ObjectState.Normal].GetColor("White");
|
|
}
|
|
void InitializeAdvancedIndicators() {
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new LinearRegressionItem());
|
|
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new SimpleMovingAverageItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new ExponentialMovingAverageItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new TripleExponentialMovingAverageItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new TriangularMovingAverageItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new WeightedMovingAverageItem());
|
|
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new MedianPriceItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new TypicalPriceItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new WeightedCloseItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new AverageTrueRangeItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new CommodityChannelIndexItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new DetrendedPriceOscillatorItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new MassIndexItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new MovingAverageConvergenceDivergenceItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new RateOfChangeItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new RelativeStrengthIndexItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new StandardDeviationItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new ChaikinsVolatilityItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items.Add(new WilliamsRItem());
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.CustomDisplayText += Empty_CustomDisplayText;
|
|
}
|
|
void StockChartUC_Load(object sender, EventArgs e) {
|
|
if(StockMarketView.defaultViewModel == null)
|
|
return;
|
|
|
|
stockBarCheckItem.ImageOptions.SvgImage = SvgResources.GetSvgImage("Stock");
|
|
candleStickBarCheckItem.ImageOptions.SvgImage = SvgResources.GetSvgImage("Candles");
|
|
volumesBarCheckItem.ImageOptions.SvgImage = SvgResources.GetSvgImage("Bars");
|
|
barCheckItem3.ImageOptions.SvgImage = SvgResources.GetSvgImage("6m");
|
|
barCheckItem4.ImageOptions.SvgImage = SvgResources.GetSvgImage("1y");
|
|
barCheckItem5.ImageOptions.SvgImage = SvgResources.GetSvgImage("1-5y");
|
|
barCheckItem6.ImageOptions.SvgImage = SvgResources.GetSvgImage("2y");
|
|
barCheckItem7.ImageOptions.SvgImage = SvgResources.GetSvgImage("4y");
|
|
barCheckItemRemoveIndicator.ImageOptions.SvgImage = SvgResources.GetSvgImage("Remove");
|
|
barCheckItemTrendLine.ImageOptions.SvgImage = SvgResources.GetSvgImage("TrendLine");
|
|
barCheckItemFibonacciArcs.ImageOptions.SvgImage = SvgResources.GetSvgImage("FibonacciArcs");
|
|
barCheckItemFibonacciFans.ImageOptions.SvgImage = SvgResources.GetSvgImage("FibonacciFans");
|
|
barCheckItemFibonacciRetracement.ImageOptions.SvgImage = SvgResources.GetSvgImage("FibonacciRetracement");
|
|
//StockMarketView.defaultViewModel.model.InitServer();
|
|
OnPeriodChanged(barCheckItem7, null);
|
|
for(int i = 0; i < 6; i++)
|
|
repositoryItemCheckedComboBoxEditAdvancedIndicators.Items[i].CheckState = CheckState.Checked;
|
|
|
|
barEditItemAdvancedIndicators.EditValue = "Default";
|
|
}
|
|
void OnShowVolumeChartChanged(object sender, ItemClickEventArgs e) {
|
|
Diagram.Panes[0].Visibility = volumesBarCheckItem.Checked ? ChartElementVisibility.Visible : ChartElementVisibility.Hidden;
|
|
}
|
|
void OnPeriodChanged(object sender, ItemClickEventArgs e) {
|
|
BarCheckItem barCheckItem = sender as BarCheckItem;
|
|
if(barCheckItem != null && barCheckItem.Checked != false) {
|
|
daysCount = (int)barCheckItem.Tag;
|
|
repositoryItemComboBoxPeriod.Items.Clear();
|
|
foreach(PeriodItem periodItem in periods) {
|
|
int numberOfCandles = daysCount / periodItem.Ticks;
|
|
if(numberOfCandles >= MinCandleCount)
|
|
repositoryItemComboBoxPeriod.Items.Add(periodItem);
|
|
}
|
|
comboBoxBarEditItem.EditValue = repositoryItemComboBoxPeriod.Items[0];
|
|
OnTicksChanged(comboBoxBarEditItem, null);
|
|
}
|
|
}
|
|
void OnTicksChanged(object sender, EventArgs e) {
|
|
if(!ViewModel.RealTimeDataViewModel.IsReady) return;
|
|
BarEditItem barEditItem = sender as BarEditItem;
|
|
if(barEditItem != null && barEditItem.Name == "comboBoxBarEditItem") {
|
|
var vm = StockMarketView.defaultViewModel;
|
|
if(vm != null) {
|
|
int numberOfTicks = ((PeriodItem)barEditItem.EditValue).Ticks;
|
|
int newCandlesCount = daysCount / numberOfTicks;
|
|
if(vm.Ticks != numberOfTicks || vm.CandlesCount != newCandlesCount) {
|
|
vm.SetTicks(numberOfTicks);
|
|
vm.CandlesCount = newCandlesCount;
|
|
vm.OnCandlesCountChanged();
|
|
}
|
|
}
|
|
}
|
|
UpdateSeriesView();
|
|
}
|
|
void UpdateSeriesView() {
|
|
if(comboBoxBarEditItem.EditValue != null) {
|
|
switch(comboBoxBarEditItem.EditValue.ToString()) {
|
|
case "1 week":
|
|
Diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Week;
|
|
PriceSeriesView.LevelLineLength = 0.3;
|
|
VolumeSeriesView.BarWidth = 0.8D;
|
|
break;
|
|
case "2 week":
|
|
Diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Week;
|
|
PriceSeriesView.LevelLineLength = 0.6;
|
|
VolumeSeriesView.BarWidth = 1.6D;
|
|
break;
|
|
case "1 month":
|
|
Diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Month;
|
|
PriceSeriesView.LevelLineLength = 0.3;
|
|
VolumeSeriesView.BarWidth = 0.8D;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
void ChangeViewToCandleStick(object sender, ItemClickEventArgs e) {
|
|
stockChart.Series[PriceSeriesName].ChangeView(ViewType.CandleStick);
|
|
}
|
|
void ChangeViewToStock(object sender, ItemClickEventArgs e) {
|
|
stockChart.Series[PriceSeriesName].ChangeView(ViewType.Stock);
|
|
}
|
|
void stockChart_MouseMove(object sender, MouseEventArgs e) {
|
|
if(isDrawing) {
|
|
DiagramCoordinates coords = Diagram.PointToDiagram(e.Location);
|
|
draggingIndicator.Point2.Argument = coords.DateTimeArgument;
|
|
trendlineBorder.AxisValue = coords.DateTimeArgument;
|
|
}
|
|
}
|
|
void stockChart_MouseUp(object sender, MouseEventArgs e) {
|
|
if(!isSelection) {
|
|
draggingIndicator = null;
|
|
Diagram.AxisX.ConstantLines.Remove(trendlineBorder);
|
|
trendlineBorder = null;
|
|
isDrawing = false;
|
|
stockChart.Capture = false;
|
|
}
|
|
}
|
|
void stockChart_MouseDown(object sender, MouseEventArgs e) {
|
|
if(!isSelection) {
|
|
draggingIndicator = CreateDraggingIndicator();
|
|
if(draggingIndicator == null)
|
|
return;
|
|
|
|
DiagramCoordinates coords = Diagram.PointToDiagram(e.Location);
|
|
draggingIndicator.Point1.Argument = coords.DateTimeArgument;
|
|
draggingIndicator.Point1.ValueLevel = ValueLevel.Close;
|
|
draggingIndicator.Point2.Argument = coords.DateTimeArgument;
|
|
draggingIndicator.Point2.ValueLevel = ValueLevel.Close;
|
|
|
|
PriceSeriesView.Indicators.Add(draggingIndicator);
|
|
|
|
trendlineBorder = new ConstantLine();
|
|
trendlineBorder.AxisValue = coords.DateTimeArgument;
|
|
trendlineBorder.LineStyle.DashStyle = DashStyle.Dash;
|
|
trendlineBorder.LineStyle.Thickness = 1;
|
|
trendlineBorder.ShowInLegend = false;
|
|
Diagram.AxisX.ConstantLines.Add(trendlineBorder);
|
|
stockChart.Capture = true;
|
|
|
|
isDrawing = true;
|
|
stockChart.Capture = true;
|
|
}
|
|
}
|
|
void stockChart_ObjectHotTracked(object sender, HotTrackEventArgs e) {
|
|
if(!isSelection || !e.HitInfo.InIndicator)
|
|
e.Cancel = true;
|
|
else if(e.HitInfo.InIndicator) {
|
|
Indicator indicator = e.HitInfo.Indicator;
|
|
if(!(indicator is TrendLine) && !(indicator is FibonacciIndicator))
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
void stockChart_ObjectSelected(object sender, HotTrackEventArgs e) {
|
|
if(isSelection && e.HitInfo.InIndicator) {
|
|
Indicator indicator = e.HitInfo.Indicator;
|
|
if(indicator is TrendLine || indicator is FibonacciIndicator)
|
|
ChartHelper.RemoveIndicator(stockChart, PriceSeriesView, indicator);
|
|
}
|
|
e.Cancel = true;
|
|
}
|
|
void barEditItemMovingAverageIndicators_EditValueChanged(object sender, EventArgs e) {
|
|
foreach(CheckedListBoxItem item in repositoryItemCheckedComboBoxEditMovingAverages.Items) {
|
|
CheckedIndicatorItem movingAverage = (CheckedIndicatorItem)item.Value;
|
|
movingAverage.UpdateIndicator(stockChart, PriceSeriesView, item.CheckState == CheckState.Checked);
|
|
}
|
|
}
|
|
void barEditItemAdvancedIndicators_EditValueChanged(object sender, EventArgs e) {
|
|
foreach(CheckedListBoxItem item in repositoryItemCheckedComboBoxEditAdvancedIndicators.Items) {
|
|
CheckedIndicatorItem indicatorItem = (CheckedIndicatorItem)item.Value;
|
|
indicatorItem.UpdateIndicator(stockChart, PriceSeriesView, item.CheckState == CheckState.Checked);
|
|
}
|
|
}
|
|
void Empty_CustomDisplayText(object sender, CustomDisplayTextEventArgs e) {
|
|
if(string.IsNullOrEmpty(e.DisplayText))
|
|
e.DisplayText = "None";
|
|
}
|
|
void UpdateDrawingItemChecked(BarCheckItem item, BarCheckItem changedItem) {
|
|
if(item != changedItem)
|
|
item.Checked = false;
|
|
}
|
|
void UpdateDrawingItems(object sender, ItemClickEventArgs e) {
|
|
BarCheckItem item = (BarCheckItem)sender;
|
|
if(item.Checked) {
|
|
UpdateDrawingItemChecked(barCheckItemTrendLine, item);
|
|
UpdateDrawingItemChecked(barCheckItemFibonacciArcs, item);
|
|
UpdateDrawingItemChecked(barCheckItemFibonacciFans, item);
|
|
UpdateDrawingItemChecked(barCheckItemFibonacciRetracement, item);
|
|
UpdateDrawingItemChecked(barCheckItemRemoveIndicator, item);
|
|
}
|
|
stockChart.CrosshairEnabled = barCheckItemTrendLine.Checked || barCheckItemFibonacciArcs.Checked || barCheckItemFibonacciFans.Checked ||
|
|
barCheckItemFibonacciRetracement.Checked || barCheckItemRemoveIndicator.Checked ? DefaultBoolean.False : DefaultBoolean.True;
|
|
}
|
|
void barCheckItemRemoveIndicator_CheckedChanged(object sender, ItemClickEventArgs e) {
|
|
isSelection = ((BarCheckItem)sender).Checked;
|
|
UpdateDrawingItems(sender, e);
|
|
}
|
|
void stockChart_BoundDataChanged(object sender, EventArgs e) {
|
|
if(PriceSeries.Points.Count > 0) {
|
|
Diagram.AxisY.CustomLabels[0].AxisValue = PriceSeries.Points[PriceSeries.Points.Count - 1].Values[3];
|
|
Diagram.AxisY.CustomLabels[0].Name = String.Format("${0:F1}", Diagram.AxisY.CustomLabels[0].AxisValue);
|
|
}
|
|
}
|
|
FinancialIndicator CreateDraggingIndicator() {
|
|
if(barCheckItemTrendLine.Checked)
|
|
return new TrendLine("TrendLine");
|
|
if(barCheckItemFibonacciArcs.Checked)
|
|
return new FibonacciIndicator(FibonacciIndicatorKind.FibonacciArcs, "FibonacciArcs");
|
|
if(barCheckItemFibonacciFans.Checked)
|
|
return new FibonacciIndicator(FibonacciIndicatorKind.FibonacciFans, "FibonacciFans");
|
|
if(barCheckItemFibonacciRetracement.Checked)
|
|
return new FibonacciIndicator(FibonacciIndicatorKind.FibonacciRetracement, "FibonacciRetracement");
|
|
return null;
|
|
}
|
|
}
|
|
public class PeriodItem {
|
|
public PeriodItem(string caption, int ticks) {
|
|
Caption = caption;
|
|
Ticks = ticks;
|
|
}
|
|
public override string ToString() {
|
|
return Caption;
|
|
}
|
|
public string Caption {
|
|
get;
|
|
private set;
|
|
}
|
|
public int Ticks {
|
|
get;
|
|
private set;
|
|
}
|
|
}
|
|
//
|
|
public class SvgResources {
|
|
const string prefix = "DevExpress.StockMarketTrader.ImagesSvg.";
|
|
const string ext = ".svg";
|
|
readonly static Dictionary<string, SvgImage> svgImages = new Dictionary<string, SvgImage>(20);
|
|
public static SvgImage GetSvgImage(string imageName) {
|
|
SvgImage svgImage;
|
|
if(!svgImages.TryGetValue(imageName, out svgImage)) {
|
|
svgImage = ResourceImageHelper.CreateSvgImageFromResources(prefix + imageName + ext, typeof(SvgResources).Assembly);
|
|
svgImages.Add(imageName, svgImage);
|
|
}
|
|
return svgImage;
|
|
}
|
|
}
|
|
} |