So clearly this doesn't add up, it thinks it's ordering BTCUSD for FAR cheaper than it really could be, and it's also somehow magically gaining buying power. Can someone tell me why this is happening and how to fix this?
decimal price = data[btc].Close;
decimal holdings = Portfolio[btc].Quantity;
if (Portfolio.GetBuyingPower("BTCUSD") > price)
{
Debug("BUY; Date: " + data.Time + "; Price: " + price + "; Buying Power: " + Portfolio.GetBuyingPower("BTCUSD") + "; Coins: " + holdings);
Order("BTCUSD", 1);
}
else
{
Debug("FAIL; Date: " + data.Time + "; Price: " + price + "; Buying Power: " + Portfolio.GetBuyingPower("BTCUSD") + "; Coins: " + holdings);
}
Debug Below:
2017-12-01 19:00:00 : BUY; Date: 12/1/2017 7:00:00 PM; Price: 10869.84; Buying Power: 100000.000; Coins: 0
2017-12-02 19:00:00 : BUY; Date: 12/2/2017 7:00:00 PM; Price: 10930.24; Buying Power: 89191.635; Coins: 1
2017-12-03 19:00:00 : BUY; Date: 12/3/2017 7:00:00 PM; Price: 11290; Buying Power: 78996.8200; Coins: 2
2017-12-04 19:00:00 : BUY; Date: 12/4/2017 7:00:00 PM; Price: 11643.98; Buying Power: 68699.825000000000000000000001; Coins: 3
2017-12-05 19:00:00 : BUY; Date: 12/5/2017 7:00:00 PM; Price: 11718.35; Buying Power: 57397.860; Coins: 4
2017-12-06 19:00:00 : BUY; Date: 12/6/2017 7:00:00 PM; Price: 14090; Buying Power: 57495.7950; Coins: 5
2017-12-07 19:00:00 : BUY; Date: 12/7/2017 7:00:00 PM; Price: 17390.01; Buying Power: 63513.930000000000000000000002; Coins: 6
2017-12-08 19:00:00 : BUY; Date: 12/8/2017 7:00:00 PM; Price: 16367.03; Buying Power: 39086.40500000000000000000000; Coins: 7
2017-12-09 19:00:00 : FAIL; Date: 12/9/2017 7:00:00 PM; Price: 15309.98; Buying Power: 13600.40000000000000000000000; Coins: 8
2017-12-10 19:00:00 : FAIL; Date: 12/10/2017 7:00:00 PM; Price: 15290.01; Buying Power: 13456.56000000000000000000000; Coins: 8
2017-12-11 19:00:00 : BUY; Date: 12/11/2017 7:00:00 PM; Price: 16885.76; Buying Power: 26302.48000000000000000000000; Coins: 8
2017-12-12 19:00:00 : FAIL; Date: 12/12/2017 7:00:00 PM; Price: 17730.12; Buying Power: 17015.95500000000000000000000; Coins: 9
Jason Briggs
I redid the code / debug stuff to make it easier to read and understand.
public override void Initialize() { SetStartDate(2017, 12, 01); SetEndDate(2017, 12, 11); SetCash(100000); AddCrypto("BTCUSD", Resolution.Daily, Market.GDAX); } public override void OnData(Slice data) { decimal price = data.Bars["BTCUSD"].Close; decimal holdings = Portfolio[btc].Quantity; Debug("BTC Price is $" + price + " and Buying Power is $" + Portfolio.GetBuyingPower("BTCUSD"));// + "; Coins: " + holdings); if (Portfolio.GetBuyingPower("BTCUSD") > price) { MarketOrder("BTCUSD", 1); Debug("Bought! Now have " + holdings + " coins"); Debug(" "); } else { Debug("Failed to buy"); Debug(" "); } }
and updated debug log.
2017-12-01 19:00:00 : BTC Price is $10869.84 and Buying Power is $100000.000 2017-12-01 19:00:00 : Bought! Now have 0 coins 2017-12-01 19:00:00 : 2017-12-02 19:00:00 : BTC Price is $10930.24 and Buying Power is $89191.635 2017-12-02 19:00:00 : Bought! Now have 1 coins 2017-12-02 19:00:00 : 2017-12-03 19:00:00 : BTC Price is $11290 and Buying Power is $78996.8200 2017-12-03 19:00:00 : Bought! Now have 2 coins 2017-12-03 19:00:00 : 2017-12-04 19:00:00 : BTC Price is $11643.98 and Buying Power is $68699.825000000000000000000001 2017-12-04 19:00:00 : Bought! Now have 3 coins 2017-12-04 19:00:00 : 2017-12-05 19:00:00 : BTC Price is $11718.35 and Buying Power is $57397.860 2017-12-05 19:00:00 : Bought! Now have 4 coins 2017-12-05 19:00:00 : 2017-12-06 19:00:00 : BTC Price is $14090 and Buying Power is $57495.7950 2017-12-06 19:00:00 : Bought! Now have 5 coins 2017-12-06 19:00:00 : 2017-12-07 19:00:00 : BTC Price is $17390.01 and Buying Power is $63513.930000000000000000000002 2017-12-07 19:00:00 : Bought! Now have 6 coins 2017-12-07 19:00:00 : 2017-12-08 19:00:00 : BTC Price is $16367.03 and Buying Power is $39086.40500000000000000000000 2017-12-08 19:00:00 : Bought! Now have 7 coins 2017-12-08 19:00:00 : 2017-12-09 19:00:00 : BTC Price is $15309.98 and Buying Power is $13600.40000000000000000000000 2017-12-09 19:00:00 : Failed to buy 2017-12-09 19:00:00 : 2017-12-10 19:00:00 : BTC Price is $15290.01 and Buying Power is $13456.56000000000000000000000 2017-12-10 19:00:00 : Failed to buy 2017-12-10 19:00:00 : 2017-12-11 19:00:00 : BTC Price is $16885.76 and Buying Power is $26302.48000000000000000000000 2017-12-11 19:00:00 : Bought! Now have 8 coins 2017-12-11 19:00:00 : 2017-12-12 19:00:00 : BTC Price is $17730.12 and Buying Power is $17015.95500000000000000000000 2017-12-12 19:00:00 : Failed to buy 2017-12-12 19:00:00 :
Jason Briggs
Bump. Please help, this problem makes all backtesting pointless.
Michael Handschuh
By default your account is set to a margin account with 3x leverage IIRC.
Try doing this at the top of your Initialize function:
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
Jason Briggs
Thank you, but the problem still occurs. It still has growing buying power (my algo doesn't sell anything) and it still buys when it shouldn't be able to.
Jason Briggs
Here is the full code that can be tested, I dont see what could possible be wrong with my code.
namespace QuantConnect.Algorithm.CSharp { public class BasicTemplateAlgorithm : QCAlgorithm { decimal cashLeft = 100000; public override void Initialize() { SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash); SetStartDate(2017, 12, 01); //Set Start Date SetEndDate(2017, 12, 12); //Set End Date SetCash(cashLeft); //Set Strategy Cash AddCrypto("BTCUSD", Resolution.Daily, Market.GDAX); } public override void OnData(Slice data) { Debug("BTC Price is $" + data.Bars["BTCUSD"].Close + " and Buying Power is $" + Portfolio.GetBuyingPower("BTCUSD")); if (Portfolio.GetBuyingPower("BTCUSD") > data.Bars["BTCUSD"].Close) { var ticket = MarketOrder("BTCUSD", 1); if (ticket.Status == OrderStatus.Filled) { var fills = ticket.OrderEvents.Where(orderEvent => orderEvent.Status.IsFill()).ToList(); Debug("Bought! Now have " + Portfolio["BTCUSD"].Quantity + " coins"); cashLeft -= fills.Sum(fill => fill.FillPrice); Debug("Actual Cash Left: " + cashLeft); Debug("Delta Cash (error): " + (Portfolio.GetBuyingPower("BTCUSD") - cashLeft)); Debug(" "); } else { Debug("Failed Fill"); Debug(" "); } } else { Debug("Not enough buying power"); Debug(" "); } } } }
Jared Broad
Welcome Jason;
1) Its not ordering below what it should be; early December was roughly $10k per coin.
2) This behaviour is called a "Margin Model". This happens in most brokerages in a currency swap. GDAX is a simplified brokerage which doesn't have this behavior so we're deciding the best way to integrate it into LEAN as per this PR. Buying power uses a margin model which allows the portfolio value to be considered as is the behavior on most brokerages. Each "coin" is converted back to the base currency of LEAN (USD) and so as the total portfolio value increases; with leverage of 1.0 -> your purchasing power can increase as the margin used to purchase the original coins is static. Cash != Purchasing Power when using margin trading.
However there is nothing "So Broken"; simply a misunderstanding on about how currency swaps+leverage works. If asking for community help try and consider your tone; with thousands of forks and contributors to the open source you can safely assume 99% of things you think are bugs are misunderstandings.
I've simplified your backtest to make it more obvious; the cash is not changing over time, its simply a swap + margin model.
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.
Jason Briggs
How do I simply get the raw amount of USD I have, no margin spending.
Say I have $100 of USD and I don't want to use any margin, and I want to buy one coin of a crypto that currently cost $50 USD. At this point I will currently hold $50 USD and 1 crypto coin. If the price of this coin then jumps to $60 USD and I try to buy 1 crypto coin, it should fail because I do not have enough USD to buy it. The question is how to I get the current spendable USD I have at any given moment and how to I turn off margin and make sure the algo doesn't do something stupid.
Jared Broad
In the backtest I attached we print the Raw amount of USD:
Portfolio.CashBook["USD"].Amount
The cashbook stores the raw "coins" you hold (including BTC).
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.
Jason Briggs
And sorry for any fustration that's coming through, I've been spending days on something that should be very very easy. Currently this feels like one of the most fustrating API's I've worked with over my 20 years of programming work. Maybe they are just misunderstandings, but I am trying to refer to the docs for help and it seems clear what should be happening, but the results are just not lining up. So much time lost haha. I really want to like/use quantconnect!
Jason Briggs
Thank you, this does seem to be what I am looking for, but is there a reason it doesn't match with that amount the order ticket says it fills at? It should stay constant with what my "cashLeft" variable tracks correct?
That is shouldn't the below statement be true after an order fills...
Portfolio.CashBook["USD"].Amount (new amount) == Portfolio.CashBook["USD"].Amount (old amount) - fills.Sum(fill => fill.FillPrice)
given that
var fills = ticket.OrderEvents.Where(orderEvent => orderEvent.Status.IsFill()).ToList();
or is fills just an approximation?
Jared Broad
There are no approximations :) and the cash impacted depends on how much margin is required in the asset purchase case. In FX case we literally deduct each side from the cashbook; and simultaneously note down how much margin was required for the trade. The margin records are like a ledger of the impact on buying power.
I wouldn't worry too much for now we'll be updating the GDAX default margin models soon; but its good for you to understand whats going on. GDAX isn't a simple case as they don't provide information that many traditional brokerages provide (e.g. virtual holdings EURUSD).
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.
Jason Briggs
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!