Overall Statistics
Total Orders
2159
Average Win
0.90%
Average Loss
-0.75%
Compounding Annual Return
-3.745%
Drawdown
41.600%
Expectancy
-0.066
Start Equity
100000
End Equity
59335.87
Net Profit
-40.664%
Sharpe Ratio
-0.351
Sortino Ratio
-0.397
Probabilistic Sharpe Ratio
0.000%
Loss Rate
58%
Win Rate
42%
Profit-Loss Ratio
1.20
Alpha
-0.031
Beta
-0.196
Annual Standard Deviation
0.114
Annual Variance
0.013
Information Ratio
-0.412
Tracking Error
0.212
Treynor Ratio
0.204
Total Fees
$4096.83
Estimated Strategy Capacity
$60000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
17.99%
#region imports
from AlgorithmImports import *
#endregion


class DualThrustAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2004,1,1)
        self.set_end_date(2017,8,30)
        self.set_cash(100000)
        
        equity = self.add_security(SecurityType.EQUITY, "SPY", Resolution.HOUR)
        self._syl = equity.symbol
        
        # schedule an event to fire every trading day for a security 
        # the time rule here tells it to fire when market open 
        self.schedule.on(self.date_rules.every_day(self._syl),self.time_rules.after_market_open(self._syl,0),self._set_signal)
        
        self._selltrig = None
        self._buytrig = None
        self._currentopen = None
    
    def _set_signal(self):
        k1 = 0.5
        k2 = 0.5
        high = []
        low = []
        close = []
        
        history = self.history(4, Resolution.DAILY)
        for slice in history:
            bar = slice[self._syl]
            high.append(bar.high)
            low.append(bar.low)
            close.append(bar.close)
        
        # Pull the open price on each trading day
        self._currentopen = self.portfolio[self._syl].price
        
        HH, HC, LC, LL = max(high), max(close), min(close), min(low)
        if (HH - LC) >= (HC - LL):
            signalrange = HH - LC
        else:
            signalrange = HC - LL
        
        self._selltrig = self._currentopen - k2 * signalrange
        self._buytrig = self._currentopen + k1 * signalrange    
    
    def on_data(self,data):
        if not data.contains_key(self._syl) or self._syl not in data:
            return
        
        holdings = self.portfolio[self._syl].quantity
        
        self.log('Holdings: ' + str(holdings))
        if self.portfolio[self._syl].price >= self._buytrig:
            if holdings >= 0:
                self.set_holdings(self._syl, 0.8)
            else:
                self.liquidate(self._syl)
                self.set_holdings(self._syl, 0.8)
                
        elif self.portfolio[self._syl].price < self._selltrig:
             if holdings >= 0:
                self.liquidate(self._syl)
                self.set_holdings(self._syl, -0.8)
             else:
                self.set_holdings(self._syl, -0.8)
                
        self.log("open: "+ str(self._currentopen)+" buy: "+str(self._buytrig)+" sell: "+str(self._selltrig))