Python programming language is getting quite popular among quants all around the globe. Following our customer's requests we have added Python (IronPython) support for QuantWeb
http://smartquant.com/quantweb.htmlCode:
import clr
clr.AddReference("clrtype")
clr.AddReference("System.Drawing")
clr.AddReference("SmartQuant")
import clrtype
from SmartQuant import *
from SmartQuant.Indicators import SMA
from System import DateTime
from System.Drawing import Color
class MyStrategy(InstrumentStrategy):
__metaclass__ = clrtype.ClrClass
entryEnabled = True
OCACount = 0
MoneyForInstrument = 100000
Qty = 100
Length1 = 14
Length2 = 50
StopOCALevel = 0.98
LimitOCALevel = 1.05
StopLevel = 0.05
StopType = StopType.Trailing
StopMode = StopMode.Percent
CrossoverExitEnabled = True
OCAExitEnabled = True
StopExitEnabled = True
def OnStrategyStart(self):
# Add money for current trading instrument's portfolio.
self.Portfolio.Account.Deposit(self.MoneyForInstrument, CurrencyId.USD, "Initial allocation")
# Set up indicators.
self.sma1 = SMA(self.Bars, self.Length1)
self.sma2 = SMA(self.Bars, self.Length2)
self.Group("Bars", "Pad", 0)
self.Group("Fills", "Pad", 0)
self.Group("Equity", "Pad", 1)
self.Group("SMA1", "Pad", 0)
self.Group("SMA1", "Color", Color.Green)
self.Group("SMA2", "Pad", 0)
self.Group("SMA2", "Color", Color.Red)
# Create log monitor groups.
self.Group("Close", "LogName", "Close")
self.Group("Close", "StrategyName", "MyStrategy")
self.Group("Close", "Symbol", self.Instrument.Symbol)
self.Group("Open", "LogName", "Open")
self.Group("Open", "StrategyName", "MyStrategy")
self.Group("Open", "Symbol", self.Instrument.Symbol)
self.Group("Position", "LogName", "Position")
self.Group("Position", "StrategyName", "MyStrategy")
self.Group("Position", "Symbol", self.Instrument.Symbol)
def OnBar(self, instrument, bar):
self.Bars.Add(bar)
# Log open close and position info to Strategy Monitor.
if (self.HasPosition(instrument)):
self.Log(self.Position.Side.ToString(), "Position")
else:
self.Log("None", "Position")
# Log bars.
self.Log(bar, "Bars")
if (self.sma1.Count == 0 or self.sma2.Count == 0):
return
# Log sma.
self.Log(self.sma1.Last, "SMA1");
self.Log(self.sma2.Last, "SMA2");
# Update performance.
self.Portfolio.Performance.Update();
# Log equity.
self.Log(self.Portfolio.Value, "Equity");
# Does the fast average cross over the slow average? If so, time to buy long.
cross = self.sma1.Crosses(self.sma2, bar.DateTime);
# We only allow one active position at a time.
if (self.entryEnabled):
# If price trend is moving upward, open a long position using a market order, and send it in.
if (cross == Cross.Above):
marketOrder = self.BuyOrder(instrument, self.Qty, "Entry")
self.Send(marketOrder)
# If one cancels all exit method is desired, we
# also issue a limit (profit target) order, and
# a stop loss order in case the breakout fails.
# The OCA exit method uses a real stop loss order.
# The Stop exit method uses a stop indicator.
# Use either the OCA or Stop method, not both at once.
if (self.OCAExitEnabled):
# Create and send a profit limit order.
profitTarget = self.LimitOCALevel * bar.Close
self.limitOrder = self.SellLimitOrder(instrument, self.Qty, profitTarget, "Limit OCA " + self.OCACount.ToString())
self.limitOrder.OCA = "OCA " + self.Instrument.Symbol + " " + self.OCACount.ToString()
self.Send(self.limitOrder)
# Create and send a stop loss order.
lossTarget = self.StopOCALevel * bar.Close
stopOrder = self.SellStopOrder(instrument, self.Qty, lossTarget, "Stop OCA " + self.OCACount.ToString())
stopOrder.OCA = "OCA " + self.Instrument.Symbol + " " + self.OCACount.ToString()
self.Send(stopOrder)
# Bump the OCA count to make OCA group strings unique.
self.OCACount = self.OCACount + 1
self.entryEnabled = False
# Else if entry is disabled on this bar, we have an open position.
else:
# If we are using the crossover exit, and if the fast
# average just crossed below the slow average, issue a
# market order to close the existing position.
if (self.CrossoverExitEnabled):
if (cross == Cross.Below):
marketOrder = self.SellOrder(instrument, self.Qty, "Crossover Exit")
self.Send(marketOrder)
def OnPositionOpened(self, position):
# If we want to exit trades using the Stop method, set a
# a trailing stop indicator when the position is
# first opened. The stop indicator is not a stop loss
# order that can be executed by a broker. Instead, the stop
# just fires the OnStopExecuted event when it it triggered.
if (self.StopExitEnabled):
self.AddStop(Stop(self, position, self.StopLevel, self.StopType, self.StopMode))
def OnPositionClosed(self, position):
# When a position is closed, cancel the limit and stop
# orders that might be associated with this position.
# But only cancel if the order has not been filled or
# not been cancelled already.
if (self.OCAExitEnabled and not(self.limitOrder.IsFilled or self.limitOrder.IsCancelled)):
self.Cancel(self.limitOrder)
# Allow entries once again, since our position is closed.
self.entryEnabled = True
def OnFill(self, fill):
# Add fill to group.
self.Log(fill, "Fills")
def OnStopExecuted(self, stop):
# If our trailing stop indicator was executed,
# issue a market sell order to close the position.
marketOrder = self.SellOrder(self.Instrument, self.Qty, "Stop Exit")
self.Send(marketOrder)