public CapitalRequest(string email, TradeLink.AppKit.Results rs) : this(email, rs.ToString()) { SubmittedResults = rs; usingresults = true; result_symbols = rs.Symbols; result = System.Text.RegularExpressions.Regex.Replace(result, "Symbols:.*\n", string.Empty); Source = CapitalRequestSource.TradeLink; }
public CapitalRequest(string email, string results) { result = results; requestor_email = email; id = 0; requestor_id = string.Empty; viewers = new string[0]; result_dates = string.Empty; result_symbols = string.Empty; result_symdates = string.Empty; result_params = string.Empty; date = null; tag = string.Empty; result_source = string.Empty; requesttype = 0; usingresults = false; SubmittedResults = new Results(); Type = CapitalRequestType.Request; }
public void RoundTurnStat() { rt = new Results(); // get some trades Trade[] fills = new TradeImpl[] { // go long new TradeImpl(sym,p,s), // increase bet new TradeImpl(sym,p+inc,s*2), // take some profits new TradeImpl(sym,p+inc*2,s*-1), // go flat (round turn) new TradeImpl(sym,p+inc*2,s*-2), // go short new TradeImpl(sym,p,s*-2), // decrease bet new TradeImpl(sym,p,s), // exit (round turn) new TradeImpl(sym,p+inc,s), // do another entry new TradeImpl(sym,p,s) }; // compute results foreach (Trade fill in fills) rt.GotFill(fill); rt = rt.FetchResults(); // check trade count Assert.AreEqual(fills.Length, rt.Trades, "trade is missing from results"); // check round turn count Assert.AreEqual(2, rt.RoundTurns, "missing round turns"); // verify trade winners Assert.AreEqual(2, rt.Winners,"missing trade winner"); // verify round turn winners Assert.AreEqual(1, rt.RoundWinners, "missing round turn winners"); // verify round turn losers Assert.AreEqual(1, rt.RoundLosers, "missing round turn loser"); }
public static Results FetchResults(List<TradeResult> results, decimal RiskFreeRate, decimal CommissionPerContractShare, bool persymbol, DebugDelegate d) { try { List<Trade> fills = new List<Trade>(); foreach (TradeResult tr in results) fills.Add(tr.Source); List<decimal> _MIU = new List<decimal>(); List<decimal> _grossreturn = new List<decimal>(); List<decimal> _netreturns = new List<decimal>(); List<decimal> pctrets = new List<decimal>(); List<int> days = new List<int>(); //clear position tracker PositionTracker pt = new PositionTracker(results.Count); // setup new results Results r = new Results(); r.ResultsDateTime = Util.ToTLDateTime(); r.ComPerShare = CommissionPerContractShare; int consecWinners = 0; int consecLosers = 0; List<long> exitscounted = new List<long>(); decimal winpl = 0; decimal losepl = 0; Dictionary<string, int> tradecount = new Dictionary<string, int>(); List<decimal> negret = new List<decimal>(results.Count); decimal curcommiss = 0; for (int i = 0; i<results.Count; i++) { var tr = results[i]; if (tradecount.ContainsKey(tr.Source.symbol)) tradecount[tr.Source.symbol]++; else tradecount.Add(tr.Source.symbol, 1); if (!days.Contains(tr.Source.xdate)) days.Add(tr.Source.xdate); var pos = pt[tr.Source.symbol]; int usizebefore = pos.UnsignedSize; decimal pricebefore = pos.AvgPrice; var islongbefore = pos.isLong; var miubefore = pos.isFlat ? 0 : pos.UnsignedSize * pos.AvgPrice; decimal pospl = pt.Adjust(tr.Source); bool islong = pt[tr.Source.symbol].isLong; bool isroundturn = (usizebefore != 0) && (pt[tr.Source.symbol].UnsignedSize == 0); // get comissions curcommiss += Math.Abs(tr.Source.xsize) * CommissionPerContractShare; bool isclosing = pt[tr.Source.symbol].UnsignedSize<usizebefore; // calculate MIU and store on array var miu = pt[tr.Source.symbol].isFlat ? 0 : pt[tr.Source.symbol].AvgPrice * pt[tr.Source.symbol].UnsignedSize; if (miu!=0) _MIU.Add(miu); // get miu up to this point var maxmiu = _MIU.Count == 0 ? 0 : Math.Abs(Calc.Max(_MIU.ToArray())); // if we closed something, update return decimal grosspl = 0; if (isclosing) if (islongbefore) grosspl = (tr.Source.xprice - pricebefore) * Math.Abs(tr.Source.xsize); else grosspl = (pricebefore - tr.Source.xprice) * Math.Abs(tr.Source.xsize); decimal netpl = grosspl - (Math.Abs(tr.Source.xsize) * CommissionPerContractShare); // get p&l for portfolio curcommiss = 0; // count return _grossreturn.Add(grosspl); _netreturns.Add(netpl); // get pct return for portfolio decimal pctret = 0; if (miubefore == 0) pctret = netpl / miu; else pctret = netpl / miubefore; pctrets.Add(pctret); // if it is below our zero, count it as negative return if (pctret < 0) negret.Add(pctret); if (isroundturn) { r.RoundTurns++; if (pospl >= 0) r.RoundWinners++; else if (pospl < 0) r.RoundLosers++; } if (!r.Symbols.Contains(tr.Source.symbol)) r.Symbols += tr.Source.symbol + ","; r.Trades++; r.SharesTraded += Math.Abs(tr.Source.xsize); r.GrossPL += tr.ClosedPL; if ((tr.ClosedPL > 0) && !exitscounted.Contains(tr.Source.id)) { if (tr.Source.side) { r.SellWins++; r.SellPL += tr.ClosedPL; } else { r.BuyWins++; r.BuyPL += tr.ClosedPL; } if (tr.Source.id != 0) exitscounted.Add(tr.id); r.Winners++; consecWinners++; consecLosers = 0; } else if ((tr.ClosedPL < 0) && !exitscounted.Contains(tr.Source.id)) { if (tr.Source.side) { r.SellLosers++; r.SellPL += tr.ClosedPL; } else { r.BuyLosers++; r.BuyPL += tr.ClosedPL; } if (tr.Source.id != 0) exitscounted.Add(tr.id); r.Losers++; consecLosers++; consecWinners = 0; } if (tr.ClosedPL > 0) winpl += tr.ClosedPL; else if (tr.ClosedPL < 0) losepl += tr.ClosedPL; if (consecWinners > r.ConsecWin) r.ConsecWin = consecWinners; if (consecLosers > r.ConsecLose) r.ConsecLose = consecLosers; if ((tr.OpenSize == 0) && (tr.ClosedPL == 0)) r.Flats++; if (tr.ClosedPL > r.MaxWin) r.MaxWin = tr.ClosedPL; if (tr.ClosedPL < r.MaxLoss) r.MaxLoss = tr.ClosedPL; if (tr.OpenPL > r.MaxOpenWin) r.MaxOpenWin = tr.OpenPL; if (tr.OpenPL < r.MaxOpenLoss) r.MaxOpenLoss = tr.OpenPL; } if (r.Trades != 0) { r.AvgPerTrade = Math.Round((losepl + winpl) / r.Trades, 2); r.AvgLoser = r.Losers == 0 ? 0 : Math.Round(losepl / r.Losers, 2); r.AvgWin = r.Winners == 0 ? 0 : Math.Round(winpl / r.Winners, 2); r.MoneyInUse = Math.Round(Calc.Max(_MIU.ToArray()), 2); r.MaxPL = Math.Round(Calc.Max(_grossreturn.ToArray()), 2); r.MinPL = Math.Round(Calc.Min(_grossreturn.ToArray()), 2); r.MaxDD = Calc.MaxDDPct(fills); r.SymbolCount = pt.Count; r.DaysTraded = days.Count; r.GrossPerDay = Math.Round(r.GrossPL / days.Count, 2); r.GrossPerSymbol = Math.Round(r.GrossPL / pt.Count, 2); if (persymbol) { for (int i = 0; i < pt.Count; i++) { r.PerSymbolStats.Add(pt[i].symbol + ": " + tradecount[pt[i].symbol] + " for " + pt[i].ClosedPL.ToString("C2")); } } } else { r.MoneyInUse = 0; r.MaxPL = 0; r.MinPL = 0; r.MaxDD = 0; r.GrossPerDay = 0; r.GrossPerSymbol = 0; } r.PctReturns = pctrets.ToArray(); r.DollarReturns = _netreturns.ToArray(); r.NegPctReturns = negret.ToArray(); try { var fret = Calc.Avg(pctrets.ToArray()); if (pctrets.Count == 0) r.SharpeRatio = 0; else if (pctrets.Count == 1) r.SharpeRatio = Math.Round((fret- RiskFreeRate), 3); else r.SharpeRatio = Math.Round(Calc.SharpeRatio(fret, Calc.StdDev(pctrets.ToArray()), RiskFreeRate), 3); } catch (Exception ex) { if (d != null) d("sharpe error: " + ex.Message); } try { var fret = Calc.Avg(pctrets.ToArray()); if (pctrets.Count == 0) r.SortinoRatio = 0; else if (negret.Count == 1) r.SortinoRatio = (fret - RiskFreeRate) / negret[0]; else if ((negret.Count == 0)) r.SortinoRatio = fret - RiskFreeRate; else r.SortinoRatio = Math.Round(Calc.SortinoRatio(fret, Calc.StdDev(negret.ToArray()), RiskFreeRate ), 3); } catch (Exception ex) { if (d != null) d("sortino error: " + ex.Message); } return r; } catch (Exception ex) { if (d != null) d("error generting report: " + ex.Message + ex.StackTrace); return new Results(); } }
public static List<string> GetDecideable() { Results r = new Results(); List<string> dr = new List<string>(); foreach (var pi in r.GetType().GetProperties()) { if (!pi.GetAccessors()[0].IsPublic) continue; var pt = pi.PropertyType; if ((pt == typeof(decimal)) || (pt == typeof(int))) dr.Add(pi.Name); } foreach (var pi in r.GetType().GetFields()) { if (!pi.IsPublic) continue; var pt = pi.FieldType; if ((pt == typeof(decimal)) || (pt == typeof(int))) dr.Add(pi.Name); } var tmp = dr.ToArray(); Array.Sort(tmp); return new List<string>(tmp); }
public static Results FetchResults(List<TradeResult> results, decimal RiskFreeRate, decimal CommissionPerContractShare, bool persymbol, DebugDelegate d) { try { List<Trade> fills = new List<Trade>(); foreach (TradeResult tr in results) fills.Add(tr.Source); List<decimal> _MIU = new List<decimal>(); List<decimal> _return = new List<decimal>(); List<int> days = new List<int>(); //clear position tracker PositionTracker pt = new PositionTracker(results.Count); // setup new results Results r = new Results(); r.ResultsDateTime = Util.ToTLDate() * 1000000 + Util.ToTLTime(); r.ComPerShare = CommissionPerContractShare; r.RiskFreeRet = string.Format("{0:P2}", RiskFreeRate); int consecWinners = 0; int consecLosers = 0; List<long> exitscounted = new List<long>(); decimal winpl = 0; decimal losepl = 0; Dictionary<string, int> tradecount = new Dictionary<string, int>(); List<decimal> negret = new List<decimal>(results.Count); foreach (TradeResult tr in results) { if (tradecount.ContainsKey(tr.Source.symbol)) tradecount[tr.Source.symbol]++; else tradecount.Add(tr.Source.symbol, 1); if (!days.Contains(tr.Source.xdate)) days.Add(tr.Source.xdate); int usizebefore = pt[tr.Source.symbol].UnsignedSize; pt.Adjust(tr.Source); bool isclosing = pt[tr.Source.symbol].UnsignedSize<usizebefore; // calculate MIU and store on array decimal miu = Calc.Sum(Calc.MoneyInUse(pt)); if (miu!=0) _MIU.Add(miu); // if we closed something, update return if (isclosing) { // get p&l for portfolio decimal pl = Calc.Sum(Calc.AbsoluteReturn(pt)); // count return _return.Add(pl); // get pct return for portfolio decimal pctret = _MIU[_MIU.Count - 1] == 0 ? 0 : pl / _MIU[_MIU.Count - 1]; // if it is below our zero, count it as negative return if (pctret < 0) negret.Add(pl); } if (!r.Symbols.Contains(tr.Source.symbol)) r.Symbols += tr.Source.symbol + ","; r.Trades++; r.SharesTraded += Math.Abs(tr.Source.xsize); r.GrossPL += tr.ClosedPL; if ((tr.ClosedPL > 0) && !exitscounted.Contains(tr.Source.id)) { if (tr.Source.side) { r.SellWins++; r.SellPL += tr.ClosedPL; } else { r.BuyWins++; r.BuyPL += tr.ClosedPL; } if (tr.Source.id != 0) exitscounted.Add(tr.id); r.Winners++; consecWinners++; consecLosers = 0; } else if ((tr.ClosedPL < 0) && !exitscounted.Contains(tr.Source.id)) { if (tr.Source.side) { r.SellLosers++; r.SellPL += tr.ClosedPL; } else { r.BuyLosers++; r.BuyPL += tr.ClosedPL; } if (tr.Source.id != 0) exitscounted.Add(tr.id); r.Losers++; consecLosers++; consecWinners = 0; } if (tr.ClosedPL > 0) winpl += tr.ClosedPL; else if (tr.ClosedPL < 0) losepl += tr.ClosedPL; if (consecWinners > r.ConsecWin) r.ConsecWin = consecWinners; if (consecLosers > r.ConsecLose) r.ConsecLose = consecLosers; if ((tr.OpenSize == 0) && (tr.ClosedPL == 0)) r.Flats++; if (tr.ClosedPL > r.MaxWin) r.MaxWin = tr.ClosedPL; if (tr.ClosedPL < r.MaxLoss) r.MaxLoss = tr.ClosedPL; if (tr.OpenPL > r.MaxOpenWin) r.MaxOpenWin = tr.OpenPL; if (tr.OpenPL < r.MaxOpenLoss) r.MaxOpenLoss = tr.OpenPL; } if (r.Trades != 0) { r.AvgPerTrade = Math.Round((losepl + winpl) / r.Trades, 2); r.AvgLoser = r.Losers == 0 ? 0 : Math.Round(losepl / r.Losers, 2); r.AvgWin = r.Winners == 0 ? 0 : Math.Round(winpl / r.Winners, 2); r.MoneyInUse = Math.Round(Calc.Max(_MIU.ToArray()), 2); r.MaxPL = Math.Round(Calc.Max(_return.ToArray()), 2); r.MinPL = Math.Round(Calc.Min(_return.ToArray()), 2); r.MaxDD = string.Format("{0:P1}", Calc.MaxDDPct(fills)); r.SymbolCount = pt.Count; r.DaysTraded = days.Count; r.GrossPerDay = Math.Round(r.GrossPL / days.Count, 2); r.GrossPerSymbol = Math.Round(r.GrossPL / pt.Count, 2); if (persymbol) { for (int i = 0; i < pt.Count; i++) { r.PerSymbolStats.Add(pt[i].Symbol + ": " + tradecount[pt[i].Symbol] + " for " + pt[i].ClosedPL.ToString("C2")); } } } else { r.MoneyInUse = 0; r.MaxPL = 0; r.MinPL = 0; r.MaxDD = "0"; r.GrossPerDay = 0; r.GrossPerSymbol = 0; } try { r.SharpeRatio = _return.Count < 2 ? 0 : Math.Round(Calc.SharpeRatio(_return[_return.Count - 1], Calc.StdDev(_return.ToArray()), (RiskFreeRate*r.MoneyInUse)), 3); } catch (Exception ex) { if (d != null) d("sharp error: " + ex.Message); } try { if (_return.Count == 0) r.SortinoRatio = 0; else if (negret.Count == 1) r.SortinoRatio = 0; else if ((negret.Count == 0) && (_return[_return.Count - 1] == 0)) r.SortinoRatio = 0; else if ((negret.Count == 0) && (_return[_return.Count - 1] > 0)) r.SortinoRatio = decimal.MaxValue; else if ((negret.Count == 0) && (_return[_return.Count - 1] < 0)) r.SortinoRatio = decimal.MinValue; else r.SortinoRatio = Math.Round(Calc.SortinoRatio(_return[_return.Count - 1], Calc.StdDev(negret.ToArray()), (RiskFreeRate * r.MoneyInUse)), 3); } catch (Exception ex) { if (d != null) d("sortino error: " + ex.Message); } return r; } catch (Exception ex) { if (d != null) d("error generting report: " + ex.Message + ex.StackTrace); return new Results(); } }
public static bool ResultsSubmittable(Results rs) { bool ok = (rs.GrossPL - (rs.ComPerShare * rs.Trades) > 0) && (rs.Trades > 1) && (rs.DaysTraded + rs.SymbolCount > 2); return ok; }
void DisplayResults(Results r) { CurrentResults = r; dt.BeginLoadData(); dt.Clear(); Type t = r.GetType(); FieldInfo[] fis = t.GetFields(); foreach (FieldInfo fi in fis) { string format = null; if (fi.GetType() == typeof(Decimal)) format = "N2"; dt.Rows.Add(fi.Name, (format != null) ? string.Format(format, fi.GetValue(r)) : fi.GetValue(r).ToString()); } PropertyInfo[] pis = t.GetProperties(); foreach (PropertyInfo pi in pis) { string format = null; if (pi.GetType() == typeof(Decimal)) format = "N2"; dt.Rows.Add(pi.Name, (format != null) ? string.Format(format, pi.GetValue(r, null)) : pi.GetValue(r, null).ToString()); } foreach (string ps in r.PerSymbolStats) { string[] rs= ps.Split(':'); if (rs.Length != 2) continue; dt.Rows.Add(rs[0], rs[1]); } dt.EndLoadData(); refreshgrid(); }
public static Results FetchResults(List <TradeResult> results, decimal RiskFreeRate, decimal CommissionPerContractShare, bool persymbol, DebugDelegate d) { try { List <Trade> fills = new List <Trade>(); foreach (TradeResult tr in results) { fills.Add(tr.Source); } List <decimal> _MIU = new List <decimal>(); List <decimal> _return = new List <decimal>(); List <int> days = new List <int>(); //clear position tracker PositionTracker pt = new PositionTracker(results.Count); // setup new results Results r = new Results(); r.ResultsDateTime = Util.ToTLDateTime(); r.ComPerShare = CommissionPerContractShare; r.RiskFreeRet = string.Format("{0:P2}", RiskFreeRate); int consecWinners = 0; int consecLosers = 0; List <long> exitscounted = new List <long>(); decimal winpl = 0; decimal losepl = 0; Dictionary <string, int> tradecount = new Dictionary <string, int>(); List <decimal> negret = new List <decimal>(results.Count); foreach (TradeResult tr in results) { if (tradecount.ContainsKey(tr.Source.symbol)) { tradecount[tr.Source.symbol]++; } else { tradecount.Add(tr.Source.symbol, 1); } if (!days.Contains(tr.Source.xdate)) { days.Add(tr.Source.xdate); } int usizebefore = pt[tr.Source.symbol].UnsignedSize; decimal pospl = pt.Adjust(tr.Source); bool isroundturn = (usizebefore != 0) && (pt[tr.Source.symbol].UnsignedSize == 0); bool isclosing = pt[tr.Source.symbol].UnsignedSize < usizebefore; // calculate MIU and store on array decimal miu = Calc.Sum(Calc.MoneyInUse(pt)); if (miu != 0) { _MIU.Add(miu); } // if we closed something, update return if (isclosing) { // get p&l for portfolio decimal pl = Calc.Sum(Calc.AbsoluteReturn(pt)); // count return _return.Add(pl); // get pct return for portfolio decimal pctret = _MIU[_MIU.Count - 1] == 0 ? 0 : pl / _MIU[_MIU.Count - 1]; // if it is below our zero, count it as negative return if (pctret < 0) { negret.Add(pl); } } if (isroundturn) { r.RoundTurns++; if (pospl >= 0) { r.RoundWinners++; } else if (pospl < 0) { r.RoundLosers++; } } if (!r.Symbols.Contains(tr.Source.symbol)) { r.Symbols += tr.Source.symbol + ","; } r.Trades++; r.SharesTraded += Math.Abs(tr.Source.xsize); r.GrossPL += tr.ClosedPL; if ((tr.ClosedPL > 0) && !exitscounted.Contains(tr.Source.id)) { if (tr.Source.side) { r.SellWins++; r.SellPL += tr.ClosedPL; } else { r.BuyWins++; r.BuyPL += tr.ClosedPL; } if (tr.Source.id != 0) { exitscounted.Add(tr.id); } r.Winners++; consecWinners++; consecLosers = 0; } else if ((tr.ClosedPL < 0) && !exitscounted.Contains(tr.Source.id)) { if (tr.Source.side) { r.SellLosers++; r.SellPL += tr.ClosedPL; } else { r.BuyLosers++; r.BuyPL += tr.ClosedPL; } if (tr.Source.id != 0) { exitscounted.Add(tr.id); } r.Losers++; consecLosers++; consecWinners = 0; } if (tr.ClosedPL > 0) { winpl += tr.ClosedPL; } else if (tr.ClosedPL < 0) { losepl += tr.ClosedPL; } if (consecWinners > r.ConsecWin) { r.ConsecWin = consecWinners; } if (consecLosers > r.ConsecLose) { r.ConsecLose = consecLosers; } if ((tr.OpenSize == 0) && (tr.ClosedPL == 0)) { r.Flats++; } if (tr.ClosedPL > r.MaxWin) { r.MaxWin = tr.ClosedPL; } if (tr.ClosedPL < r.MaxLoss) { r.MaxLoss = tr.ClosedPL; } if (tr.OpenPL > r.MaxOpenWin) { r.MaxOpenWin = tr.OpenPL; } if (tr.OpenPL < r.MaxOpenLoss) { r.MaxOpenLoss = tr.OpenPL; } } if (r.Trades != 0) { r.AvgPerTrade = Math.Round((losepl + winpl) / r.Trades, 2); r.AvgLoser = r.Losers == 0 ? 0 : Math.Round(losepl / r.Losers, 2); r.AvgWin = r.Winners == 0 ? 0 : Math.Round(winpl / r.Winners, 2); r.MoneyInUse = Math.Round(Calc.Max(_MIU.ToArray()), 2); r.MaxPL = Math.Round(Calc.Max(_return.ToArray()), 2); r.MinPL = Math.Round(Calc.Min(_return.ToArray()), 2); r.MaxDD = string.Format("{0:P2}", Calc.MaxDDPct(fills)); r.SymbolCount = pt.Count; r.DaysTraded = days.Count; r.GrossPerDay = Math.Round(r.GrossPL / days.Count, 2); r.GrossPerSymbol = Math.Round(r.GrossPL / pt.Count, 2); if (persymbol) { for (int i = 0; i < pt.Count; i++) { r.PerSymbolStats.Add(pt[i].Symbol + ": " + tradecount[pt[i].Symbol] + " for " + pt[i].ClosedPL.ToString("C2")); } } } else { r.MoneyInUse = 0; r.MaxPL = 0; r.MinPL = 0; r.MaxDD = "0"; r.GrossPerDay = 0; r.GrossPerSymbol = 0; } try { r.SharpeRatio = _return.Count < 2 ? 0 : Math.Round(Calc.SharpeRatio(_return[_return.Count - 1], Calc.StdDev(_return.ToArray()), (RiskFreeRate * r.MoneyInUse)), 3); } catch (Exception ex) { if (d != null) { d("sharpe error: " + ex.Message); } } try { if (_return.Count == 0) { r.SortinoRatio = 0; } else if (negret.Count == 1) { r.SortinoRatio = 0; } else if ((negret.Count == 0) && (_return[_return.Count - 1] == 0)) { r.SortinoRatio = 0; } else if ((negret.Count == 0) && (_return[_return.Count - 1] > 0)) { r.SortinoRatio = decimal.MaxValue; } else if ((negret.Count == 0) && (_return[_return.Count - 1] < 0)) { r.SortinoRatio = decimal.MinValue; } else { r.SortinoRatio = Math.Round(Calc.SortinoRatio(_return[_return.Count - 1], Calc.StdDev(negret.ToArray()), (RiskFreeRate * r.MoneyInUse)), 3); } } catch (Exception ex) { if (d != null) { d("sortino error: " + ex.Message); } } return(r); } catch (Exception ex) { if (d != null) { d("error generting report: " + ex.Message + ex.StackTrace); } return(new Results()); } }
public static bool ResultsSubmittable(Results rs) { bool ok = (rs.GrossPL - (rs.ComPerShare * rs.Trades) > 0) && (rs.Trades > 1) && (rs.DaysTraded + rs.SymbolCount > 2); return(ok); }