Hi,
I'm new and and I try to learn by creating a simple algo. The algo should buy on stochastics signal (cross under classic 20 threshold) and sell only if the PNL of the trade is > to a % defined.
1. When I run the algo and I export the trades I noted that the exit conditions is not always respected (PNL < 2% for some trades). Why please ?
2. Also I would like to run it on 10 securities. I understand that I need to add securities and then lool to create the stochastic for each security. Can someone give me an example to create sur a loop please ?
3. Last, I would like to try other timeframe especially 30 minutes. How to do it with consolidator please ?
Thank you
JF
using System.Drawing; // for Color
namespace QuantConnect
{
public class Teststochnoloss : QCAlgorithm
{
// stock name set up.
String symbol = "IRBT";
decimal targetProfit = 0.02m; //0.02m=0.2% //Target profit for strategy. When achieve this exit.
Stochastic sto;
int overBought = 20;//a optimiser
decimal sortie=100000m;
//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{
//ini broker model
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash);
//Start and End Date range for the backtest:
SetStartDate(2016, 1, 16);
SetEndDate(DateTime.Now.Date.AddDays(-1));
//Add as many securities as you like. All the data will be passed into the event handler:
AddSecurity(SecurityType.Equity, symbol, Resolution.Hour);
//*how to use the algo on several stocks (a dozen max) ?
//* Is it possible to use 30 minutes timeframe please ?
// customize benchmark
SetBenchmark("AAPL");
// initializing stochastic
int KPeriod = 14;
int DPeriod = 3;
sto = STO(symbol,14,KPeriod,DPeriod);
SetWarmup(20);
// we can 'warm up' our indicators using the history function directly
//var history = History("SPY", 250);
// we can also warm up these indicators using the SetWarmup function
// SetWarmup will pump data through the entire algorithm, including OnData
// whereas the History function is handled by user code
//SetWarmup(250); // ask for 250 bars of warmup at registered resolution
//SetWarmup(TimeSpan.FromDays(3)); // ask for 3 calendar days of warmup
// these are calendar days, so beware of weekends
//Cash allocation
SetCash(10000);
Chart plotter = new Chart("Plotter");
plotter.AddSeries(new Series("D", SeriesType.Line, " ",Color.Red));
plotter.AddSeries(new Series("K", SeriesType.Line, " ",Color.Blue));
plotter.AddSeries(new Series("Over Bought", SeriesType.Line, " ",Color.Black));
plotter.AddSeries(new Series("Buy", SeriesType.Scatter, index:0));
plotter.AddSeries(new Series("Sell", SeriesType.Scatter, index:0));// sur graph plot pas rouge
AddChart(plotter);
}
//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
public void OnData(TradeBars data)
{
if (IsWarmingUp) return;
Log(string.Format("{0} {1}",sto.StochD,sto.StochK));
if (!Portfolio.HoldStock && sto.IsReady) //* is is not a doublon to put is ready with warmup ?
{
if(sto.StochK>sto.StochD && sto.StochD<overBought )
{
int quantity = (int)Math.Floor(Portfolio.Cash / data[symbol].Close);
var entry = data[symbol].Price;
sortie = entry * (1 + targetProfit); // target = 0.05 for 5% gain
//SetHoldings(symbol, 1);
Order(symbol, quantity);///sur plusieurs titres quantité?
Plot("Plotter", "Buy", data[symbol].Close);
Debug("Stoch no loss buy" + Time.ToString("Y"));
//return;
}
}
if (data[symbol].Price >= sortie)
{
Liquidate(symbol);//sortie a optimiser avec croisement sto ou trailinstop
Plot("Plotter","Sell", data[symbol].Close);
sortie=100000;
//exitDate = Time.Date;
return;
}
// Later in your OnData(Slice data):
Plot("Plotter", "IRBT", data[symbol].Close);
Plot("Plotter","D", sto.StochD);
Plot("Plotter","K", sto.StochK);
Plot("Plotter","Over Bought", overBought);
//Plot("Buy", buyOrders);
//Plot("Sell", sellOrders);
//Plot(_plotter, "Price", data[symbol].Close);
}
}
}
Alexandre Catarino
When we set up out target price with the current price, we are not taking into consideration that our order can be filled in another/worse price. For instance, if current price is $100 and fill price is $100,05, when we reach the target at $102, we have only locking for a $1.95 profit. We can adjust this by calculating the target with the fill price at the OnOrderEvent handler:
public override void OnOrderEvent(OrderEvent orderEvent) { if (orderEvent.Status == OrderStatus.Filled) { var symbol = orderEvent.Symbol; var price = orderEvent.FillPrice; if (orderEvent.Direction == OrderDirection.Buy) { _targetPrice[symbol] = price * (1 + _targetProfit); } } }
Please checkout QuantConnect University example "How do I Use Consolidators?".
I have attached project with a full working example.
Note that I used dictionaries to manage stochastic and target prices for each security. If we need to add more complexity (more indicators, stop loss, trailing stop, etc), we better create a class that holds the information and a single dictionary to access each security information.
Jean-François Garino
Thank you thats nice. I dont see the attachment, I suppose it was supposed to appear chere I have the Oops! 404 error message ? could you put the code directly please ?
Jean-François Garino
please forget my last comment, its due to my browser. Thank you.
Jean-François Garino
Hi, when I try the code with MSFT only from 16/01/1998 I obtain several inconsistencies:
- the report says 9% of negative trades out of 93 trades whereas I shouldn't have negative trades. When I look at the detail of the trades I don't find 8 negatives trades but two (03/01/2000 et the last one). The trade on 03/01/2000 exits in 3 parts (?) at a strange price. The entry too has a price that I don't confirm in other data provider (prorealtime for instance).
- there are some trades that are bought at one stock like on 12/01/1999, what is the cause please ?
Thank you
JF
Alexandre Catarino
There are negative trades due to margin calls. By default, equities have 2:1 leverage, therefore when your total portfolio value reaches 50% of its initial value, some shares are sold. If we do not want to use leverage, we need to set it to 1:
var security = AddSecurity(SecurityType.Equity, ticker, Resolution.Minute); security.SetLeverage(1m);
In this particular case, the algorithm buys MSFT at $39.90, its share value drops until $13.33. That triggered two margin calls that didn't liquidate the position. Finally the remaining shares were sold once the price met the exit criteria of 2% gain.
2000-01-03T15:00:00Z, MSFT, 39.904112875, 406, Market, 3, 16201.06982725, 2000-10-09T17:16:00Z, MSFT, 18.070742025, -84, Market, 3, -1517.9423301, Margin Call 2009-02-24T18:16:00Z, MSFT, 13.330090791, -92, Market, 3, -1226.368352772, Margin Call 2014-07-16T16:20:00Z, MSFT, 40.709282079, -230, Market ,3, -9363.13487817,
Jean-François Garino
is it correct directly like this please ? AddSecurity(SecurityType.Equity, ticker, Resolution.Minute,true,1,false);
Jean-François Garino
There may be an other mistake because I still have order volumes buying 1 or 2 stocks in the detailed trades...
Petter Hansson
Regarding small stock orders: If you call SetHoldings repeatedly, your portfolio will inevitably be rebalanced to match the specified leveraged.
Jean-François Garino
Hi. If I understand well, whent there is a stochastic signal on a second symbol, SetHoldings re adjusts the first position to maintain the desired weight. I tried to use the Order function to avoid this rebalancing. To compute the quantity, I divide the cash by the number of securities and by the bar open when there are no holdings, and by the number of non invested securities when there is on invested securities ate least. I still have several questions:
- when debugging the "securities.count" I noticed that SPY is always included. Is this due to the default benchmark ?
- concerning the leverage the account is declared as cash account. I understand from the documentation that there should be no leverage by default. Is it true only in live mode ?
- I don't know why but I now have a lot of invalid orders (bought at no price), status 7 and still some orders at 1 quantity...
Help please ;-)
Jean-François Garino
There is one order at 1 quantity. At this time, there is only one opened position but it seems that cash is not updated. When I debug Cash is at 126$ whereas it should be at 6643 after the sales of JLL and IRBT.
Jean-François Garino
It seems like it tries to take orders before and after market. I tried the following in the addsecurity function but it does not improve...
Jean-François Garino
Hi,
In this version I beleive Ifixed the previous issues. There s no more rebalancing thus no more small orders except those coming from capital remaining after rounding (fixed by condition on order size). I now would like to save the stochastic values (stock D and K) for the 4 previous days. Do I have to write a class like written here for the bollinger band state or is there an easier way please ?
Thx
JF
Jean-François Garino
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!