I modify the code to include ticksize adjustment for K200 options. The ticksize is 0.01 for price < 3.0. The ticksize is 0.05 when price >= 3.0. However, my strategy will do the adjustment when price >= 2.70.
Code:
using System;
using System.Drawing;
using OpenQuant.API;
using OpenQuant.API.Indicators;
public class MyStrategy : Strategy
{
private double Range;
private int Qty = 1;
private double High = 0;
private double Low = 0;
private int longshort = 1; // 1 is long, 0 is short
private bool CloseOnStop = true;
private double delta = 0;
private int ocaCount = 0;
private int n = 1;
private int n1 = 0;
private int n0 = 0;
private double PortfolioValue0 = 0;
private bool started = false;
private bool newlow = false;
private bool newhigh = false;
private int barcount = 0;
private double barclose = 0;
private double barlow = 0;
private double barhigh = 0;
private double barlowest = 999999.0;
private double barhighest = 0.0;
private double tickSize = 0.0001;
private int longshortdecimals = 1;
private int rangedecimals = 5;
private int qtydecimals = 1;
private bool getDecimals = false;
Order order1;
Order limitOrder;
Order stopOrder;
private double Value = 0;
private double PnL = 0;
private double NetPnL = 0;
private double Debt = 0;
private double CashFlow = 0;
private double NetCashFlow = 0;
public override void OnStrategyStart()
{
if (Instrument.TickSize != 0)
tickSize = Instrument.TickSize;
getDecimals = int.TryParse(Instrument.Description.Substring(0,1), out longshortdecimals);
if (getDecimals)
{
longshort = longshortdecimals; // 1 is long, 0 is short
}
getDecimals = int.TryParse(Instrument.Description.Substring(2,2), out rangedecimals);
if (getDecimals)
{
Range = tickSize*rangedecimals;
}
getDecimals = int.TryParse(Instrument.Description.Substring(5,5), out qtydecimals);
if (getDecimals)
{
Qty = qtydecimals;
}
PortfolioValue0 = Portfolio.GetValue();
Console.WriteLine("{0}, {1}", Instrument, PortfolioValue0);
started = false;
newlow = false;
}
public override void OnStrategyStop()
{
if (CloseOnStop)
{
if (HasPosition)
{
if (Position.Side == PositionSide.Long)
MarketOrder(OrderSide.Sell, Position.Qty).Send();
if (Position.Side == PositionSide.Short)
MarketOrder(OrderSide.Buy, Position.Qty).Send();
}
if (order1 != null)
{
order1.Cancel();
}
if (limitOrder != null)
{
limitOrder.Cancel();
}
if (stopOrder != null)
{
stopOrder.Cancel();
}
}
}
public override void OnBar(Bar bar)
{
DataManager.Add(Instrument, bar);
barcount ++;
barclose = bar.Close;
barhigh = bar.High;
barlow = bar.Low;
if (barcount > 1)
{
if ((barlow + tickSize) < barlowest)
{
barlowest = barlow;
newlow = true;
}
if ((barlow + tickSize) > barhighest)
{
barhighest = barhigh;
newhigh = true;
}
}
if (HasPosition)
{
PortfolioValue0 = Portfolio.GetValue();
Value = Position.GetValue();
PnL = Position.GetPnL();
NetPnL = Position.GetNetPnL();
Debt = Position.GetDebtValue();
CashFlow = Position.GetCashFlow();
NetCashFlow = Position.GetNetCashFlow();
// Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", Instrument, n, Value, PnL, NetPnL, Debt, CashFlow, NetCashFlow, PortfolioValue0);
}
if (!HasPosition && (barcount > 5))
{
if (!started)
{
started = true;
if (PnL >= 0) //previous trade taken profit, start from 1
{
n = 1;
n1 = 0;
if (Instrument.Currency == "KRW")
{
Console.WriteLine("{0}, Currency = {1}", Instrument, Instrument.Currency );
if (barhigh >= 2.70)
{
tickSize = 0.05;
}
else
{
tickSize = 0.01;
}
Range = tickSize*rangedecimals;
Range = Math.Round(Range/tickSize) * tickSize;
}
}
else
{
n0 = n;
n = n+n1;
n1 = n0;
}
if (longshort == 1)
{
Low = barhigh;
Low = Math.Round(Low/tickSize) * tickSize;
High = Low + Range;
High = Math.Round(High/tickSize) * tickSize;
}
else
{
High = barlow;
High = Math.Round(High/tickSize) * tickSize;
Low = High - Range;
Low = Math.Round(Low/tickSize) * tickSize;
}
delta = 2*Range;
barlowest = barlow;
barhighest = barhigh;
Low = Math.Round(Low/tickSize) * tickSize;
High = Math.Round(High/tickSize) * tickSize;
delta = Math.Round(delta/tickSize) * tickSize;
if (longshort == 1)
order1 = StopOrder(OrderSide.Buy, Qty*(n), High);
if (longshort == 0)
order1 = StopOrder(OrderSide.Sell, Qty*(n), Low);
order1.Send();
}
else
{
if ((longshort == 1) && newlow)
{
if ((n0 == 0) && (Instrument.Currency == "KRW"))
{
Console.WriteLine("{0}, Currency = {1}", Instrument, Instrument.Currency );
if (barhigh >= 2.70)
{
tickSize = 0.05;
}
else
{
tickSize = 0.01;
}
Range = tickSize*rangedecimals;
Range = Math.Round(Range/tickSize) * tickSize;
}
newlow = false;
Low = barlowest;
Low = Math.Round(Low/tickSize) * tickSize;
Range = tickSize*rangedecimals;
Range = Math.Round(Range/tickSize) * tickSize;
High = Low + Range;
High = Math.Round(High/tickSize) * tickSize;
delta = 2*Range;
delta = Math.Round(delta/tickSize) * tickSize;
Console.WriteLine("{0}, barlowest = {1}", Instrument, barlowest);
if (order1 != null)
{
order1.Cancel();
}
order1 = StopOrder(OrderSide.Buy, Qty*(n), High);
order1.Send();
}
if ((longshort == 0) && newhigh)
{
if ((Instrument.Currency == "KRW"))
{
Console.WriteLine("{0}, Currency = {1}", Instrument, Instrument.Currency );
if (barhigh >= 2.70)
{
tickSize = 0.05;
}
Range = tickSize*rangedecimals;
Range = Math.Round(Range/tickSize) * tickSize;
}
newhigh = false;
High = barhighest;
High = Math.Round(High/tickSize) * tickSize;
Range = tickSize*rangedecimals;
Range = Math.Round(Range/tickSize) * tickSize;
Low = High - Range;
Low = Math.Round(Low/tickSize) * tickSize;
delta = 2*Range;
delta = Math.Round(delta/tickSize) * tickSize;
Console.WriteLine("{0}, barhighest = {1}", Instrument, barhighest);
if (order1 != null)
{
order1.Cancel();
}
order1 = StopOrder(OrderSide.Sell, Qty*(n), Low);
order1.Send();
}
}
}
}
public override void OnPositionChanged()
{
if (HasPosition)
{
if (longshort == 1)
{
limitOrder = LimitOrder(OrderSide.Sell, Position.Qty, High + delta);
stopOrder = StopOrder (OrderSide.Sell, Position.Qty, Low);
}
else
{
stopOrder = StopOrder (OrderSide.Buy, Position.Qty, High);
limitOrder = LimitOrder(OrderSide.Buy, Position.Qty, Low - delta);
}
ocaCount++;
string id = Clock.Now.Ticks.ToString();
limitOrder.OCAGroup = id + ": " + Instrument.Symbol + " " + ocaCount;
stopOrder.OCAGroup = id + ": " + Instrument.Symbol + " " + ocaCount;
limitOrder.Send();
stopOrder.Send();
}
else
{
started = false;
}
}
}