using IndexFormula.Finance;
using IndexFormula.Finance.DataProvider;
using IndexFormula.Finance.Win;
using MuchInfo.Chart.Data.EnumTypes;
using MuchInfo.Chart.Data.Models;
using MuchInfo.Chart.Utilities.Enums;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
namespace MuchInfo.Chart.DataAdapter
{
public class DataService : IDataService
{
///
/// 使用公式计算图表数据
///
/// 源数据,需要计算的数据
/// 返回图表数据
public List Calculate(List source, List sourceCharts, Data.EnumTypes.CycleType cycleType, TimeSpan minutes)
{
var commonDataProvider = new CommonDataProvider(null);
commonDataProvider.LoadBinary(ConvertData(source));
commonDataProvider.DataCycle = ConvertCycle(cycleType, minutes);
foreach (var formulaModel in sourceCharts)
{
try
{
var formulaBase = FormulaBase.GetFormulaByName(formulaModel.FormulaName);
var formulaPackage = formulaBase.Run(commonDataProvider);
if (formulaPackage.Count > 0)
{
for (int i = 0; i < formulaPackage.Count - 1; i++)
{
var indicatorModel = formulaModel.IndicatorList.FirstOrDefault((model) => model.LineName == formulaPackage[i].Name);
if (indicatorModel == null) continue;
indicatorModel.CalculateDataPoints = ConvertDataPoint(formulaPackage[i].Data, commonDataProvider["DATE"]);
}
}
}
catch
{
//找到不公式跳过,不影响下一个
}
}
return sourceCharts;
}
///
/// 使用公式计算图表数据
///
/// 源数据,需要计算的数据
/// 公式
/// 周期类型
/// 自定义周期分钟数
/// 返回图表数据
public FormulaModel Calculate(List source, FormulaModel formula,
Data.EnumTypes.CycleType cycleType, TimeSpan minutes)
{
var commonDataProvider = new CommonDataProvider(null);
commonDataProvider.LoadBinary(ConvertData(source));
commonDataProvider.DataCycle = ConvertCycle(cycleType, minutes);
try
{
var formulaBase = FormulaBase.GetFormulaByName(formula.FormulaName);
var formulaPackage = formulaBase.Run(commonDataProvider);
if (formulaPackage.Count > 0)
{
if (formula.IndicatorList == null)
{
formula.IndicatorList = new List();
}
formula.IndicatorList.Clear();
for (int i = 0; i < formulaPackage.Count; i++)
{
var indicatorModel = FormulaDataCovnert(formulaPackage[i], formula, commonDataProvider["DATE"]);
formula.IndicatorList.Add(indicatorModel);
}
}
}
catch
{
//找到不公式跳过,不影响下一个
}
return formula;
}
///
/// 打开指标编辑器
///
/// 计算源数据
/// 当前图表的所有计算公式
/// 周期类型
/// 自定义周期分钟数
/// 返回图表数据
public List OpenEditor(List source, string[] formulaArray, Data.EnumTypes.CycleType cycleType, TimeSpan minutes)
{
string selectFormula = (formulaArray != null && formulaArray.Any())
? formulaArray[0]
: "";
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(SetLanguage.languageName);
var manager = new FormulaManager();
if (manager.ShowForm(formulaArray, selectFormula) == DialogResult.OK)
{
//公式之间用#号隔开
string[] currentFormulas = manager.CurrentFormulas.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries);
var commonDataProvider = new CommonDataProvider(null);
//todo:以下内容考虑用线程实现
commonDataProvider.LoadBinary(ConvertData(source));
commonDataProvider.DataCycle = ConvertCycle(cycleType, minutes);
var formulas = new List();
foreach (var formula in currentFormulas)
{
try
{
var formulaModel = new FormulaModel();
var formulaBase = FormulaBase.GetFormulaByName(formula);
var formulaPackage = formulaBase.Run(commonDataProvider);
if (formulaPackage.Count > 0)
{
var indicatorModels = new List();
for (int i = 0; i < formulaPackage.Count; i++)
{
var indicatorModel = FormulaDataCovnert(formulaPackage[i], formulaModel, commonDataProvider["DATE"]);
indicatorModels.Add(indicatorModel);
}
formulaModel.FormulaName = formulaBase.FormulaName;
formulaModel.IndicatorList = indicatorModels;
formulas.Add(formulaModel);
}
}
catch (Exception ex)
{
//找到不公式跳过,不影响下一个
// throw;
}
}
return formulas;
}
return null;
}
///
/// 将编辑器计算的数据生成转换生成图表数据
///
/// 计算后的数据
/// 生成图表数据
private IndicatorModel FormulaDataCovnert(FormulaData formulaData, FormulaModel formulaModel, double[] dateTime)
{
var indicator = new IndicatorModel(formulaModel);
indicator.Alpha = formulaData.Alpha;
if (formulaData.AreaBrush is System.Drawing.SolidBrush) //只处理单色
{
SolidBrush solidBrush = formulaData.AreaBrush as System.Drawing.SolidBrush;
indicator.AreaBrush = System.Windows.Media.Color.FromArgb
(solidBrush.Color.A, solidBrush.Color.R, solidBrush.Color.G, solidBrush.Color.B);
}
if (formulaData.FormulaUpColor != System.Drawing.Color.Empty)
{
indicator.UpBrush = System.Windows.Media.Color.FromArgb(formulaData.FormulaUpColor.A,
formulaData.FormulaUpColor.R, formulaData.FormulaUpColor.G, formulaData.FormulaUpColor.B);
}
if (formulaData.FormulaDownColor != System.Drawing.Color.Empty)
{
indicator.DownBrush = System.Windows.Media.Color.FromArgb(formulaData.FormulaDownColor.A,
formulaData.FormulaDownColor.R, formulaData.FormulaDownColor.G, formulaData.FormulaDownColor.B);
}
indicator.CalculateDataPoints = ConvertDataPoint(formulaData.Data, dateTime);
// indicator.SubData = formulaData.SubData;
indicator.DataFormat = formulaData.Format;
indicator.LineName = formulaData.Name;
indicator.LineWidth = formulaData.LineWidth;
#region 还有多种未对应
switch (formulaData.DashStyle)
{
case System.Drawing.Drawing2D.DashStyle.Custom: //未设置
indicator.DashStyleType = DashStyleType.Dashed;
break;
case System.Drawing.Drawing2D.DashStyle.Dash:
indicator.DashStyleType = DashStyleType.Dashed;
break;
case System.Drawing.Drawing2D.DashStyle.DashDot://
indicator.DashStyleType = DashStyleType.Dashed;
break;
case System.Drawing.Drawing2D.DashStyle.DashDotDot:
indicator.DashStyleType = DashStyleType.LongDashes; //
break;
case System.Drawing.Drawing2D.DashStyle.Dot:
indicator.DashStyleType = DashStyleType.Dotted;
break;
case System.Drawing.Drawing2D.DashStyle.Solid:
indicator.DashStyleType = DashStyleType.Solid;
break;
default:
indicator.DashStyleType = DashStyleType.Solid;
break;
}
#endregion
#region 图表类型未一一对应
switch (formulaData.RenderType)
{
case FormulaRenderType.NORMAL:
indicator.LinePlotType = LinePlotType.Line;
break;
case FormulaRenderType.COLORSTICK:
indicator.LinePlotType = LinePlotType.Bar;
indicator.PlotNegValsDiffColor = true;
break;
case FormulaRenderType.VOLSTICK:
indicator.LinePlotType = LinePlotType.Bar;
indicator.VolBar = true;
break;
case FormulaRenderType.STICKLINE:
indicator.LinePlotType = LinePlotType.Bar;
break;
case FormulaRenderType.ICON:
break;
case FormulaRenderType.TEXT:
break;
case FormulaRenderType.POLY:
break;
case FormulaRenderType.FILLRGN:
indicator.LinePlotType = LinePlotType.FillRGN;
var doubleArray = formulaData.SubData["PRICE2"] as double[];
if (doubleArray != null)
{
indicator.SubData[indicator.FillRNGKey] = ConvertDataPoint(doubleArray, dateTime);
}
indicator.SubData[indicator.CondKey] = formulaData.SubData[indicator.CondKey];
break;
case FormulaRenderType.FILLAREA:
indicator.LinePlotType = LinePlotType.Area;
break;
case FormulaRenderType.PARTLINE:
indicator.LinePlotType = LinePlotType.OHLC;
break;
case FormulaRenderType.LINE:
indicator.LinePlotType = LinePlotType.Line;
break;
case FormulaRenderType.VERTLINE:
break;
case FormulaRenderType.AXISY:
break;
case FormulaRenderType.AXISYTEXT:
break;
case FormulaRenderType.STOCK:
indicator.LinePlotType = LinePlotType.Candlestick;
break;
case FormulaRenderType.MONOSTOCK:
indicator.LinePlotType = LinePlotType.Candlestick;
break;
default:
break;
}
#endregion
#region 点样式
switch (formulaData.Dot)
{
case FormulaDot.NORMAL:
indicator.PointDotType = PointDotType.NORMAL;
break;
case FormulaDot.CROSSDOT:
indicator.PointDotType = PointDotType.CROSSDOT;
indicator.LinePlotType = LinePlotType.CROSSDOT;
break;
case FormulaDot.POINTDOT:
indicator.PointDotType = PointDotType.POINTDOT;
indicator.LinePlotType = LinePlotType.Dot;
break;
case FormulaDot.CIRCLEDOT:
indicator.PointDotType = PointDotType.CIRCLEDOT;
indicator.LinePlotType = LinePlotType.CIRCLEDOT;
break;
default:
indicator.PointDotType = PointDotType.NORMAL;
break;
}
#endregion
indicator.LineWidth = formulaData.LineWidth;
indicator.SameColor = formulaData.SameColor;
return indicator;
}
///
/// 将使用公式计算数据转换成BarPoint
///
/// 计算数据
///
///
private List ConvertDataPoint(double[] dataArray, double[] dateArray)
{
if (dataArray == null) return null;
int index = 0;
var BarPoints = new List();
if (dataArray.Length < dateArray.Length)
{
foreach (var d in dateArray)
{
if (index >= dataArray.Length)
{
var barPoint = new BarDataPoint(DateTime.FromOADate(d), BarPoints[index - 1].Value);
BarPoints.Add(barPoint);
}
else
{
if (dataArray.Length == 0)
{
var barPoint = new BarDataPoint(DateTime.FromOADate(d), (float)dataArray[index]);
BarPoints.Add(barPoint);
}
else
{
var barPoint = new BarDataPoint(DateTime.FromOADate(d), (float)dataArray[index]);
BarPoints.Add(barPoint);
}
}
index++;
}
}
else
{
if (dataArray != null && dataArray.Count() > 0)
{
foreach (var d in dataArray)
{
if (!double.IsNaN(d))
{
var barPoint = new BarDataPoint(DateTime.FromOADate(dateArray[index]), (float)d);
BarPoints.Add(barPoint);
index++;
}
}
}
}
return BarPoints;
}
///
/// 转换周期
///
/// 周期类型
/// 分钟数据
/// 编辑器中的数据周期
private DataCycle ConvertCycle(Data.EnumTypes.CycleType cycleType, TimeSpan minutes)
{
switch (cycleType)
{
case CycleType.None:
return DataCycle.Day;
break;
case CycleType.Tik:
return DataCycle.Tick;
case CycleType.Minute:
return DataCycle.Minute;
case CycleType.Minute3:
return new DataCycle(DataCycleBase.MINUTE, 3);
case CycleType.Minute5:
return new DataCycle(DataCycleBase.MINUTE, 5);
case CycleType.Minute10:
return new DataCycle(DataCycleBase.MINUTE, 10);
case CycleType.Minute15:
return new DataCycle(DataCycleBase.MINUTE, 15);
case CycleType.Minute30:
return new DataCycle(DataCycleBase.MINUTE, 30);
case CycleType.Minute60:
return new DataCycle(DataCycleBase.MINUTE, 60);
case CycleType.Minute90:
return new DataCycle(DataCycleBase.MINUTE, 90);
case CycleType.Minute120:
return new DataCycle(DataCycleBase.MINUTE, 120);
case CycleType.Minute180:
return new DataCycle(DataCycleBase.MINUTE, 180);
case CycleType.Minute240:
return new DataCycle(DataCycleBase.MINUTE, 240);
case CycleType.Hour:
return DataCycle.Hour;
case CycleType.Day:
return DataCycle.Day;
case CycleType.Week:
return DataCycle.Week;
case CycleType.Month:
return DataCycle.Minute;
case CycleType.Quarter:
return DataCycle.Quarter;
case CycleType.Year:
return DataCycle.Year;
case CycleType.Custom:
return new DataCycle(DataCycleBase.MINUTE, (int)minutes.TotalMinutes);
default:
return DataCycle.Day;
}
}
///
/// 将源数据转换成数组
///
/// 源数据
/// 返回open, high, low, close, volume, date数据组
private double[][] ConvertData(List source)
{
var opens = new double[source.Count];
var highs = new double[source.Count];
var lows = new double[source.Count];
var closes = new double[source.Count];
var volumes = new double[source.Count];
var dates = new double[source.Count];
for (int i = 0; i < source.Count; i++)
{
opens[i] = source[i].Open;
highs[i] = source[i].High;
lows[i] = source[i].Low;
closes[i] = source[i].Close;
volumes[i] = source[i].Volume;
dates[i] = source[i].Date.ToOADate();
}
return new double[][] { opens, highs, lows, closes, volumes, dates };
}
///
/// 编辑公式
///
/// 公式名称
public void EditFormula(string formulaName)
{
MessageBoxManager.Unregister();
switch (SetLanguage.currentLanguage)
{
case ChartLanguageType.SimplifiedChinese:
MessageBoxManager.Yes = "是";
MessageBoxManager.No = "否";
MessageBoxManager.Cancel = "取消";
break;
case ChartLanguageType.TraditionalChinese:
MessageBoxManager.Yes = "是";
MessageBoxManager.No = "否";
MessageBoxManager.Cancel = "取消";
break;
case ChartLanguageType.English:
MessageBoxManager.Yes = "Yes";
MessageBoxManager.No = "No";
MessageBoxManager.Cancel = "Cancel";
break;
}
//注册MessageBoxManager
MessageBoxManager.Register();
var formulaBase = FormulaBase.GetFormulaByName(formulaName);
string formulaFile = PluginManager.GetFormulaFile(formulaBase);
if (formulaFile != null)
{
string directoryName = Path.GetDirectoryName(formulaFile);
formulaFile = Path.GetFileNameWithoutExtension(formulaFile).Replace('_', '.');
formulaFile = directoryName + @"\" + formulaFile;
if (File.Exists(formulaFile))
{
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(SetLanguage.languageName);
FormulaSourceEditor.Open(formulaFile, formulaBase.GetType().ToString());
}
}
}
public DataService()
{
SetLanguage.SetcurrentLanguage(ChartLanguageType.SimplifiedChinese);
}
///
/// 设置编辑器的语言
///
///
public void SetEditorLanguage(ChartLanguageType language)
{
SetLanguage.SetcurrentLanguage(language);
}
///
/// 从文件中加载公式
///
/// 文件名称
///
public SpaceModel LoadSpaceFromFile(string fileName)
{
if (string.IsNullOrEmpty(fileName)) //如fileName为空取主图指标的路径
{
var formulaBase = FormulaBase.GetFormulaByName("Main");
string formulaFile = PluginManager.GetFormulaFile(formulaBase);
if (formulaFile != null)
{
string directoryName = Path.GetDirectoryName(formulaFile);
formulaFile = Path.GetFileNameWithoutExtension(formulaFile).Replace('_', '.');
fileName = directoryName + @"\" + formulaFile;
}
}
var formulaSpace = FormulaSpace.Read(fileName);
if (formulaSpace != null)
{
var spaceModel = new SpaceModel();
CovertToModel(spaceModel, formulaSpace);
return spaceModel;
}
return null;
}
///
/// 转换Xml中公式命名对象
///
///
///
private void CovertToModel(SpaceModel model, FormulaSpace fs)
{
model.SpaceModels = new List();
model.ProgramModels = new List();
foreach (FormulaSpace space in fs.Namespaces) //加载命名空间
{
SpaceModel modelItem = new SpaceModel();
modelItem.SpaceName = space.Name;
model.SpaceModels.Add(modelItem);
this.CovertToModel(modelItem, space);
}
if (fs.Programs != null)
{
foreach (FormulaProgram program in fs.Programs)
{
var programItem = new ProgramModel();
programItem.Name = program.Name;
programItem.IsMainView = program.IsMainView;
model.ProgramModels.Add(programItem);
if (program.Params != null && program.Params.Count > 0)
{
foreach (var paramItem in program.Params)
{
var fParam = paramItem as FormulaParam;
if (fParam != null && !string.IsNullOrEmpty(fParam.Name))
{
programItem.DefaultParams[fParam.Name] = fParam.DefaultValue;
programItem.CustomParams[fParam.Name] = new CustomParamModel()
{
Value = fParam.CustomValue
};
}
}
}
}
}
}
///
/// 保存指标参数
///
/// 公式参数
public void SaveFormulaParams(List programModels)
{
if (programModels == null || !programModels.Any()) return;
var dicFormulaSpace = new Dictionary();
foreach (var programModel in programModels)
{
var formulaBase = FormulaBase.GetFormulaByName(programModel.Name);
if (formulaBase == null) continue;
string formulaFile = PluginManager.GetFormulaFile(formulaBase);
string directoryName = Path.GetDirectoryName(formulaFile);
formulaFile = Path.GetFileNameWithoutExtension(formulaFile);
if (!string.IsNullOrWhiteSpace(formulaFile))
{
formulaFile = formulaFile.Replace('_', '.');
var fileName = directoryName + @"\" + formulaFile;
FormulaProgram formulaProgram = null;
if (!dicFormulaSpace.ContainsKey(fileName))
{
var space = FormulaSpace.Read(fileName);
if (space != null)
{
dicFormulaSpace[fileName] = space;
formulaProgram = space.FindFormulaProgram(formulaBase);
}
}
else
{
formulaProgram = dicFormulaSpace[fileName].FindFormulaProgram(formulaBase);
}
if (formulaProgram != null)
{
if (programModel.CustomParams != null && programModel.CustomParams.Keys.Any())
{
foreach (var key in programModel.CustomParams.Keys)
{
if (formulaProgram.Params[key] != null)
{
formulaProgram.Params[key].CustomValue = programModel.CustomParams[key].Value;
}
}
}
}
}
}
if (dicFormulaSpace.Any()) //保存参数到配置文件
{
foreach (var key in dicFormulaSpace.Keys)
{
dicFormulaSpace[key].Write(key);
}
}
}
public void OpenFormulaEdit(string formulaName)
{
MessageBoxManager.Unregister();
switch (SetLanguage.currentLanguage)
{
case ChartLanguageType.SimplifiedChinese:
MessageBoxManager.Yes = "是";
MessageBoxManager.No = "否";
MessageBoxManager.Cancel = "取消";
break;
case ChartLanguageType.TraditionalChinese:
MessageBoxManager.Yes = "是";
MessageBoxManager.No = "否";
MessageBoxManager.Cancel = "取消";
break;
case ChartLanguageType.English:
MessageBoxManager.Yes = "Yes";
MessageBoxManager.No = "No";
MessageBoxManager.Cancel = "Cancel";
break;
}
//注册MessageBoxManager
MessageBoxManager.Register();
var formulaBase = FormulaBase.GetFormulaByName(formulaName);
string formulaFile = PluginManager.GetFormulaFile(formulaBase);
if (formulaFile != null)
{
string directoryName = Path.GetDirectoryName(formulaFile);
formulaFile = Path.GetFileNameWithoutExtension(formulaFile).Replace('_', '.');
formulaFile = directoryName + @"\" + formulaFile;
if (File.Exists(formulaFile))
{
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(SetLanguage.languageName);
FormulaSourceEditor.Open(formulaFile, "FML.");
}
}
}
///
/// 转换DataPoint数据
///
/// 数据源
/// 周期
/// 自定义周期时间
///
public CommonDataProvider DataPointConvert(List source, CycleType cycleType, TimeSpan minutes,IDataManager dataManager)
{
var commonDataProvider = new CommonDataProvider(dataManager);
if (source != null)
{
commonDataProvider.LoadBinary(ConvertData(source));
commonDataProvider.DataCycle = ConvertCycle(cycleType, minutes);
}
return commonDataProvider;
}
}
}