As of this writing this algo is ranked #1 and is in the top 1% of the community.
It's a crypto algo. GDAX charges high fees for 'takers', and there is no fee modelling. It will have to be appropriately converted to limit orders in order to take advantage of GDAX's zero fee for 'makers' fee model in order to actually be useful. Slippage is low on GDAX for the instruments in question so that shouldn't have too much of an impact.
Jack Pizza
Thushara Silva
Why do you have limit orders on? Even with market orders and fees the backtest is showing profitable....or are the numbers that the backtest is calculating for the fees wrong?
Jack Pizza
Ok guys launched this live, do I need to have my holdings in cash when I first launch it? It's currently all in BTC... How long does it usually take to get the first order?
I set it to a very low order size too see if it's operating properly.
Thushara Silva
- i have market order running live on GDAX.
I also have limit orders and market orders running on paper trading. WIll let these run for a few days to do a comparision between all 3.
Jack Pizza
Thushara Silva
Ok cool, I started running live too with super low margin to see how it performs, I'm not seeing any orders yet how long does it take to place first order? And my holdings are in BTC, not in cash.
Also, I basically traded Samuals code as is for market orders, do I need to make any changes? I don't see any errors.
Thushara Silva
Elsid Aliaj - - could take 1-3 hours. Take a look at the backtest results, you will get an idea of when the orders times.
Jack Pizza
Thushara Silva
Looks like I am getting error for some orders, even though I lowered the margin to .001,
New Order Event: Time: 3/24/2018 12:12:47 AM OrderID: 4 Symbol: BTCUSD Status: Invalid Message: Order Error: id: 4, Insufficient buying power to complete order (Value:2628.4652), Reason: Your portfolio holds 2541.54650205335745 USD, 0 USD of which are reserved for open orders, but your Buy order is for 0.29443662 BTC. Your order requires a total value of 2628.465150402 USD, but only a total value of 2544.17941311345 USD is available. 2018-03-24 00:12:48 : Algorithm Id:(L-fe6856cf9b2554e53d3ef958b6330703) completed in 5768.64 seconds at 0k data points per second. Processing total of 13 data points. 2018-03-24 00:00:00 : New Order Event: Time: 3/24/2018 12:00:00 AM OrderID: 2 Symbol: BTCUSD Status: Invalid Message: Order Error: id: 2, Insufficient buying power to complete order (Value:2628.4652), Reason: Your portfolio holds 2541.54650205335745 USD, 0 USD of which are reserved for open orders, but your Buy order is for 0.29443662 BTC. Your order requires a total value of 2628.465150402 USD, but only a total value of 2544.21886183485 USD is available. 2018-03-24 00:00:00 : New Order Event: Time: 3/24/2018 12:00:00 AM OrderID: 2 Symbol: BTCUSD Status: Invalid Message: Order Error: id: 2, Insufficient buying power to complete order (Value:2628.4652), Reason: Your portfolio holds 2541.54650205335745 USD, 0 USD of which are reserved for open orders, but your Buy order is for 0.29443662 BTC. Your order requires a total value of 2628.465150402 USD, but only a total value of 2544.21886183485 USD is available. 2018-03-24 00:00:00 : New Order Event: Time: 3/24/2018 12:00:00 AM OrderID: 3 Symbol: ETHUSD Status: Invalid Message: BrokerageModel declared unable to submit order 2018-03-24 00:00:00 : New Order Event: Time: 3/24/2018 12:00:00 AM OrderID: 3 Symbol: ETHUSD Status: Invalid Message: BrokerageModel declared unable to submit order 2018-03-24 00:00:00 : Order Error: id: 2, Insufficient buying power to complete order (Value:2628.4652), Reason: Your portfolio holds 2541.54650205335745 USD, 0 USD of which are reserved for open orders, but your Buy order is for 0.29443662 BTC. Your order requires a total value of 2628.465150402 USD, but only a total value of 2544.21886183485 USD is available.
1. Insufficient buying power? I also don't know why it was trying to buy the whole account with leverage set so low.
2. ETH/USD was rejected, broker unable to submit order.
Jack Pizza
This is my code btw, do I need to set
SetBrokerageModel(BrokerageName.GDAX) somewhere?
//Copyright HardingSoftware.com, 2018. //Granted to the public domain. //Use entirely at your own risk. namespace QuantConnect { public class MultiCoinFramework : QCAlgorithm { string tickersString ="BTCUSD,ETHUSD,LTCUSD"; decimal changes1Ratio=-1.0m; //The influence of change upon fitness. decimal changes2Ratio=0.0m; //The influence of change in change upon fitness. int emaOfChanges1Length=1; //The length of the change indicator. int emaOfChanges2Length=1; //The length of the change in change indicator. //decimal leverage=.998m; decimal leverage=.001m; int historyLength=2; int changes1Length=2; int changes2Length=2; Resolution resolution=Resolution.Hour; List<StockData> stockDatas = new List<StockData>(); string stockHeld=""; public override void Initialize() { SetStartDate(2018, 2, 1); SetEndDate(2018, 3, 21); SetCash(1000); string[] tickers = tickersString.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (string ticker in tickers) { Symbol symbol = QuantConnect.Symbol.Create(ticker, SecurityType.Crypto, Market.GDAX); AddCrypto(symbol, resolution); StockData stockData=new StockData(); stockData.Ticker=ticker; stockData.emaOfChanges1Indicator = new ExponentialMovingAverage(emaOfChanges1Length); stockData.emaOfChanges2Indicator = new ExponentialMovingAverage(emaOfChanges2Length); stockDatas.Add(stockData); } foreach (Security s in Securities.Values) { s.FeeModel=new CustomFeeModel(); } } public override void OnData(Slice data) { foreach (StockData stockData in stockDatas) { if (data.QuoteBars.ContainsKey(stockData.Ticker)==false) { continue; } stockData.history.Add(data.QuoteBars[stockData.Ticker].Close); if (stockData.history.Count>historyLength) { stockData.history.RemoveAt(0); } if (stockData.history.Count>=2) { if (stockData.history[stockData.history.Count-2]!=0) { decimal change=(stockData.history.Last()-stockData.history[stockData.history.Count-2])/stockData.history[stockData.history.Count-2]; stockData.changes1History.Add(change); if (stockData.changes1History.Count>changes1Length) { stockData.changes1History.RemoveAt(0); } } } if (stockData.changes1History.Count>=2) { decimal change=stockData.changes1History.Last()-stockData.changes1History[stockData.changes1History.Count-2]; stockData.changes2History.Add(change); if (stockData.changes2History.Count>changes2Length) { stockData.changes2History.RemoveAt(0); } } if (stockData.changes1History.Count>0) { stockData.emaOfChanges1Indicator.Update(Time,stockData.changes1History.Last()); } if (stockData.changes2History.Count>0) { stockData.emaOfChanges2Indicator.Update(Time,stockData.changes2History.Last()); } stockData.Fitness=changes1Ratio*stockData.emaOfChanges1Indicator+changes2Ratio*stockData.emaOfChanges2Indicator; } var q1 = from x in stockDatas orderby x.Fitness descending select x; List<StockData> q2=q1.ToList(); if (q2.Count>0) { StockData selectedStockData=q2.First(); if (selectedStockData.Ticker != stockHeld) { Liquidate(); SetHoldings(selectedStockData.Ticker, leverage); stockHeld=selectedStockData.Ticker; } } } class StockData { public string Ticker; public List<decimal> history=new List<decimal>(); public List<decimal> changes1History=new List<decimal>(); public List<decimal> changes2History=new List<decimal>(); public ExponentialMovingAverage emaOfChanges1Indicator; public ExponentialMovingAverage emaOfChanges2Indicator; public decimal Fitness; } public class CustomFeeModel : IFeeModel { public decimal GetOrderFee(Security security, Order order) { var fee = order.AbsoluteQuantity*0.0025m*security.Price; return fee; } } } }
Samuel Cutler
Thushara I'm running a little different strategy live, but more or less does the same thing, I have mine set to limit orders to keep the fees down on the GDAX exchange, The best i've got so far was a buy sell then another buy and sell then it comes invalid orders, I come to think its because the algo is trying to buy again before it has sold the previous asset. I am trying to find the approrite place to code in the delay so it would sell that asset then wait a few minutes for that limit order to fill before moving on to the next lines of code. (I'm still very new to this)
Elsid explained in previous comments is how to set holding to BTC. I have been using cash. The above would work and profit but not to that degree. Towards the end its filling orders for over $1M theres not that type of liquidity in the crypto market to fill that type of order on GDAX. Setting the EMA to 1 would also increase the sharp ratio drastically. I found 5 to be a nice number for this algo (sharp Ratio still high) for shorter term the higher the number would be better for longer term in my opinion like Warren had it at 24.
Jack Pizza
I think I figured out the insane profits, If you leave out in the backtests:
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash); according to the API it defaults to Margin trading of 2, if I'm not mistaken, when you turn on Cash which GDAX is cash only the profits go down, still nothing to scoff at, but about 10X less.
@Samual if the order issues are due to limit orders, I would just use market orders, the profits are still mind boggling even with fees turned on, it would save you a lot of time handling logic for the orders, and also with limit orders the backtests become kind of flaky as you never know if you would fill your whole order or not.
I'm not very familiar with QC's data to be able to distinguish if it has proper/tick data.
Jack Pizza
I still don't understand why leverage is being ignored.... All my orders seem to be for full account size + fees, even though leverage is .001...
Jared Broad
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Jack Pizza
Jared Broad
What does the model default too if you don't set brokerage model? Because when I don't set the brokerage model the algorithm shows returns of 10 times more, than when set... trying to figure out why.
Jack Pizza
Orders are filling fine live as Market Orders. Issue I've noticed is the status of orders doesn't change they all stay as Submitted.
Samuel Cutler
Elsid mine goes back and forth some say submitted some say filled, the best i got was a buy sell buy sell then the orders start to be invalid and it does this abou 5 times over the course of 6 hours. I am trying it now with market orders. I have my Liquidate();Transactions.MarketOrderFillTimeout = TimeSpan.FromSeconds(100); but im not sure if I have this in the right spot?
;
Thushara Silva
So I had market orders running live since y'day. Updated leverage to .998, set "Transactions.MarketOrderFillTimeout = TimeSpan.FromSeconds(45);"
Last night it started acting up.
1. Around 8 PM, it submitted an ETH order, but I assume it did not get filled, 2 hours later it tired to sell it.
2. 11PM - tried to sell an LTC order for more than I owned. AFtrer that through this AM everthing is invalid, as it kept trying to sell this higher LTC amount than I owned.
3. Another issue is the at 4AM, the next log entry is at 10 AM. I stopped the algo aty 9:53AM, but the Log time states 14:53. Even though I restarted, it shows the time at 15:xx. Not sure if this sync issue causes order issues.
Jack Pizza
Samuel Cutler
Yeah I don't have the TimeSpan at all, I'm assuming TimeSpan goes into the initilize function. I noticed only 2 orders come back as filled. I don't think the TimeSpan is needed at all for Market orders, also according to QC from an old post there is a default timeout of 5 seconds which should be more than enough, when you set your brokeragetype properly to GDAX it also makes sure you have the cash/coins for the order supposedly at least.
Yes I believe in should be under liquidate(), as anything outside of the if statement won't apply, and that is the only place I can see as order logic.
But Again I've let it out completely and my orders are going through fine as Market orders.
Thushara Silva
1. How do you know it did not get filled? It's a Market order unless the order didn't make it to GDAX.
2. Could be a margin issue, try lowering it lower than .998 because fees are probably not covering the order, I have mine set to .01 as an experiment and every order since last night has went through fine with no amount errors. You have to calculate what percentage fee GDAX charges on orders (0.3 %) which means you should probably lower margin to cover it, to say something like .997 as a bare minimum.
3. I am ignoring the log times for now also, as they are completely off. Unrealized profits seem off too, seems like live trading stats have been completely neglected for the most part, so I am ignoring majority of them.
Been running since 6AM I'll let you know if i run into any issues
Jared Broad
Its not the margin/leverage etc. On GDAX the top of the order book is shallow - so when you submit an order for say 1BTC @ $5,000ea it only fills 0.01 at that price; and then others at more expensive prices after that.
Normally exchanges don't fill or allow you to submit an order which will only get partially filled -- but in this case GDAX fills say 95% of the order -- 0.95BTC for $5,000 and never sends a "Filled" message to denote its done processing your trade.
We're working on a systematic fix for this now which will detect when the order is completed (as much as we can anyway). The way for you to not encounter this in your algorithm is to put a wider margin of error in your trading -- say leave 10% of BTC and 10% USD in your account at anytime.
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Jack Pizza
Samuel Cutler
Also Transactions.MarketOrderFillTimeout = TimeSpan.FromSeconds(45); doesn't seem to do anything at least in the If statement of Liquidate(); from what I read it would need to go into it's own Transactions class which this algo doesn't have. I could be wrong, but from backtesting you still get the same results with it on or off.
John Schwartz
I have vetted this algo pretty good. It's going to take quite a few mods to make it work. This algo is great on the ups, but it's crap on the downs. I don't recommend using it without an algo to initialize it on up trends only.
It'll magnify downs just as much as ups.
John Schwartz
Here's an updated Gdax fee model.
public class CustomFeeModel : IFeeModel { public decimal GetOrderFee(Security security, Order order) { var feePercent = 0.0025m; if (security.Symbol == "LTCUSD" || security.Symbol == "ETHUSD") { feePercent = 0.0030m; } var fee = order.AbsoluteQuantity * feePercent * security.Price; return fee; } }
Warren Harding
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!