Not too sure how to show my latest (failed) backtest, but here the code snippet that's giving me problems:
#Variables
self.symbol = "BTCUSD"
self.fast_ma_period = 50
self.slow_ma_period = 200
#this is under def Initialize(self)
Crypto = self.AddCrypto(self.symbol, Resolution.Hour).Symbol
self.FastMA = self.SMA(Crypto, self.fast_ma_period, Resolution.Hour)
self.FastMa.Updated += self.FastMAUpdated
self.FastMAValues = RollingWindow[Decimal](2)
self.SlowMA = self.SMA(Crypto, self.slow_ma_period, Resolution.Hour)
self.SlowMA.Updated += self.SlowMAUpdated
self.SlowMAValues = RollingWindow[Decimal](2)
def SlowMAUpdated(self, sender, updated):
'''Adds updated values to rolling window'''
self.SlowMAWin.Add(updated)
def FastMAUpdated(self, sender, updated):
'''Adds updated values to rolling window'''
self.FastMAWin.Add(updated)
I'm trying to make a moving average cross algorithm, the source code is in C and I'm having a hard time translating to python
Source code (credit to bigbits on youtube):
namespace QuantConnect.Algorithm.CSharp
{
public class CryptoCrossover : QCAlgorithm
{
// -- User Settings
private string Symbol = "BTCUSD";
private int USDStart = 1000;
private decimal Weight = .8m;
private int StartDaysAgo = 450;
private int EndDaysAgo = 1;
private decimal TargetPercent = .05m; // 5%
private decimal StopPercent = .02m; // 2%
private Resolution AlgoResolution = Resolution.Hour;
private int FastMAPeriod = 50;
private int SlowMAPeriod = 200;
// -- Application variables
private decimal Price; // Price of BTC
private decimal Holding; // BTC held in portfolio
private string SymbolBase; // Pair base. Ex: "BTC" from "BTCUSD"
private decimal PurchasePrice;
private decimal TradeDifference;
private decimal TargetPrice;
private decimal StopPrice;
private decimal USDHolding; // USD we are holding
private RollingWindow<decimal> FastMAValues;
private RollingWindow<decimal> SlowMAValues;
// -- Indicators
SimpleMovingAverage FastMA;
SimpleMovingAverage SlowMA;
// ALGO INITIALIZATION - Configures algo before running
public override void Initialize()
{
SetStartDate(DateTime.Today.AddDays(StartDaysAgo * -1).Year,
DateTime.Today.AddDays(StartDaysAgo * -1).Month,
DateTime.Today.AddDays(StartDaysAgo * -1).Day); // Set Start Date
SetEndDate(DateTime.Today.AddDays(EndDaysAgo * -1).Year,
DateTime.Today.AddDays(EndDaysAgo * -1).Month,
DateTime.Today.AddDays(EndDaysAgo * -1).Day); // Set End Date
SetCash(USDStart); // Set Strategy Cash
var Crypto = AddCrypto(Symbol, AlgoResolution); // Saves our Crypto pair info
SymbolBase = Crypto.BaseCurrencySymbol; // Sets the SymbolBase variable
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash); // Tells algo what brokerage model to use
FastMA = SMA(Symbol, FastMAPeriod, AlgoResolution);
SlowMA = SMA(Symbol, SlowMAPeriod, AlgoResolution);
FastMAValues = new RollingWindow<decimal>(2);
SlowMAValues = new RollingWindow<decimal>(2);
}
// ALGO RECEIVES NEW DATA - Algo logic goes here, occurs each time new data is received
public override void OnData(Slice data)
{
// Make sure our indicators are ready
if (!FastMA.IsReady) return;
if (!SlowMA.IsReady) return;
Price = data[Symbol].Price; // Saves the current price of the symbol
USDHolding = Portfolio.CashBook["USD"].Amount; // Get the USD we have currently
FastMAValues.Add(FastMA); // Saves Indicator values for later
SlowMAValues.Add(SlowMA); // Saves Indicator values for later
if (!Portfolio.Invested && USDHolding > 0) // If we are not currently invested and have cash
{
if(SlowMAValues.Count() > 1 && FastMAValues[0] > SlowMAValues[0] && FastMAValues[1] <= SlowMAValues[1]) // Our Fast MA just now crossed above the Slow MA
{
decimal CashToOrder = USDHolding * Weight;
decimal Quantity = Math.Round((CashToOrder / Price), 2);
MarketOrder(Symbol, Quantity);
Log($"Bought {SymbolBase} at {Price}. Goodluck!");
TargetPrice = Price + (Price * TargetPercent); // Set these while creating holdings to save target values
StopPrice = Price - (Price * StopPercent);
PurchasePrice = Price;
}
}
else if (Portfolio.Invested) // We are already invested
{
Holding = Portfolio.CashBook[SymbolBase].Amount; // Get the amount we are holding in Crypto
if(Price <= StopPrice) // If we are below our stop price
{
Sell(Symbol, Holding); // -- Sell, stop the losses.
TradeDifference = Price - PurchasePrice;
Log($"Sold {SymbolBase} at {Price}. Change in price of {TradeDifference} after buying.");
}
else if(Price >= TargetPrice) // If we are above our target price
{
Sell(Symbol, Holding); // -- Sell, take our profits
TradeDifference = Price - PurchasePrice;
Log($"Sold {SymbolBase} at {Price}. Change in price of {TradeDifference} after buying.");
}
}
}
}
}
namespace QuantConnect.Algorithm.CSharp
{
public class CryptoCrossover : QCAlgorithm
{
// -- User Settings
private string Symbol = "BTCUSD";
private int USDStart = 1000;
private decimal Weight = .8m;
private int StartDaysAgo = 450;
private int EndDaysAgo = 1;
private decimal TargetPercent = .05m; // 5%
private decimal StopPercent = .02m; // 2%
private Resolution AlgoResolution = Resolution.Hour;
private int FastMAPeriod = 50;
private int SlowMAPeriod = 200;
// -- Application variables
private decimal Price; // Price of BTC
private decimal Holding; // BTC held in portfolio
private string SymbolBase; // Pair base. Ex: "BTC" from "BTCUSD"
private decimal PurchasePrice;
private decimal TradeDifference;
private decimal TargetPrice;
private decimal StopPrice;
private decimal USDHolding; // USD we are holding
private RollingWindow<decimal> FastMAValues;
private RollingWindow<decimal> SlowMAValues;
// -- Indicators
SimpleMovingAverage FastMA;
SimpleMovingAverage SlowMA;
// ALGO INITIALIZATION - Configures algo before running
public override void Initialize()
{
SetStartDate(DateTime.Today.AddDays(StartDaysAgo * -1).Year,
DateTime.Today.AddDays(StartDaysAgo * -1).Month,
DateTime.Today.AddDays(StartDaysAgo * -1).Day); // Set Start Date
SetEndDate(DateTime.Today.AddDays(EndDaysAgo * -1).Year,
DateTime.Today.AddDays(EndDaysAgo * -1).Month,
DateTime.Today.AddDays(EndDaysAgo * -1).Day); // Set End Date
SetCash(USDStart); // Set Strategy Cash
var Crypto = AddCrypto(Symbol, AlgoResolution); // Saves our Crypto pair info
SymbolBase = Crypto.BaseCurrencySymbol; // Sets the SymbolBase variable
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash); // Tells algo what brokerage model to use
FastMA = SMA(Symbol, FastMAPeriod, AlgoResolution);
SlowMA = SMA(Symbol, SlowMAPeriod, AlgoResolution);
FastMAValues = new RollingWindow<decimal>(2);
SlowMAValues = new RollingWindow<decimal>(2);
}
// ALGO RECEIVES NEW DATA - Algo logic goes here, occurs each time new data is received
public override void OnData(Slice data)
{
// Make sure our indicators are ready
if (!FastMA.IsReady) return;
if (!SlowMA.IsReady) return;
Price = data[Symbol].Price; // Saves the current price of the symbol
USDHolding = Portfolio.CashBook["USD"].Amount; // Get the USD we have currently
FastMAValues.Add(FastMA); // Saves Indicator values for later
SlowMAValues.Add(SlowMA); // Saves Indicator values for later
if (!Portfolio.Invested && USDHolding > 0) // If we are not currently invested and have cash
{
if(SlowMAValues.Count() > 1 && FastMAValues[0] > SlowMAValues[0] && FastMAValues[1] <= SlowMAValues[1]) // Our Fast MA just now crossed above the Slow MA
{
decimal CashToOrder = USDHolding * Weight;
decimal Quantity = Math.Round((CashToOrder / Price), 2);
MarketOrder(Symbol, Quantity);
Log($"Bought {SymbolBase} at {Price}. Goodluck!");
TargetPrice = Price + (Price * TargetPercent); // Set these while creating holdings to save target values
StopPrice = Price - (Price * StopPercent);
PurchasePrice = Price;
}
}
else if (Portfolio.Invested) // We are already invested
{
Holding = Portfolio.CashBook[SymbolBase].Amount; // Get the amount we are holding in Crypto
if(Price <= StopPrice) // If we are below our stop price
{
Sell(Symbol, Holding); // -- Sell, stop the losses.
TradeDifference = Price - PurchasePrice;
Log($"Sold {SymbolBase} at {Price}. Change in price of {TradeDifference} after buying.");
}
else if(Price >= TargetPrice) // If we are above our target price
{
Sell(Symbol, Holding); // -- Sell, take our profits
TradeDifference = Price - PurchasePrice;
Log($"Sold {SymbolBase} at {Price}. Change in price of {TradeDifference} after buying.");
}
}
}
}
}
Jing Wu
This is a simple template. For details, please refer to this Github example
https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/BasicTemplateCryptoAlgorithm.py
Cai Shuhang
Thanks for your help!!
Cai Shuhang
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!