| Overall Statistics |
|
Total Trades 24 Average Win 0.09% Average Loss -0.02% Compounding Annual Return -17.276% Drawdown 0.200% Expectancy -0.135 Net Profit -0.035% Sharpe Ratio 0 Loss Rate 83% Win Rate 17% Profit-Loss Ratio 4.19 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $27.16 |
using System.Collections.Generic;
using NodaTime;
using QuantConnect.Data;
using QuantConnect.Data.Custom;
namespace QuantConnect.Algorithm.Examples
{
public enum TradingState
{
OutOfMarket = 0,
PendingOrderEnter = 1,
PendingOrderEnterCancelationSent = 2,
PendingOrderExit = 3,
PendingOrderExitCancelationSent = 4,
InMarket = 5
};
public class Arbitrator : QCAlgorithm
{
bool printNextBar = false;
decimal BiDirectionalIBFees = 0;
decimal entryPortfolioValue = 0;
decimal myCurrentSpread=0;
decimal minGain = 0.3m; // not used
decimal PortfolioInvestFraction=0.4m;
decimal minSpreadToEnter = 0.25m; // for entry
decimal FeeMultiplier = 4; // for exit
int PendingOrderWaitSec = 1*60;
OrderTicket order1 = null;
OrderTicket order2 = null;
int MyShares1, MyShares2;
DateTime tradingTime;
TradingState tradingState = TradingState.OutOfMarket;
decimal entrySpread = 0;
Resolution resolution = Resolution.Second;
string baseSymbol = "SPY";
TradeBar baseBar = new TradeBar();
List<string> namePair = new List<string>()
{
"TYD", "DRN"
};
List<decimal> spreadPair = new List<decimal>
{
0.001m, 0.02m
};
List<TradeBar> barPairNow = new List<TradeBar>()
{
new TradeBar(), new TradeBar()
};
List<TradeBar> barPairPrev = new List<TradeBar>()
{
new TradeBar(), new TradeBar()
};
public override void Initialize()
{
SetStartDate(2018, 9, 17); // 2012, 3, 10
SetEndDate(2018, 9, 17);
SetCash(1000*20);
AddSecurity(SecurityType.Equity, namePair[0], resolution);
Securities[namePair[0]].TransactionModel = new MyTransactionModel( spreadPair[0], this);
AddSecurity(SecurityType.Equity, namePair[1], resolution);
Securities[namePair[1]].TransactionModel = new MyTransactionModel(spreadPair[1], this);
AddSecurity(SecurityType.Equity, baseSymbol, resolution);
Securities[baseSymbol].TransactionModel = new MyTransactionModel(0.0m, this); // spy 0.01%
barPairPrev[0].Close = 88.90m;
barPairPrev[1].Close = 25.94m;
barPairNow[0].Close = 88.90m;
barPairNow[1].Close = 25.94m;
} // Initalize
public void OnData(TradeBars data)
{
TradeBar temp1 = null;
TradeBar temp2 = null;
data.TryGetValue(namePair[0], out temp1);
data.TryGetValue(namePair[1], out temp2);
if ( temp1 != null && temp2 != null)
{
if ( Time.Hour == 15 && Time.Minute == 59 && Time.Second == 59 )
{
// get the closing amount
barPairPrev[0] = temp1;
barPairPrev[1] = temp2;
}
else
{
barPairNow[0] = temp1;
barPairNow[1] = temp2;
} // else
if ( barPairNow[0].Close>0 && barPairNow[1].Close>0
&& barPairPrev[0].Close>0 && barPairPrev[1].Close>0
)
{
if ( printNextBar==true )
{
Console.WriteLine( "{0}, barPairNow[0]={1:F3}, high={2:F3}, low={3:F3}, vol={4:F3}", Time, barPairNow[0].Close, barPairNow[0].High, barPairNow[0].Low, barPairNow[0].Volume );
Console.WriteLine( "{0}, barPairNow[1]={1:F3}, high={2:F3}, low={3:F3}, vol={4:F3}", Time, barPairNow[1].Close, barPairNow[1].High, barPairNow[1].Low, barPairNow[1].Volume );
printNextBar = false;
}
ProcessBar();
}
}// if
else
{
if ( temp1 == null)
Console.WriteLine("{0} temp1 is null - {1}", Time, namePair[0]);
if ( temp2 == null)
Console.WriteLine("{0} temp2 is null - {1}", Time, namePair[1]);
}
} // OnData
private int CalculateQuantity( decimal price, decimal portfolioFraction)
{
decimal Money = portfolioFraction * Portfolio.TotalPortfolioValue;
decimal entryPrice = price;
int rawShares = (int) (Money/ entryPrice );
decimal IBFee = 0.005m*rawShares;
BiDirectionalIBFees += 2*IBFee;
int rtn = (int) ((Money -IBFee - 100)/entryPrice);
return rtn;
}
private void HandleState_InMarket()
{
if ( IsExit(barPairNow, barPairPrev, minGain, out myCurrentSpread, entrySpread) )
{
decimal finalExitPrice1 = barPairNow[0].Close +0.01m;// - spreadPair[0]/2;
if ( MyShares1 >= 1)
{
order1 = LimitOrder(namePair[0], -MyShares1, Math.Round(finalExitPrice1,2) );
Console.WriteLine( "{0} EXIT order1 sent, .status={1}, limit= {2:F3}, curPrice={3:F3}, high={4:F3},low={5:F3}, vol={6:F3} ",
Time, order1.Status,finalExitPrice1, barPairNow[0].Close, barPairNow[0].High, barPairNow[0].Low, barPairNow[0].Volume);
}
decimal finalExitPrice2 = barPairNow[1].Close - spreadPair[1]/2;
if ( MyShares1 >= 1)
{
order2 = LimitOrder(namePair[1], -MyShares2, Math.Round(finalExitPrice2,2) );
Console.WriteLine( "{0} EXIT order2 sent, .status={1}, limit= {2:F3}, curPrice={3:F3}, high={4:F3},low={5:F3}, vol={6:F3}",
Time, order1.Status,finalExitPrice2, barPairNow[1].Close, barPairNow[1].High, barPairNow[1].Low, barPairNow[1].Volume);
}
MyShares1 = MyShares2 = 0;
Console.WriteLine( "{0} Exit orders sent ", Time);
printNextBar = true;
Console.WriteLine("{0}, Will print next bar", Time);
tradingState = TradingState.PendingOrderExit;
entryPortfolioValue = 0;
} // if
}
private void HandleSTate_OutOfMrket()
{
decimal curSpread = 0;
if ( IsEntry( barPairNow, barPairPrev, minSpreadToEnter, out curSpread ) )
{
try
{
entrySpread = curSpread;
tradingState = TradingState.PendingOrderEnter;
tradingTime = Time;
decimal entryPrice1 = barPairNow[0].Close + 0.02m;
MyShares1 = CalculateQuantity( entryPrice1 , 0.3m);
decimal finalEntryPrice1 = Math.Round(entryPrice1,2);
if ( MyShares1 > 0)
{
order1 = LimitOrder(namePair[0], MyShares1, finalEntryPrice1 );
Console.WriteLine( "{0} BUY order1 sent, .status={1}, limit= {2:F3}, curPrice={3:F3}, high={4:F3},low={5:F3}, vol={6:F3}",
Time, order1.Status,finalEntryPrice1,barPairNow[0].Close, barPairNow[0].High, barPairNow[0].Low, barPairNow[0].Volume);
}
else
{
//Console.WriteLine("{0}, Bad shares = {1}, price = {2}", Time, MyShares1, barPairNow[0].Close);
order1 = null;
}
decimal entryPrice2 = barPairNow[1].Close + 0.02m;
MyShares2 = CalculateQuantity( entryPrice2, 0.3m );
decimal finalEntryPrice2 = Math.Round(entryPrice2,2);
if ( MyShares2 > 0)
{
order2 = LimitOrder(namePair[1], MyShares2, finalEntryPrice2 );
Console.WriteLine( "{0} BUY order2 sent, .status={1}, limit= {2:F3}, curPrice={3:F3}, high={4:F3},low={5:F3}, vol={6:F3}",
Time, order2.Status, finalEntryPrice2, barPairNow[1].Close, barPairNow[1].High, barPairNow[1].Low, barPairNow[1].Volume);
}
else
{
//Console.WriteLine("{0}, Bad shares = {1}, price = {2}", Time, MyShares2, barPairNow[1].Close);
order2 = null;
}
printNextBar = true;
Console.WriteLine("{0}, Will print next bar", Time);
entryPortfolioValue = Portfolio.TotalPortfolioValue;
}
catch( Exception e)
{
Console.WriteLine( "{0} Exception(HandleSTate_OutOfMrket)=> {1} ", Time, e.Message);
}
} // IsEntry is true
}
private void HandleState_PendingOrderEnter()
{
if ( order1!=null && order1.Status == OrderStatus.Filled
&& order2!=null && order2.Status == OrderStatus.Filled
)
{
tradingState = TradingState.InMarket;
tradingTime = Time;
Console.WriteLine( "{0} Entry Orders Executed , order1.FilledPrice={1}, order2.FilledProce={2}"
, Time, order1.AverageFillPrice, order2.AverageFillPrice );
}
else
if ( (Time-tradingTime).TotalSeconds >=PendingOrderWaitSec || Time.Hour==15 && Time.Minute>=59 )
{
if (order1!=null && order1.Status != OrderStatus.Filled && order1.Status != OrderStatus.PartiallyFilled)
{
order1.Cancel("entry order1 canceled " + Time.ToString());
//Console.WriteLine( "{0} entry order1 canceled", Time);
}
if (order2!=null && order2.Status != OrderStatus.Filled && order2.Status != OrderStatus.PartiallyFilled)
{
order2.Cancel("entry order2 canceled " + Time.ToString() );
//Console.WriteLine( "{0} entry order2 canceled", Time);
}
Console.WriteLine( "{0} \t PendingOrderEnterCancelationSent", Time);
tradingState = TradingState.PendingOrderEnterCancelationSent;
tradingTime = Time;
} // if
}
private void HandleState_PendingOrderEnterCancelationSent()
{
MyShares1 = MyShares2 = 0;
Liquidate();
Console.WriteLine( "{0} \t HandleState_PendingOrderEnterCancelationSent - Liquidated ALL entry orders if any", Time);
tradingState = TradingState.OutOfMarket;
tradingTime = Time;
}
private void HandleState_PendingOrderExit()
{
if ( order1!=null && order1.Status == OrderStatus.Filled
&& order2!=null && order2.Status == OrderStatus.Filled
)
{
tradingState = TradingState.OutOfMarket;
tradingTime = Time;
Console.WriteLine( "{0} EXIT Orders Executed , order1.FilledPrice={1}, order2.FilledProce={2}"
, Time, order1.AverageFillPrice, order2.AverageFillPrice );
}
else
if ( (Time-tradingTime).TotalSeconds >=PendingOrderWaitSec || Time.Hour==15 && Time.Minute>=59)
{
if (order1!=null && order1.Status != OrderStatus.Filled && order1.Status != OrderStatus.PartiallyFilled)
{
order1.Cancel("exit order1 canceled " + Time.ToString());
Console.WriteLine( "{0} exit order1 canceled", Time);
}
if (order2!=null && order2.Status != OrderStatus.Filled && order2.Status != OrderStatus.PartiallyFilled)
{
order2.Cancel("exit order2 canceled " + Time.ToString());
Console.WriteLine( "{0} exit order2 canceled", Time);
}
tradingState = TradingState.PendingOrderExitCancelationSent;
tradingTime = Time;
} // if
}
private void HandleState_PendingOrderExitCancelationSent()
{
MyShares1 = MyShares2 = 0;
Liquidate();
Console.WriteLine( "{0} \t HandleState_PendingOrderExitCancelationSent - Liquidated ALL exit orders if any", Time);
tradingState = TradingState.OutOfMarket;
tradingTime = Time;
}
private void ProcessBar()
{
try
{
switch( tradingState )
{
case TradingState.OutOfMarket:
HandleSTate_OutOfMrket();
break;
case TradingState.PendingOrderEnter:
HandleState_PendingOrderEnter();
break;
case TradingState.PendingOrderEnterCancelationSent:
HandleState_PendingOrderEnterCancelationSent();
break;
case TradingState.PendingOrderExit:
HandleState_PendingOrderExit();
break;
case TradingState.PendingOrderExitCancelationSent:
HandleState_PendingOrderExitCancelationSent();
break;
case TradingState.InMarket:
HandleState_InMarket();
break;
} // switch
}
catch (Exception ex)
{
Error("Liquidate-all, Algorithm->ProcessBar: " + ex.Message + "\r\n\r\n" + ex.StackTrace);
// reset everything
Liquidate();
MyShares1 = MyShares2 = 0;
order1 = order2 = null;
tradingTime = Time;
tradingState = TradingState.OutOfMarket;
}
} // ProcessBar
bool IsEntry( List<TradeBar> pairNow, List<TradeBar> pairPrev, decimal minSpread, out decimal spread)
{
spread = 0;
bool rtn = false;
if ( Time.Minute == 15 && tradingState == TradingState.OutOfMarket)
{
rtn = true;
}
return rtn;
} // IsEntry
bool IsExit( List<TradeBar> pairNow, List<TradeBar> pairPrev, decimal minGain, out decimal myCurrentSpread, decimal myEntrySpread)
{
bool rtn = false;
myCurrentSpread = 0;
if ( Time.Hour==15 && Time.Minute==58 && tradingState == TradingState.InMarket )
{
rtn = true;
}
if ( rtn==false && Time.Minute == 33 && tradingState == TradingState.InMarket )
{
rtn = true;
} // if
return rtn;
} // IsEntry
} // class
} // namespacenamespace QuantConnect.Algorithm.Examples
{
public class TrailingStop
{
public decimal TrailingStopValue {get;set;}
decimal TrailingStopPercent{get;set;}
bool IsLong {get;set;}
public TrailingStop ( decimal stopValue, decimal stopPercent, bool isLongEntry )
{
TrailingStopValue = stopValue;
TrailingStopPercent = stopPercent;
IsLong = isLongEntry;
}
public bool IsTrailingExit( TradeBar b, out decimal exitPrice)
{
bool rtn = false;
exitPrice = 0;
if ( IsLong == true)
{
if ( b.Close / TrailingStopValue < 1-TrailingStopPercent/100)
{
exitPrice = b.Close;
rtn = true;
}
}
else
{
// short
if ( b.Close / TrailingStopValue > 1+TrailingStopPercent/100 )
{
exitPrice = b.Close;
rtn = true;
}
}
// update Trailing stop if needed
if ( rtn != true)
{
if ( IsLong == true && b.Close > TrailingStopValue)
TrailingStopValue = b.Close;
if ( IsLong == false && b.Close < TrailingStopValue)
TrailingStopValue = b.Close;
}
return rtn;
} // IsTrailingExit
} // TrailingStop
}namespace QuantConnect
{
/*
,
UXI, (SIJ): 2009-2-1 - only UXI actually
Total Trades1650
Average Win1.85%
Average Loss-0.53%
Compounding Annual Return 113.286%
Drawdown 7.700%
Expectancy1.626
Net Profit103129.908%
Sharpe Ratio 4.031
Loss Rate41%
Win Rate59%
Profit-Loss Ratio 3.49
Alpha0.525
Beta6.788
Annual Standard Deviation0.158
Annual Variance0.025
Information Ratio3.927
Tracking Error0.158
Treynor Ratio0.094
VMIN 2016-5-2, 2.59/2.60 but low volume and Size=1
TVIX - 11/29/2010 (market down) bid/ask 9.92/9.93,
URTY, SRTY: 2010-2-20
Total Trades2628
Average Win1.84%
Average Loss-1.16%
Compounding Annual Return 72.684%
Drawdown 21.800%
Expectancy0.312
Net Profit8294.308%
Sharpe Ratio 1.925
Loss Rate49%
Win Rate51%
Profit-Loss Ratio1.58
Alpha0.456
Beta1.545
Annual Standard Deviation0.25
Annual Variance0.062
Information Ratio1.859
TNA, TZA (Small Cap)
Total Trades2974
Average Win2.03%
Average Loss-1.28%
Compounding Annual Return 67.088%
Drawdown 26.500%
Expectancy0.271
Net Profit10913.068%
Sharpe Ratio 1.674
Loss Rate51%
Win Rate49%
Profit-Loss Ratio1.59
Alpha0.41
Beta3.069
Annual Standard Deviation0.275
Annual Variance0.076
Information Ratio1.614
Tracking Error0.275
Treynor Ratio0.15
UPRO, SPXU (S&P 500 etfs)
Total Trades2822
Average Win1.33%
Average Loss-0.80%
Compounding Annual Return 37.313%
Drawdown 12.900%
Expectancy0.274
Net Profit1725.062%
Sharpe Ratio 1.614
Loss Rate52%
Win Rate48%
Profit-Loss Ratio1.67
Alpha0.423
Beta-8.926
Annual Standard Deviation0.171
Annual Variance0.029
Information Ratio1.518
Tracking Error0.171
Treynor Ratio-0.031
UBIO, ZBIO (Biotech): 2015-5-10
Total Trades928
Average Win2.36%
Average Loss-1.77%
Compounding Annual Return 71.381%
Drawdown 29.500%
Expectancy0.213
Net Profit374.516%
Sharpe Ratio 1.515
Loss Rate48%
Win Rate52%
Profit-Loss Ratio1.34
Alpha0.486
Beta0.721
Annual Standard Deviation0.328
Annual Variance0.108
Information Ratio1.465
TQQQ, SQQQ
Total Trades2632
Average Win1.56%
Average Loss-0.96%
Compounding Annual Return 36.082%
Drawdown 14.400%
Expectancy0.241
Net Profit1580.533%
Sharpe Ratio 1.435
Loss Rate53%
Win Rate 47%
Profit-Loss Ratio1.63
Alpha0.279
Beta-0.465
Annual Standard Deviation 0.189
UDOW, SDOW
Total Trades2632
Average Win1.20%
Average Loss-0.74%
Compounding Annual Return 30.606%
Drawdown 15.900%
Expectancy0.267
Net Profit1053.665%
Sharpe Ratio 1.574
Loss Rate52%
Win Rate 48%
Profit-Loss Ratio1.64
Alpha0.472
Beta-14.679
Annual Standard Deviation 0.147
Annual Variance 0.021
Information Ratio1.461
Tracking Error0.147
Treynor Ratio-0.016
-------------2x leveraged -------------
UWM, TWM (Russel 2000)
Total Trades2978
Average Win1.39%
Average Loss-0.85%
Compounding Annual Return 45.887%
Drawdown 19.100%
Expectancy0.289
Net Profit3081.668%
Sharpe Ratio 1.769
Loss Rate51%
Win Rate49%
Profit-Loss Ratio1.63
Alpha0.281
Beta2.875
Annual Standard Deviation0.186
Annual Variance0.034
Information Ratio1.68
SSO, SDS
Total Trades2978
Average Win0.93%
Average Loss-0.58%
Compounding Annual Return 25.242%
Drawdown 9.800%
Expectancy0.250
Net Profit686.193%
Sharpe Ratio 1.507
Loss Rate52%
Win Rate48%
Profit-Loss Ratio1.60
Alpha0.241
Beta-2.889
Annual Standard Deviation0.129
Annual Variance0.017
Information Ratio1.379
QLD, QID -
Total Trades2978
Average Win1.15%
Average Loss-0.71%
Compounding Annual Return 23.397%
Drawdown 15.500%
Expectancy0.194
Net Profit586.258%
Sharpe Ratio 1.233
Loss Rate54%
Win Rate46%
Profit-Loss Ratio1.61
Alpha0.159
Beta1.542
Annual Standard Deviation0.149
Annual Variance0.022
Information Ratio1.123
=================================== LONG VXX SYmbols (shorting uptranding market) =====================================
TVIX: 2013-11-11 bid/ask 9.92/9.93, VMIN also is 2.59/2.60 but low volume and Size=1
Total Trades702
Average Win2.57%
Average Loss-1.24%
Compounding Annual Return 41.088%
Drawdown 15.200%
Expectancy0.374
Net Profit354.288%
Sharpe Ratio 1.446
Loss Rate55%
Win Rate45%
Profit-Loss Ratio 2.07
Alpha0.44
LABD: 2015-6-1 - Biotech (but long (LABU) is BAD ?!!)
Total Trades456
Average Win3.08%
Average Loss-1.95%
Compounding Annual Return 102.914%
Drawdown 13.700%
Expectancy0.485
Net Profit640.855%
Sharpe Ratio 2.101
Loss Rate43%
Win Rate57%
Profit-Loss Ratio1.59
Alpha0.211
Beta25.269
Annual Standard Deviation0.298
Annual Variance0.089
Information Ratio2.046
ZBIO: 2015-5-10, vol=47,000
Total Trades446
Average Win2.36%
Average Loss-1.38%
Compounding Annual Return 56.279%
Drawdown 14.500%
Expectancy0.445
Net Profit263.458%
Sharpe Ratio 1.809
Loss Rate47%
Win Rate53%
Profit-Loss Ratio1.71
Alpha0.261
Beta7.889
Annual Standard Deviation0.216
Annual Variance0.047
Information Ratio1.733
SRTY - 02/11/2010
Total Trades1242
Average Win1.43%
Average Loss-0.84%
Compounding Annual Return 23.058%
Drawdown 12.400%
Expectancy0.338
Net Profit440.411%
Sharpe Ratio 1.372
Loss Rate50%
Win Rate50%
Profit-Loss Ratio 1.70
Alpha-0.008
Beta11.363
Annual Standard Deviation0.131
MIDZ: 2009-2-1
otal Trades1396
Average Win1.40%
Average Loss-0.66%
Compounding Annual Return 22.930%
Drawdown 13.700%
Expectancy0.425
Net Profit562.841%
Sharpe Ratio 1.445
Loss Rate54%
Win Rate46%
Profit-Loss Ratio2.11
Alpha0.186
Beta-0.499
Annual Standard Deviation0.123
Annual Variance0.015
Information Ratio1.311
TZA: 2008-11-5
Total Trades1398
Average Win1.50%
Average Loss-0.87%
Compounding Annual Return 20.581%
Drawdown 13.700%
Expectancy0.307
Net Profit479.272%
Sharpe Ratio 1.2
Loss Rate52%
Win Rate48%
Profit-Loss Ratio1.74
Alpha0.131
Beta1.94
Annual Standard Deviation0.136
Annual Variance0.019
Information Ratio1.079
TWM - 2009-2-1
Total Trades1396
Average Win1.04%
Average Loss-0.60%
Compounding Annual Return 13.725%
Drawdown 10.500%
Expectancy0.294
Net Profit224.883%
Sharpe Ratio 1.159
Loss Rate53%
Win Rate47%
Profit-Loss Ratio1.75
Alpha0.088
Beta1.333
Annual Standard Deviation0.095
Annual Variance0.009
Information Ratio0.986
SOXS: Semiconductors
Total Trades1240
Average Win1.73%
Average Loss-1.28%
Compounding Annual Return 18.259%
Drawdown 30.600%
Expectancy0.189
Net Profit288.007%
Sharpe Ratio 0.899
Loss Rate50%
Win Rate50%
Profit-Loss Ratio1.35
Alpha0.155
Beta-0.179
Annual Standard Deviation0.169
Annual Variance0.029
Information Ratio0.802
SPXU - 6/23/2009
Total Trades1334
Average Win0.89%
Average Loss-0.56%
Compounding Annual Return 6.278%
Drawdown 11.100%
Expectancy0.151
Net Profit70.572%
Sharpe Ratio 0.666
Loss Rate55%
Win Rate45%
Profit-Loss Ratio1.58
Alpha0.122
SQQQ: 2010-4-1
Total Trades1230
Average Win1.24%
Average Loss-0.72%
Compounding Annual Return 13.374%
Drawdown 12.900%
Expectancy0.241
Net Profit172.863%
Sharpe Ratio 1.002
Loss Rate55%
Win Rate45%
Profit-Loss Ratio1.74
Alpha0.129
SDOW: 2010-2-9
Total Trades1242
Average Win0.81%
Average Loss-0.54%
Compounding Annual Return 4.334%
Drawdown 10.200%
Expectancy0.110
Net Profit41.218%
Sharpe Ratio 0.53
Loss Rate56%
Win Rate44%
Profit-Loss Ratio1.50
Alpha0.097
FAZ: 2008-11-10
Total Trades1374
Average Win1.20%
Average Loss-0.80%
Compounding Annual Return 10.720%
Drawdown 13.100%
Expectancy0.189
Net Profit160.090%
Sharpe Ratio 0.756
Loss Rate52%
Win Rate48%
Profit-Loss Ratio1.50
Alpha0.203
Beta-6.829
Annual Standard Deviation0.12
Annual Variance0.014
Information Ratio0.619
*/
}namespace QuantConnect.Algorithm.Examples
{
public class MyTransactionModel : EquityTransactionModel
{
private decimal SlippagePercent {get;set;}
/// <summary>
/// Initialize the default transaction model class
/// </summary>
public MyTransactionModel( decimal slippage, QCAlgorithm a)
{
SlippagePercent = slippage;
}
public override decimal GetSlippageApproximation(Security asset, Order order)
{
var lastData = asset.GetLastData();
if (lastData == null)
return 0;
decimal slippage = lastData.Value * SlippagePercent/100m;
return slippage;
}
} // class
}using System.Collections.Generic;
using NodaTime;
using QuantConnect.Data;
using QuantConnect.Data.Custom;
namespace QuantConnect.Algorithm.Examples
{
public class DrawDPoint
{
public decimal DD;
public decimal upVal;
public decimal downVal;
public DateTime upValTime;
public DateTime downValTime;
public DateTime recoverTime;
public DrawDPoint( DrawDPoint d )
{
DD = d.DD;
upVal= d.upVal;
downVal= d.downVal;
upValTime= d.upValTime;
downValTime = d.downValTime;
}
public DrawDPoint( )
{}
} // class
public class DrawDown
{
public DrawDPoint GetDD( List<TradeBar> bars )
{
DrawDPoint worst=new DrawDPoint();
DrawDPoint cur = new DrawDPoint();
worst.DD=0;
worst.upVal = worst.downVal = bars[0].Close;
worst.upValTime = worst.downValTime = bars[0].Time;
cur.DD = 0;
cur.upVal = cur.downVal = bars[0].Close;
cur.upValTime = cur.downValTime = bars[0].Time;
for(int i=1; i<bars.Count; i++)
{
// check if it needs to be set as recovery for worst
if ( worst.recoverTime == DateTime.MinValue && bars[i].Close>worst.upVal )
{
// this is first exceed, we can set recovery
worst.recoverTime = bars[i].Time;
}
// check for new peak
if ( bars[i].Close>cur.upVal )
{
// reset current
cur.upVal = bars[i].Close;
cur.upValTime = bars[i].Time;
cur.downVal = bars[i].Close;
cur.downValTime = bars[i].Time;
cur.DD = cur.upVal-cur.downVal;
}
else
{
// check for new min
if (bars[i].Close < cur.downVal )
{
// new min found
cur.downVal = bars[i].Close;
cur.downValTime = bars[i].Time;
cur.DD = cur.upVal-cur.downVal;
// since this is a new min, check for drawdown
if ( cur.DD > worst.DD )
{
// found new worst DD
worst = new DrawDPoint( cur);
}
else
{
// not a new drawdown, do nothing
}
} // if
else
{
// no peak, no min - do nothing
}
} // else
} // for i
return worst;
} // GetDD
} // class DrawDown
} // namespace