| Overall Statistics |
|
Total Trades 339 Average Win 3.18% Average Loss -2.79% Compounding Annual Return 409.296% Drawdown 21.000% Expectancy 0.354 Net Profit 363.331% Sharpe Ratio 2.64 Loss Rate 37% Win Rate 63% Profit-Loss Ratio 1.14 Alpha 0.344 Beta 0.427 Annual Standard Deviation 0.465 Annual Variance 0.216 Information Ratio -1.561 Tracking Error 0.538 Treynor Ratio 2.873 Total Fees $0.00 |
import decimal as d
# shorthands for units
K, M, B = 10**3, 10**6, 10**9
### <summary>
### GDAX Playground.
### </summary>
### <meta name="tag" content="crypto bitcoin GDAX SetHoldings order PostType playground" />
class GDAXPlaygroundAlgorithm(QCAlgorithm):
def Initialize(self):
#-- Parameters ---------------------------------------------------------
self.crypto = "BTCUSD"
self.cash = 10*K
self.SetStartDate(2017, 01, 01)
resolution = Resolution.Daily
#-----------------------------------------------------------------------
self.cash = d.Decimal(self.cash)
self.SetCash(self.cash)
self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
self.AddCrypto(self.crypto, resolution)
#DefaultOrderProperties = GDAXOrderProperties()
#DefaultOrderProperties.PostType = True
self.SetBenchmark(SecurityType.Crypto, self.crypto) # doesn't work
def OnData(self, data):
security = self.Securities[self.crypto]
quantity = security.Holdings.Quantity
self.Transactions.CancelOpenOrders(self.crypto) # in case they haven't filled
# flip from 0% to 100% repeatedly
self.SetHoldings(self.crypto, 1 if not quantity else 0)
portfolio = self.Portfolio
self.Plot("Leverage?", portfolio.TotalHoldingsValue / portfolio.TotalPortfolioValue) # inaccurate
self.Plot("Price", security.Price)
self.Plot("Quantity", quantity)
# Override SetHoldings to use limit orders (ratio is of totalPortfolioValue.)
def SetHoldings(self, symbol, ratio):
security = self.Securities[symbol]
if not security.IsTradable:
self.Debug("{} is not tradable.".format(symbol))
return # passive fail
ratio = d.Decimal(ratio)
price, quantity = security.Price, security.Holdings.Quantity
# Keep 2% Cash (for the limit order, rounding errors, and safety)
totalPortfolioValue = self.Portfolio.TotalPortfolioValue * d.Decimal(0.98)
# +0.1% Limit Order
# (to make sure it executes quickly and without much loss)
# (if you set the limit large it will act like a market order)
limit = 1.001
desiredQuantity = totalPortfolioValue * ratio / price
orderQuantity = desiredQuantity - quantity
# limit needs to be inverse when selling
limitPrice = price * d.Decimal(limit if orderQuantity >= 0 else 1/limit)
self.Log("Limit Order: {} coins @ ${} per coin".format(orderQuantity, limitPrice))
self.LimitOrder(self.crypto, orderQuantity, limitPrice)
# END