PageRenderTime 90ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/Trading/SchemaTrading/tables/Data/CDataList.customisation.cs

#
C# | 382 lines | 319 code | 29 blank | 34 comment | 51 complexity | 4fd43199b8b1f57e83a0c2951afab144 MD5 | raw file
  1. using System;
  2. using System.Text;
  3. using System.Data;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Web;
  8. using Framework;
  9. namespace SchemaTrading
  10. {
  11. //Collection Class (Customisable half)
  12. public partial class CDataList
  13. {
  14. #region Filters
  15. #endregion
  16. #region Searching (Optional)
  17. //Represents a simple search box to search PK and any string columns (add overloads as required, based on the pattern below)
  18. //e.g. public CDataList Search(string nameOrId, int seriesId) { ...
  19. public CDataList Search(string nameOrId)
  20. {
  21. //1. Normalisation
  22. nameOrId = (nameOrId??string.Empty).Trim().ToLower();
  23. //2. Start with a complete list
  24. CDataList results = this;
  25. //3. Use any available index, such as those generated for fk/bool columns
  26. //Normal Case - non-unique index (e.g. foreign key)
  27. //if (int.MinValue != seriesId) results = results.GetBySeriesId(seriesId);
  28. //Special case - unique index (e.g. primary key)
  29. /*
  30. if (!string.IsNullOrEmpty(nameOrId))
  31. {
  32. int id;
  33. if (int.TryParse(nameOrId, out id))
  34. {
  35. CData obj = this.GetById(id);
  36. if (null != obj)
  37. {
  38. results = new CDataList(1);
  39. results.Add(obj);
  40. return results;
  41. }
  42. }
  43. }
  44. */
  45. //4. Exit early if remaining (non-index) filters are blank
  46. if (string.IsNullOrEmpty(nameOrId)) return results;
  47. //5. Manually search each record using custom match logic, building a shortlist
  48. CDataList shortList = new CDataList();
  49. foreach (CData i in results)
  50. if (Match(nameOrId, i))
  51. shortList.Add(i);
  52. return shortList;
  53. }
  54. //Manual Searching e.g for string-based columns i.e. anything not indexed (add more params if required)
  55. private bool Match(string name, CData obj)
  56. {
  57. if (!string.IsNullOrEmpty(name)) //Match any string column
  58. {
  59. return false; //If filter is active, reject any items that dont match
  60. }
  61. return true; //No active filters (should catch this in step #4)
  62. }
  63. #endregion
  64. #region Cloning
  65. public CDataList Clone(CDataSrc target) //, int parentId)
  66. {
  67. //No Transaction
  68. if (target is CDataSrcRemote)
  69. return Clone(target, null); //, parentId);
  70. //Transaction
  71. using (IDbConnection cn = target.Local.Connection())
  72. {
  73. IDbTransaction tx = cn.BeginTransaction();
  74. try
  75. {
  76. CDataList clone = Clone(target, tx); //, parentId);
  77. tx.Commit();
  78. return clone;
  79. }
  80. catch
  81. {
  82. tx.Rollback();
  83. throw;
  84. }
  85. }
  86. }
  87. public CDataList Clone(CDataSrc target, IDbTransaction txOrNull) //, int parentId)
  88. {
  89. CDataList list = new CDataList(this.Count);
  90. foreach (CData i in this)
  91. list.Add(i.Clone(target, txOrNull)); //, parentId)); *Child entities must reference the new parent
  92. return list;
  93. }
  94. #endregion
  95. #region Export to Csv
  96. //Web - Need to add a project reference to System.Web, or comment out these two methods
  97. public void ExportToCsv(HttpResponse response, string fileName, List<EData> columns, List<EDecision> decisions)
  98. {
  99. CDataSrc.ExportToCsv(response, fileName); //Standard response headers
  100. StreamWriter sw = new StreamWriter(response.OutputStream);
  101. ExportToCsv(sw, columns, decisions);
  102. sw.Flush();
  103. response.End();
  104. }
  105. //Non-web
  106. public void ExportToCsv(string filePath, List<EData> columns, List<EDecision> decisions)
  107. {
  108. StreamWriter sw = new StreamWriter(filePath);
  109. ExportToCsv(sw, columns, decisions);
  110. sw.Close();
  111. }
  112. //Logic
  113. protected void ExportToCsv(StreamWriter sw, List<EData> columns, List<EDecision> decisions)
  114. {
  115. List<string> headings = new List<string>(1 + columns.Count + decisions.Count);
  116. headings.Add("Date");
  117. foreach (EData i in columns)
  118. headings.Add(i.ToString());
  119. foreach (EDecision i in decisions)
  120. headings.Add(string.Concat(i, " (", CData.GetTooltip(i), ")"));
  121. CDataSrc.ExportToCsv(headings.ToArray(), sw);
  122. foreach (CData d in this)
  123. {
  124. List<object> data = new List<object>(1 + columns.Count + decisions.Count);
  125. data.Add(d.DataDate.ToString("d-MMM-yyyy"));
  126. foreach (EData i in columns)
  127. data.Add(d.GetData(i));
  128. foreach (EDecision i in decisions)
  129. data.Add(d.GetDecision(i));
  130. CDataSrc.ExportToCsv(data.ToArray(), sw);
  131. }
  132. }
  133. #endregion
  134. #region Custom
  135. public DateTime MinDate { get { return Count == 0 ? DateTime.MinValue : this[0].DataDate; } }
  136. public DateTime MaxDate { get { return Count == 0 ? DateTime.MinValue : this[Count - 1].DataDate; } }
  137. public TimeSpan TimeSpan { get { return Count == 0 ? TimeSpan.MinValue : MaxDate.AddDays(1).Subtract(MinDate); } }
  138. public int TotalDays { get { return (int)TimeSpan.TotalDays; } }
  139. #endregion
  140. #region Foreign-Key Indices (Subsets)
  141. //Index by DataSeriesId
  142. public CDataList GetBySeriesId(int seriesId)
  143. {
  144. CDataList temp = null;
  145. if (!IndexBySeriesId.TryGetValue(seriesId, out temp))
  146. {
  147. temp = new CDataList();
  148. IndexBySeriesId[seriesId] = temp;
  149. }
  150. return temp;
  151. }
  152. [NonSerialized]
  153. private Dictionary<int, CDataList> _indexBySeriesId;
  154. private Dictionary<int, CDataList> IndexBySeriesId
  155. {
  156. get
  157. {
  158. if (null == _indexBySeriesId)
  159. {
  160. Dictionary<int, CDataList> index = new Dictionary<int, CDataList>();
  161. CDataList temp = null;
  162. foreach (CData i in this)
  163. {
  164. if (!index.TryGetValue(i.DataSeriesId, out temp))
  165. {
  166. temp = new CDataList();
  167. index[i.DataSeriesId] = temp;
  168. }
  169. temp.Add(i);
  170. }
  171. _indexBySeriesId = index;
  172. foreach (CDataList i in index.Values)
  173. i.DoCalcs();
  174. }
  175. return _indexBySeriesId;
  176. }
  177. }
  178. #endregion
  179. #region Date Index
  180. public CData GetByDate(DateTime date)
  181. {
  182. CData c = null;
  183. IndexByDate.TryGetValue(date, out c);
  184. return c;
  185. }
  186. [NonSerialized]
  187. private Dictionary<DateTime, CData> _indexByDate;
  188. private Dictionary<DateTime, CData> IndexByDate
  189. {
  190. get
  191. {
  192. if (null != _indexByDate && _indexByDate.Count == this.Count)
  193. return _indexByDate;
  194. _indexByDate = new Dictionary<DateTime, CData>(this.Count);
  195. foreach (CData i in this)
  196. _indexByDate[i.DataDate] = i;
  197. return _indexByDate;
  198. }
  199. }
  200. #endregion
  201. #region Trading Simulation
  202. public void DoCalcs()
  203. {
  204. lock (this)
  205. {
  206. foreach (CData i in this)
  207. {
  208. i.ClearAllCalcs();
  209. i.Prev = Prev(i);
  210. i.Next = Next(i);
  211. if (null == i.Prev)
  212. i.Simulation = new CSimulation(i);
  213. else
  214. i.Simulation = new CSimulation(i.Prev.Simulation, i);
  215. }
  216. }
  217. }
  218. public CData Last { get { return 0 == Count ? null : this[this.Count - 1]; } }
  219. public CData Prev(CData d)
  220. {
  221. int index = this.IndexOf(d);
  222. if (-1 == index)
  223. index = this.IndexOf(this.GetById(d.DataId));
  224. if (0 == index)
  225. return null;
  226. return this[index - 1];
  227. }
  228. public CData Next(CData d)
  229. {
  230. int index = this.IndexOf(d);
  231. if (-1 == index)
  232. index = this.IndexOf(this.GetById(d.DataId));
  233. if (this.Count - 1 == index)
  234. return null;
  235. return this[index + 1];
  236. }
  237. public double SimulatedTotal { get { return null == Last ? CSimulation.LEVERAGE * CSimulation.START : this.Last.SimulatedTotal; } }
  238. public double SimulatedProfit { get { return SimulatedTotal - CSimulation.LEVERAGE * CSimulation.START; } }
  239. public double SimulatedReturns { get { return SimulatedProfit / CSimulation.START; } }
  240. public double AnnualisedReturns { get { return Math.Pow(1 + SimulatedReturns, 365.0 / TotalDays) - 1; } }
  241. public double ExposureAdjustedReturns { get { return AnnualisedReturns / (AverageExposure * CSimulation.LEVERAGE); } }
  242. private double _avgExp = double.NaN;
  243. public double AverageExposure
  244. {
  245. get
  246. {
  247. if (double.IsNaN(_avgExp))
  248. {
  249. double total = 0;
  250. foreach (CData i in this)
  251. total += i.Simulation.Exposure;
  252. _avgExp = total / Count;
  253. }
  254. return _avgExp;
  255. }
  256. }
  257. private double _maxExp = double.NaN;
  258. public double MaxExposure
  259. {
  260. get
  261. {
  262. if (double.IsNaN(_maxExp))
  263. {
  264. double max = 0;
  265. foreach (CData i in this)
  266. max = Math.Max(max, i.Simulation.Exposure);
  267. _maxExp = max;
  268. }
  269. return _maxExp;
  270. }
  271. }
  272. private double _sumClosing = double.NaN;
  273. public double SumClosing
  274. {
  275. get
  276. {
  277. if (double.IsNaN(_sumClosing))
  278. {
  279. double sum = 0;
  280. foreach (CData i in this)
  281. sum += i.DataClose;
  282. _sumClosing = sum;
  283. }
  284. return _sumClosing;
  285. }
  286. }
  287. private double _sumSquaresClosing = double.NaN;
  288. public double SumSquaresClosing
  289. {
  290. get
  291. {
  292. if (double.IsNaN(_sumSquaresClosing))
  293. {
  294. double sum = 0;
  295. foreach (CData i in this)
  296. sum += Math.Pow(i.DataClose, 2);
  297. _sumSquaresClosing = sum;
  298. }
  299. return _sumSquaresClosing;
  300. }
  301. }
  302. public double MeanClosing { get { return SumClosing / Count; } }
  303. public double VolatilityClosing { get { return (SumSquaresClosing / Count) - Math.Pow(MeanClosing, 2); } }
  304. public double StdDevClosing { get { return Math.Sqrt(VolatilityClosing); } }
  305. private int _wins = int.MinValue;
  306. private int _losses = int.MinValue;
  307. private int _flat = int.MinValue;
  308. public int Wins { get { if (int.MinValue == _wins) DoCount(); return _wins; } }
  309. public int Losses { get { if (int.MinValue == _losses)DoCount(); return _losses; } }
  310. public int Flat { get { if (int.MinValue == _flat) DoCount(); return _flat; } }
  311. public double WinsPercent { get { return (double)Wins / (double)Count; } }
  312. public double LossesPercent { get { return (double)Losses / (double)Count; } }
  313. public double FlatPercent { get { return (double)Flat / (double)Count; } }
  314. private void DoCount()
  315. {
  316. if (this.Count == 0)
  317. return;
  318. lock (this)
  319. {
  320. _wins = 0;
  321. _losses = 0;
  322. _flat = 0;
  323. foreach (CData i in this)
  324. if (double.IsNaN(i.Returns) || 0 == i.Returns)
  325. _flat += 1;
  326. else if (i.Returns > 0)
  327. _wins += 1;
  328. else
  329. _losses += 1;
  330. }
  331. }
  332. private double _low = double.NaN;
  333. private double _high = double.NaN;
  334. public double Low { get { if (double.IsNaN(_low)) DoHighLow(); return _low; } }
  335. public double High { get { if (double.IsNaN(_high)) DoHighLow(); return _high; } }
  336. private void DoHighLow()
  337. {
  338. if (this.Count == 0)
  339. return;
  340. lock (this)
  341. {
  342. _low = double.PositiveInfinity;
  343. _high = 0;
  344. foreach (CData i in this)
  345. if (_low > i.SimulatedTotal)
  346. _low = i.SimulatedTotal;
  347. else if (_high < i.SimulatedTotal)
  348. _high = i.SimulatedTotal;
  349. }
  350. }
  351. #endregion
  352. }
  353. }