DataMananer.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Windows.Controls;
  6. using System.Windows.Documents;
  7. using System.Windows.Threading;
  8. using Easychart.Finance;
  9. using Easychart.Finance.DataProvider;
  10. using Easychart.Finance.Win;
  11. using GalaSoft.MvvmLight.Ioc;
  12. using Muchinfo.MTPClient.Data;
  13. using Muchinfo.MTPClient.Data.Enums;
  14. using Muchinfo.MTPClient.Data.Model;
  15. using Muchinfo.MTPClient.Data.Quote;
  16. using Muchinfo.MTPClient.Infrastructure.Utilities;
  17. using Muchinfo.MTPClient.IService;
  18. namespace Muchinfo.MTPClient.Analysis.Utilities
  19. {
  20. /// <summary>
  21. /// Class DataMananer.
  22. /// </summary>
  23. public class DataMananer : CacheDataManagerBase
  24. {
  25. #region Members of DataMananer (4)
  26. private const int c_defaultCount = 3;
  27. private ChartWinControl _winChart;
  28. private CycleType _cycleType;
  29. private DateTime BasicDateTime = new DateTime(1970, 1, 1, 0, 0, 0); //
  30. private IQuoteDataService _quoteDataService;
  31. private const short c_DefaultCount = 500;
  32. private QuoteGoods _currentGoods; //当前商品
  33. private TimeSpan _timeSpan;
  34. private DateTime _quoteTime; //行情时间
  35. private List<OHLCDataPoints> _iDataPoints;
  36. private CommonDataProvider _commonDataProvider; //数据源
  37. #endregion Members of DataMananer (4)
  38. #region Constructors of DataMananer (1)
  39. public DataMananer(ChartWinControl chart)
  40. {
  41. _quoteDataService = SimpleIoc.Default.GetInstance<IQuoteDataService>();
  42. _winChart = chart;
  43. _commonDataProvider = new CommonDataProvider(this);
  44. ////可自定义首行显示格式
  45. ////this._winChart.PriceLabelFormat = "{CODE} O:{OPEN} H:{HIGH} L:{LOW} C:{CLOSE} Chg:{CHANGE}";
  46. _winChart.InsertFormulaToMain("MA4(5,10,20,30)");
  47. _winChart.InsertDefaultFormula("MACD");
  48. KeyMessageFilter.AddMessageFilter(_winChart);
  49. }
  50. #endregion Constructors of DataMananer (1)
  51. #region Methods of DataMananer (5)
  52. /// <summary>
  53. /// 转换周期
  54. /// </summary>
  55. /// <param name="cycleType">周期类型</param>
  56. /// <param name="minutes">分钟数据</param>
  57. /// <returns>编辑器中的数据周期</returns>
  58. private DataCycle ConvertCycle(CycleType cycleType, TimeSpan minutes)
  59. {
  60. switch (cycleType)
  61. {
  62. case CycleType.TimeSharing:
  63. return DataCycle.TimeChart;
  64. case CycleType.Minutes1:
  65. return DataCycle.Minute;
  66. case CycleType.Minutes5:
  67. return new DataCycle(DataCycleBase.MINUTE, 5);
  68. case CycleType.Minutes30:
  69. return new DataCycle(DataCycleBase.MINUTE, 30);
  70. case CycleType.Hour:
  71. return new DataCycle(DataCycleBase.HOUR, 1);
  72. case CycleType.Hour4:
  73. return new DataCycle(DataCycleBase.HOUR,4);
  74. case CycleType.Day:
  75. return new DataCycle(DataCycleBase.DAY, 1);
  76. default:
  77. return DataCycle.Day;
  78. }
  79. }
  80. /// <summary>
  81. /// Gets the data.
  82. /// </summary>
  83. /// <param name="goodsCode">The goods code.</param>
  84. /// <param name="count">The count.</param>
  85. /// <returns>IDataProvider.</returns>
  86. public override IDataProvider GetData(string goodsCode, int count)
  87. {
  88. if (_iDataPoints != null && _iDataPoints.Any())
  89. {
  90. _commonDataProvider.LoadBinary(ConvertData(_iDataPoints));
  91. _commonDataProvider.DataCycle = ConvertCycle(_cycleType, _timeSpan);
  92. _commonDataProvider.SetStringData("Code", goodsCode);
  93. }
  94. if (_iDataPoints == null || !_iDataPoints.Any()) //没数据时刷新会报异常
  95. {
  96. return null;
  97. }
  98. return _commonDataProvider;
  99. }
  100. /// <summary>
  101. /// 初始化数据
  102. /// </summary>
  103. /// <param name="goods">商品</param>
  104. /// <param name="cycleType">周期</param>
  105. /// <param name="timeSpan">自定义周期</param>
  106. public void InitBarDataPoints(QuoteGoods goods, CycleType cycleType, TimeSpan timeSpan)
  107. {
  108. _currentGoods = goods;
  109. if (_iDataPoints != null) //删除前一周期数据
  110. {
  111. _iDataPoints.Clear();
  112. }
  113. CycleType = cycleType;
  114. _timeSpan = timeSpan;
  115. _winChart.DataManager = this;
  116. _winChart.DecimalPrice = goods.GoodsParameters.HqExchFigures;
  117. _winChart.CurrentDataCycle = ConvertCycle(_cycleType, _timeSpan);
  118. this._winChart.Symbol = goods.GoodsCode;
  119. //时间应该是服务器的时间
  120. DateTime starTime = ApplicationParameter.ServerTimeNow; //取当前时间之前的
  121. DateTime endTime = BasicDateTime;
  122. short count = c_DefaultCount;
  123. if (cycleType == CycleType.TimeSharing)
  124. {
  125. if (this._winChart.openCloseArray != null && this._winChart.openCloseArray.Length >= 2)
  126. {
  127. starTime = this._winChart.openCloseArray[0];
  128. endTime = this._winChart.openCloseArray[this._winChart.openCloseArray.Length - 1];
  129. count = 0;
  130. }
  131. }
  132. _quoteDataService.GetHistoryCycleData(goods, cycleType, starTime, endTime, count, QueryHistorySuccess,
  133. ErrorSuccess);
  134. ////数据源必须按时间顺排序,否则画不出图表
  135. }
  136. private void QueryHistorySuccess(GoodsHistoryCycle historyCycle)
  137. {
  138. if (historyCycle.OhlcDataPoints != null && historyCycle.OhlcDataPoints.Any())
  139. {
  140. _iDataPoints = historyCycle.OhlcDataPoints.OrderBy((item) => item.Date).ToList();
  141. }
  142. if (_cycleType == CycleType.TimeSharing && historyCycle.OhlcDataPoints.Any() &&
  143. this._winChart.openCloseArray != null)
  144. {
  145. _iDataPoints = CalcTimeSpanData(historyCycle); ///补成交前的数据
  146. _iDataPoints = _iDataPoints.OrderBy(item => item.Date).ToList();
  147. RepairChartData(); ///补成交到现在的数据
  148. }
  149. if (_iDataPoints != null && _iDataPoints.Any() ) ////分时图没有数据也画
  150. {
  151. ReflashChart();
  152. }
  153. else
  154. {
  155. if (_cycleType == CycleType.TimeSharing) ////分时图补数据
  156. {
  157. WithoutDataSetLastCose();
  158. ReflashChart();
  159. }
  160. }
  161. }
  162. /// <summary>
  163. /// 分时图补数据
  164. /// </summary>
  165. private void WithoutDataSetLastCose()
  166. {
  167. var date =
  168. ApplicationParameter.BasicDateTime.AddMinutes(
  169. (int) (ApplicationParameter.ServerTimeNow - ApplicationParameter.BasicDateTime).TotalMinutes);
  170. var barDataPoint = new OHLCDataPoints((double) this._currentGoods.LastClose, date.ToOADate());
  171. // var tempdate = DateTime.FromOADate(barDataPoint.Date);
  172. UpdateTickChart(barDataPoint);
  173. }
  174. /// <summary>
  175. /// 补缺分时图数据
  176. /// </summary>
  177. /// <param name="historyCycle"></param>
  178. private List<OHLCDataPoints> CalcTimeSpanData(GoodsHistoryCycle historyCycle)
  179. {
  180. ////结算计划是开盘时间[0] 收盘时间[1]
  181. DateTime currentTime = DateTime.Now;
  182. DateTime.TryParse(ApplicationParameter.ServerTimeNow.ToString("yyyy-MM-dd HH:mm"), out currentTime);
  183. var dataPoints = new List<OHLCDataPoints>();
  184. if (this._winChart.openCloseArray.Any() && this._winChart.openCloseArray[0] < currentTime) //当前时间比开市时间早
  185. {
  186. var points = historyCycle.OhlcDataPoints.OrderBy(item => item.Date).ToList();
  187. double currentDate1;
  188. DateTime temDate, currentDateTime = this._winChart.openCloseArray[0]; //currentDateTime当前点的时间
  189. double currentValue; //当前值
  190. int currentIndex = 0;
  191. var spanList = new List<double>(); //开收市首次开市的时间间隔
  192. for (int j = 0; j < this._winChart.openCloseArray.Length; j++)
  193. {
  194. var span = Math.Floor((this._winChart.openCloseArray[j] - this._winChart.openCloseArray[0]).TotalMinutes);
  195. spanList.Add(span);
  196. }
  197. for (int i = 0; i < points.Count; i++)
  198. {
  199. temDate = DateTime.FromOADate(points[i].Date);
  200. currentDate1 = Math.Floor((temDate - this._winChart.openCloseArray[0]).TotalMinutes);
  201. if (currentDate1 == 0) ////开盘点
  202. {
  203. dataPoints.Add(points[i]);
  204. #if DEBUG
  205. Console.WriteLine("q1:" + temDate.ToString("yyyy-MM-dd HH:mm:ss"));
  206. #endif
  207. continue;
  208. }
  209. for (int j = currentIndex; j < spanList.Count - 1; j += 2)
  210. {
  211. if (spanList[j] > currentDate1)
  212. {
  213. break;
  214. }
  215. else if (spanList[j] <= currentDate1 && spanList[j + 1] >= currentDate1)
  216. {
  217. if (!dataPoints.Any())
  218. {
  219. currentDateTime = this._winChart.openCloseArray[0];
  220. currentValue = points[i].Close;
  221. }
  222. else
  223. {
  224. currentDateTime = DateTime.FromOADate(dataPoints.Last().Date);
  225. if (currentDateTime < this._winChart.openCloseArray[j]) ///第二段时间开始不能使用最后一个为当前时间
  226. {
  227. currentDateTime = this._winChart.openCloseArray[j];
  228. }
  229. currentValue = dataPoints.Last().Close;
  230. }
  231. var barSpan = currentDate1 - Math.Floor((currentDateTime - this._winChart.openCloseArray[0]).TotalMinutes) - 1;
  232. for (int k = 0; k < barSpan; k++)
  233. {
  234. var point = new OHLCDataPoints(currentValue, currentDateTime.AddMinutes(k).ToOADate(),0,0); //// 补数据 ////成交量0
  235. #if DEBUG
  236. Console.WriteLine("q2:" + currentDateTime.AddMinutes(k).ToString("yyyy-MM-dd HH:mm:ss"));
  237. #endif
  238. dataPoints.Add(point);
  239. }
  240. #if DEBUG
  241. Console.WriteLine("q3:" + DateTime.FromOADate(points[i].Date).ToString("yyyy-MM-dd HH:mm:ss"));
  242. #endif
  243. dataPoints.Add(points[i]);
  244. currentDateTime = temDate;
  245. currentIndex = j;
  246. break;
  247. }
  248. else if (spanList[j + 1] < currentDate1) //开盘第一时间段没有数据
  249. {
  250. var curentSpan = Math.Floor((currentDateTime - this._winChart.openCloseArray[0]).TotalMinutes);
  251. if (curentSpan < spanList[j + 1])
  252. {
  253. var barSpan = spanList[j + 1] - curentSpan;
  254. for (int k = 0; k <= barSpan; k++)
  255. {
  256. var point = new OHLCDataPoints(points[i].Close, currentDateTime.AddMinutes(k).ToOADate(),0,0); //// 补数据 ////成交量0
  257. #if DEBUG
  258. Console.WriteLine("q4:" + currentDateTime.AddMinutes(k).ToString("yyyy-MM-dd HH:mm:ss"));
  259. #endif
  260. dataPoints.Add(point);
  261. }
  262. currentDateTime = currentDateTime.AddMinutes(barSpan);
  263. }
  264. currentIndex = j;
  265. }
  266. }
  267. }
  268. }
  269. return dataPoints;
  270. }
  271. private void ErrorSuccess(ErrorEntity errorEntity)
  272. {
  273. //todo:行情请求超时
  274. }
  275. /// <summary>
  276. /// 将源数据转换成数组
  277. /// </summary>
  278. /// <param name="source">源数据</param>
  279. /// <returns>返回open, high, low, close, volume, date数据组 </returns>
  280. private double[][] ConvertData(List<OHLCDataPoints> source)
  281. {
  282. var opens = new double[source.Count];
  283. var highs = new double[source.Count];
  284. var lows = new double[source.Count];
  285. var closes = new double[source.Count];
  286. var volumes = new double[source.Count];
  287. var dates = new double[source.Count];
  288. var turnovers = new double[source.Count];
  289. var adjClose = new double[source.Count];
  290. for (int i = 0; i < source.Count; i++)
  291. {
  292. opens[i] = source[i].Open;
  293. highs[i] = source[i].High;
  294. lows[i] = source[i].Low;
  295. closes[i] = source[i].Close;
  296. volumes[i] = source[i].Volume;
  297. dates[i] = source[i].Date;
  298. adjClose[i] = source[i].Close;
  299. turnovers[i] = source[i].TotleTurnovers;
  300. }
  301. return new double[][] { opens, highs, lows, closes, volumes, dates,adjClose, turnovers };
  302. }
  303. /// <summary>
  304. /// 更新图表周期
  305. /// </summary>
  306. /// <param name="cycleType">周期</param>
  307. /// <param name="timeSpan">自定义周期</param>
  308. public void ChangeCycle(CycleType cycleType, TimeSpan timeSpan)
  309. {
  310. InitBarDataPoints(_currentGoods, cycleType, timeSpan);
  311. }
  312. /// <summary>
  313. /// 图表切换商品
  314. /// </summary>
  315. /// <param name="goods"></param>
  316. public void ChangeGoods(QuoteGoods goods)
  317. {
  318. InitBarDataPoints(goods, this._cycleType, this._timeSpan);
  319. }
  320. /// <summary>
  321. /// 加载更多数据
  322. /// </summary>
  323. public void LoadMoreData()
  324. {
  325. if (_cycleType == CycleType.TimeSharing) return;
  326. DateTime endDate = ApplicationParameter.ServerTimeNow; //todo:默认应该是服务端的时间
  327. if (_iDataPoints != null && _iDataPoints.Any())
  328. {
  329. endDate = DateTime.FromOADate(_iDataPoints[0].Date);
  330. }
  331. _quoteDataService.GetHistoryCycleData(_currentGoods, _cycleType,endDate,BasicDateTime,
  332. c_DefaultCount, LoadMoreSuccess, ErrorSuccess);
  333. }
  334. public void LoadMoreSuccess(GoodsHistoryCycle historyCycle)
  335. {
  336. if (historyCycle != null && historyCycle.OhlcDataPoints != null && historyCycle.OhlcDataPoints.Any())
  337. {
  338. historyCycle.OhlcDataPoints = historyCycle.OhlcDataPoints.OrderBy(z => z.Date).ToList();
  339. if (_iDataPoints == null)
  340. {
  341. _iDataPoints = historyCycle.OhlcDataPoints;
  342. }
  343. else
  344. {
  345. _iDataPoints.InsertRange(0, historyCycle.OhlcDataPoints);
  346. }
  347. if (_iDataPoints != null)
  348. {
  349. ReflashChart();
  350. }
  351. }
  352. }
  353. /// <summary>
  354. /// Sets the data source.
  355. /// </summary>
  356. /// <param name="symbol">The symbol.</param>
  357. /// <param name="barDataPoints">The bar data points.</param>
  358. /// <param name="cycleType">Type of the cycle.</param>
  359. /// <param name="timeSpan">The time span.</param>
  360. public void SetDataSource(string symbol, List<OHLCDataPoints> barDataPoints, CycleType cycleType, TimeSpan timeSpan)
  361. {
  362. ////数据源必须按时间顺排序,否则画不出图表
  363. _iDataPoints = barDataPoints == null ? null : barDataPoints.OrderBy(z => z.Date).ToList();
  364. CycleType = cycleType;
  365. _timeSpan = timeSpan;
  366. this._winChart.Symbol = symbol;
  367. ReflashChart();
  368. }
  369. /// <summary>
  370. /// 更新Tick数据
  371. /// </summary>
  372. /// <param name="barDataPoint">BarPoint</param>
  373. public void UpdatePoint(OHLCDataPoints barDataPoint)
  374. {
  375. #region 设置是否是显示最新数据
  376. var currentTime = DateTime.FromOADate(barDataPoint.Date); ////设置显示结束时间
  377. if (_winChart.Chart != null && _winChart.EndTime != DateTime.MinValue)
  378. {
  379. var lastIndex = _winChart.Chart.DateToIndex(currentTime);
  380. var currentIndex = _winChart.Chart.DateToIndex(_winChart.EndTime);
  381. if (Math.Abs(lastIndex - currentIndex) < 5)
  382. {
  383. _winChart.EndTime = currentTime;
  384. }
  385. }
  386. else
  387. {
  388. _winChart.EndTime = currentTime;
  389. }
  390. #endregion
  391. UpdateHighLowPrice(barDataPoint.Close); //更新最高最低价
  392. if (_cycleType == CycleType.TimeSharing)
  393. {
  394. var tempdate = DateTime.FromOADate(barDataPoint.Date);
  395. if (IsOnSettlementPlan(tempdate))
  396. {
  397. barDataPoint.Date = tempdate.AddSeconds(-tempdate.Date.Second).ToOADate();
  398. UpdateTickChart(barDataPoint);
  399. }
  400. }
  401. else
  402. {
  403. DateTime updateTime = default(DateTime);
  404. if (_iDataPoints == null)
  405. {
  406. _iDataPoints=new List<OHLCDataPoints>();
  407. var item = new OHLCDataPoints(barDataPoint.Date, barDataPoint.Open, barDataPoint.High, barDataPoint.Low,
  408. barDataPoint.Close, barDataPoint.Volume, barDataPoint.TotleTurnovers);
  409. _iDataPoints.Add(item);
  410. }
  411. else if (IsNotInCycle(DateTime.FromOADate(barDataPoint.Date), ref updateTime))
  412. {
  413. var item = new OHLCDataPoints(updateTime.ToOADate(), barDataPoint.Open, barDataPoint.High, barDataPoint.Low,
  414. barDataPoint.Close, barDataPoint.Volume, barDataPoint.TotleTurnovers );
  415. _iDataPoints.Add(item);
  416. }
  417. else
  418. {
  419. if (_iDataPoints != null && _iDataPoints.Count > 0)
  420. {
  421. var barPointTmp = _iDataPoints.Last() ;
  422. if (barPointTmp == null) return;
  423. barPointTmp.Close = barDataPoint.Close;
  424. barPointTmp.High = barDataPoint.Close > barPointTmp.High ? barDataPoint.Close : barPointTmp.High;
  425. barPointTmp.Low = barDataPoint.Close < barPointTmp.Low ? barDataPoint.Close : barPointTmp.Low;
  426. barPointTmp.TotleTurnovers += barDataPoint.TotleTurnovers;
  427. barPointTmp.Volume += barDataPoint.Volume;
  428. }
  429. }
  430. }
  431. if (_iDataPoints != null)
  432. {
  433. ReflashChart();
  434. }
  435. }
  436. #region 分时图
  437. /// <summary>
  438. /// 更新当前最高,最低价
  439. /// </summary>
  440. /// <param name="currentPrice"></param>
  441. private void UpdateHighLowPrice(double currentPrice)
  442. {
  443. if (_winChart.Chart != null)
  444. {
  445. if (_winChart.Chart.Highest < currentPrice)
  446. {
  447. _winChart.Chart.Highest = currentPrice;
  448. }
  449. else if (_winChart.Chart.Lowsest > currentPrice&&currentPrice!=0)
  450. {
  451. _winChart.Chart.Lowsest = currentPrice;
  452. }
  453. }
  454. }
  455. /// <summary>
  456. /// 实时行情更新分时数据
  457. /// </summary>
  458. /// <param name="barDataPoint">实时数据</param>
  459. public void UpdateTickChart(OHLCDataPoints barDataPoint)
  460. {
  461. if (_iDataPoints == null)
  462. {
  463. _iDataPoints = new List<OHLCDataPoints>();
  464. }
  465. var barPointTmp = _iDataPoints.LastOrDefault();
  466. if (barPointTmp != null)
  467. {
  468. RepairMinDate(barPointTmp, barDataPoint);
  469. }
  470. else
  471. {
  472. if (this._winChart.openCloseArray != null ||
  473. this._winChart.openCloseArray.Any())
  474. {
  475. var ohlc = new OHLCDataPoints(barDataPoint.Close, this._winChart.openCloseArray[0].ToOADate());
  476. //if (! IsOnSettlementPlan(currentMin.Date))
  477. //{
  478. // //todo:当前的时间不在开休市时间内
  479. //}
  480. //_iDataPoints.Add(barDataPoint);
  481. _iDataPoints.Add(ohlc);
  482. RepairMinDate(ohlc, barDataPoint);
  483. }
  484. }
  485. if (_iDataPoints != null)
  486. {
  487. ReflashChart();
  488. }
  489. }
  490. /// <summary>
  491. /// /补分时图数据
  492. /// </summary>
  493. /// <param name="barPointTmp">最近一分钟数据</param>
  494. /// <param name="barDataPoint"></param>
  495. private void RepairMinDate(OHLCDataPoints barPointTmp, OHLCDataPoints barDataPoint)
  496. {
  497. var spanMinutes = (DateTime.FromOADate(barDataPoint.Date) - DateTime.FromOADate(barPointTmp.Date)).TotalMinutes;
  498. var lastdate = DateTime.FromOADate(barPointTmp.Date);
  499. if (spanMinutes > 1)
  500. {
  501. for (int i = 1; i < (int)spanMinutes + 1; i++) //补数据
  502. {
  503. if (IsOnSettlementPlan(lastdate.AddMinutes(i)))
  504. {
  505. var tembarPoint = new OHLCDataPoints(barDataPoint.Close, lastdate.AddMinutes(i).ToOADate(), 0,0); ////补数据成交量为0
  506. _iDataPoints.Add(tembarPoint);
  507. }
  508. }
  509. if (IsOnSettlementPlan(DateTime.FromOADate(barDataPoint.Date)))
  510. {
  511. _iDataPoints.Add(barDataPoint);
  512. }
  513. //_iDataPoints.Add(barDataPoint);
  514. }
  515. else if (spanMinutes > 0)
  516. {
  517. var current = DateTime.FromOADate(barDataPoint.Date);
  518. if (current.Minute == lastdate.Minute) //同分钟
  519. {
  520. barPointTmp.Close = barDataPoint.Close;
  521. barPointTmp.Volume += barDataPoint.Volume; ////成交量累加
  522. barPointTmp.TotleTurnovers += barDataPoint.TotleTurnovers;////成交额累加
  523. }
  524. else
  525. {
  526. _iDataPoints.Add(barDataPoint);
  527. }
  528. }
  529. }
  530. #endregion
  531. /// <summary>
  532. /// 图表切换主题
  533. /// </summary>
  534. /// <param name="style">The style.</param>
  535. public void UpdateSkin(string style)
  536. {
  537. var skinByName = FormulaSkin.GetSkinByName(style);
  538. if (skinByName == null)
  539. {
  540. return;
  541. }
  542. _winChart.Skin = style;
  543. _winChart.ApplySkin(skinByName);
  544. _winChart.CurrentDataCycle = ConvertCycle(_cycleType, _timeSpan);
  545. }
  546. /// <summary>
  547. /// 图表放大缩小
  548. /// </summary>
  549. /// <param name="zoomType">Type of the zoom.</param>
  550. public void Zoom(ZoomType zoomType)
  551. {
  552. var direction = zoomType == ZoomType.In ? 1 : -1;
  553. _winChart.ScaleChart(direction * 0.05);
  554. }
  555. /// <summary>
  556. /// 是否在周期内
  557. /// </summary>
  558. public bool IsNotInCycle(DateTime tikTime, ref DateTime CycleDate)
  559. {
  560. var Rlt = default(bool);
  561. if (_iDataPoints != null && _iDataPoints.Any() && tikTime != DateTime.MinValue)
  562. {
  563. var dt =DateTime.FromOADate( _iDataPoints.Last().Date);
  564. var ts = tikTime - dt;
  565. switch (_cycleType)
  566. {
  567. case CycleType.Minutes1:
  568. case CycleType.Minutes5:
  569. case CycleType.Minutes30:
  570. case CycleType.Hour:
  571. case CycleType.Hour4:
  572. var newDt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0).AddMinutes(CurrentTimeFrame.TotalMinutes);
  573. Rlt = tikTime >= newDt;
  574. if (Rlt)
  575. {
  576. CycleDate = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0).AddMinutes((Math.Floor((ts.TotalMinutes / CurrentTimeFrame.TotalMinutes)) * CurrentTimeFrame.TotalMinutes));
  577. }
  578. break;
  579. case CycleType.Day:
  580. Rlt = tikTime >= new DateTime(dt.Year, dt.Month, dt.Day).AddDays(1);
  581. if (Rlt)
  582. {
  583. CycleDate = new DateTime(dt.Year, dt.Month, dt.Day).AddDays((Math.Floor((ts.TotalDays / CurrentTimeFrame.TotalDays)) * CurrentTimeFrame.TotalDays));
  584. }
  585. break;
  586. //case CycleType.Week:
  587. // Rlt = tikTime >= new DateTime(dt.Year, dt.Month, dt.Day).AddDays((7 - ((int)(DayOfWeek)dt.DayOfWeek)));
  588. // if (Rlt)
  589. // {
  590. // CycleDate = new DateTime(dt.Year, dt.Month, dt.Day).AddDays((Math.Floor((ts.TotalDays / CurrentTimeFrame.TotalDays)) * CurrentTimeFrame.TotalDays));
  591. // }
  592. // break;
  593. //case CycleType.Month:
  594. // Rlt = tikTime >= new DateTime(dt.Year, dt.Month, 1).AddMonths(1);
  595. // if (Rlt)
  596. // {
  597. // CycleDate = new DateTime(dt.Year, tikTime.Month, 1);
  598. // }
  599. // break;
  600. //case CycleType.Quarter:
  601. // Rlt = tikTime >= new DateTime(dt.Year, dt.Month, 1).AddMonths(3);
  602. // if (Rlt)
  603. // {
  604. // var mm = (Math.Floor((ts.TotalDays / CurrentTimeFrame.TotalDays)) * CurrentTimeFrame.TotalDays);
  605. // CycleDate = new DateTime(dt.Year, dt.Month, 1).AddDays(mm);
  606. // }
  607. // break;
  608. //case CycleType.Year:
  609. // Rlt = tikTime >= new DateTime(dt.Year + 1, 1, 1);
  610. // if (Rlt)
  611. // {
  612. // CycleDate = new DateTime(tikTime.Year, 1, 1);
  613. // }
  614. // break;
  615. default:
  616. Rlt = false;
  617. break;
  618. }
  619. //Console.WriteLine("time:{0} tikTime:{1} newdate Rlt:{2} RltTime:{3}", dt.ToString(), tikTime.ToString(), newDt.ToString(), Rlt.ToString(), CycleDate.ToString());
  620. }
  621. return Rlt;
  622. }
  623. /// <summary>
  624. /// 根据周期生成TimeSpan
  625. /// </summary>
  626. public TimeSpan CurrentTimeFrame
  627. {
  628. get
  629. {
  630. switch (_cycleType)
  631. {
  632. case CycleType.Minutes1:
  633. return new TimeSpan(0, 1, 0);
  634. case CycleType.Minutes5:
  635. return new TimeSpan(0, 5, 0);
  636. case CycleType.Minutes30:
  637. return new TimeSpan(0, 30, 0);
  638. case CycleType.Hour:
  639. return new TimeSpan(1, 0, 0);
  640. case CycleType.Hour4:
  641. return new TimeSpan(4, 0, 0);
  642. case CycleType.Day:
  643. return new TimeSpan(24, 0, 0);
  644. default:
  645. //分时图为1分
  646. return new TimeSpan(0, 1, 0);
  647. }
  648. }
  649. }
  650. /// <summary>
  651. /// 添加指标
  652. /// </summary>
  653. /// <param name="farmulaName"></param>
  654. /// <param name="isMain"></param>
  655. public void AddIndicator(string farmulaName,bool isMain)
  656. {
  657. if (this._winChart!=null)
  658. {
  659. if (!isMain)
  660. {
  661. if (this._winChart.Chart.Areas.Count < c_defaultCount)
  662. {
  663. this._winChart.InsertDefaultFormula(farmulaName,1);
  664. }
  665. else
  666. {
  667. this._winChart.InsertFormulaToArea(this._winChart.Chart.SelectedArea, farmulaName);
  668. }
  669. }
  670. else
  671. {
  672. this._winChart.InsertFormulaToMain(farmulaName);
  673. }
  674. }
  675. }
  676. /// <summary>
  677. /// 读取数据,周期改变时更新图表(周期,需赋值才能调用)
  678. /// </summary>
  679. private void ReflashChart()
  680. {
  681. _winChart.DecimalPrice = _currentGoods.GoodsParameters.HqExchFigures;
  682. //if (_iDataPoints != null && _iDataPoints.Any())
  683. //{
  684. //}
  685. //else
  686. //{
  687. //}
  688. _winChart.DataManager = this;
  689. // _winChart.BindData();
  690. //_winChart.SetQuoteDigits(_currentGoods.GoodsParameters.HqExchFigures);
  691. _winChart.NeedRebind();
  692. _winChart.NeedRefresh();
  693. }
  694. /// <summary>
  695. /// 移除选择的指标
  696. /// </summary>
  697. public void RemoveFormula()
  698. {
  699. if (this._winChart.Chart.SelectedArea != null
  700. && this._winChart.Chart.SelectedArea.SelectedFormula!=null)
  701. {
  702. this._winChart.Chart.SelectedArea.RemoveFormula(this._winChart.Chart.SelectedArea.SelectedFormula);
  703. if (this._winChart.Chart.SelectedArea.Formulas != null &&
  704. this._winChart.Chart.SelectedArea.Formulas.Count <= 0)
  705. {
  706. this._winChart.Chart.RemoveArea(this._winChart.Chart.SelectedArea.Name);
  707. }
  708. ReflashChart();
  709. }
  710. }
  711. /// <summary>
  712. /// 是否在结算计划内
  713. /// </summary>
  714. /// <param name="date"></param>
  715. /// <returns></returns>
  716. private bool IsOnSettlementPlan(DateTime date)
  717. {
  718. if (this._winChart.openCloseArray == null ||
  719. !this._winChart.openCloseArray.Any() ||
  720. this._winChart.openCloseArray.Length % 2 != 0)
  721. {
  722. return false;
  723. }
  724. else
  725. {
  726. for (int i = 0; i < this._winChart.openCloseArray.Length; i += 2)
  727. {
  728. if (this._winChart.openCloseArray[i] <= date && date <= this._winChart.openCloseArray[i + 1])
  729. {
  730. return true;
  731. }
  732. }
  733. return false;
  734. }
  735. }
  736. public new void Dispose()
  737. {
  738. base.Dispose();
  739. if (_iDataPoints != null)
  740. {
  741. _iDataPoints.Clear();
  742. }
  743. _iDataPoints = null;
  744. if (_commonDataProvider != null)
  745. {
  746. _commonDataProvider.Dispose();
  747. }
  748. if (_chartTimer != null)
  749. {
  750. _chartTimer.Stop();
  751. }
  752. }
  753. #region 分时图定时器
  754. public CycleType CycleType
  755. {
  756. get { return _cycleType; }
  757. set
  758. {
  759. _cycleType = value;
  760. if (_cycleType == CycleType.TimeSharing)
  761. {
  762. StartMinituesTimer();
  763. }
  764. else
  765. {
  766. if (_chartTimer != null)
  767. {
  768. _chartTimer.Stop();
  769. }
  770. }
  771. }
  772. }
  773. private bool IsInitTimer = false;
  774. private DispatcherTimer _chartTimer;
  775. private void StartMinituesTimer()
  776. {
  777. if (!IsInitTimer)
  778. {
  779. _chartTimer = new DispatcherTimer();
  780. _chartTimer.Tick+=_chartTimer_Tick;
  781. _chartTimer.Interval=new TimeSpan(0,0,30);
  782. }
  783. _chartTimer.Start();
  784. }
  785. private void _chartTimer_Tick(object sender, EventArgs e)
  786. {
  787. RepairChartData();
  788. }
  789. /// <summary>
  790. /// 补数据
  791. /// </summary>
  792. private void RepairChartData()
  793. {
  794. var date = ApplicationParameter.BasicDateTime.AddMinutes(
  795. (int)(ApplicationParameter.ServerTimeNow - ApplicationParameter.BasicDateTime).TotalMinutes);
  796. var currentPrice = this._currentGoods.CurrentPrice > 0
  797. ? this._currentGoods.CurrentPrice
  798. : this._currentGoods.LastClose;
  799. var barDataPoint = new OHLCDataPoints((double)currentPrice, date.ToOADate());
  800. UpdateTickChart(barDataPoint);
  801. }
  802. #endregion
  803. #endregion Methods of DataMananer (5)
  804. }
  805. }