How to replace order in pine script? - algorithmic-trading

Is there an option to set on pine script such that when a new order command is submitted, it would cancel the previous unfulfilled one?
if secondbuycond and firstbuycond and (time >= testPeriodStart and time <= testPeriodStop)
strategy.entry("buy", strategy.long, stop=((valuewhen(firstbuycond,open,0))*x))
strategy.exit("Trailing Stop", "buy", trail_points= trailPoints, trail_offset= trailOffset, when= testType == 'Trail Points')

//#version=3
strategy("My Strategy", overlay=true)
limit_price = 0
ts = timestamp(2018, 11, 13, 0, 0)
if (time > ts)
limit_price := 999
ts2 = timestamp(2018, 11, 22, 0, 0)
// here new price will be set to replace an order
if time > ts2
limit_price := 988
strategy.entry("BUY", strategy.long, limit=limit_price)
It's possible to replace just making an entry again with new price, but both entries must differ only in price (so the order ID and direction must be the same)
I tested the stragegy above in CHMF, dayly resolution.

Related

Pine script strategy open at second open candel and no when EMA crossover

whith this strategy i would like to have the open trade in exactly moment of ema crossovers, but all time I have open trade when the next candle open.
It is often a problem because at the ema crossovers I have a bullish push but at the opening of the next candle can be bearish causing the loss of the trade.
Can you help me? thanks
//#version=5
strategy(title='MARCO 18/20', overlay=true)
// STEP 1:
// Make inputs that set the take profit % (optional)
FastPeriod = input.int(title='Fast MA Period', defval=18, group='Moving Average')
SlowPeriod = input.int(title='Slow MA Period', defval=20, group='Moving Average')
TPPerc = input.float(title='Long Take Profit (%)', defval=0.11, group='TP & SL')
SLPerc = input.float(title='Long Stop Loss (%)', defval=4.4, group='TP & SL')
TP_Ratio = input.float(title='Sell Postion Size % # TP', defval=100, group='TP & SL', tooltip='Example: 100 closing 100% of the position once TP is reached') / 100
// Calculate moving averages
fastSMA = ta.sma(close, FastPeriod)
slowSMA = ta.sma(close, SlowPeriod)
// Calculate trading conditions
enterLong = ta.crossover(fastSMA, slowSMA)
// Plot moving averages
plot(series=fastSMA, color=color.new(color.green, 0), title='Fase MA')
plot(series=slowSMA, color=color.new(color.red, 0), title='Slow MA')
// STEP 2:
// Figure out take profit price
percentAsPoints(pcnt) =>
strategy.position_size != 0 ? math.round(pcnt / 100.0 * strategy.position_avg_price / syminfo.mintick) : float(na)
percentAsPrice(pcnt) =>
strategy.position_size != 0 ? (pcnt / 100.0) * strategy.position_avg_price : float(na)
current_position_size = math.abs(strategy.position_size)
initial_position_size = math.abs(ta.valuewhen(strategy.position_size[1] == 0.0, strategy.position_size, 0))
TP = strategy.position_avg_price + percentAsPoints(TPPerc) * syminfo.mintick * strategy.position_size / math.abs(strategy.position_size)
SL = strategy.position_avg_price - percentAsPoints(SLPerc) * syminfo.mintick * strategy.position_size / math.abs(strategy.position_size)
// Submit entry orders
if enterLong
strategy.entry(id='Long', direction=strategy.long)
// STEP 3:
// Submit exit orders based on take profit price
if strategy.position_size > 0
strategy.exit('TP', from_entry='Long', limit=TP, stop=SL)
// Plot take profit values for confirmation
plot(series=strategy.position_size > 0 ? TP : na, color=color.new(color.green, 0), style=plot.style_circles, linewidth=1, title='Take Profit')
plot(series=strategy.position_size > 0 ? SL : na, color=color.new(color.red, 0), style=plot.style_circles, linewidth=1, title='Stop Loss')
Pine script makes the calculations (runs your code) when the bar closed. After that, if your code has an entry, you can enter a trade on the next trade. Since the bar where you run the script is already closed, the trade will be made on the next trade - open price of the next bar. This is basically how real trade will work, since you can't check a trade that already happened and then decide that this trade is good for you or not. You will have to enter on the next trade.
You can override this if you wish.
try enabling in settings: recalculate strategy on each tick

What approach to be followed to code this in Pinescript

Buy signal to be generated if any candle closes above a line (let's say EMA20)
Stoploss should get triggered only if any subsequent candle closes below it (buy signal candle).
All candles formed prior to the "buy signal" candle should have a closing below EMA20.
Inversely for sell signal also.
I do not wish to know the code, only the logic would suffice for backtesting.
Thanks
You can use ta.crossover(close, ema20) to check that
Store entry price in a var, and check if the price closes below it when you are in a trade
Use a counter to count when the price is below ema20
Below code should do it or at least give you an idea
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © vitruvius
//#version=5
indicator("My script", overlay=true)
ema_len = input.int(20)
below_ema_no = input.int(4)
_ema = ta.ema(close, ema_len)
ema_co = ta.crossover(close, _ema)
var below_ema_cnt = 0
below_ema_cnt := close < _ema ? below_ema_cnt + 1 : 0 // Increase the counter if it closed below EMA20, reset oterwise
var is_long = false
var float buy_price = na
is_buy = not is_long and ema_co and (below_ema_cnt[1] >= below_ema_no) // Buy when we are not already long, ema crossover takes place, last n candles below ema20
is_long := not is_long ? is_buy ? true : false : is_long // Update is_long flag
buy_price := not is_long[1] and is_long ? close : buy_price // New position: Store buy price (close price)
is_sl = is_long ? close < buy_price : false // SL is hit if price closes below entry price
is_long := is_sl ? false : is_long // Update is_long flag in case SL is hit
buy_price := is_sl ? na : buy_price // Reset buy_price in case SL is hit
plot(_ema, "EMA", color.yellow, 2)
plotshape(is_buy, "Buy", shape.triangleup, location.belowbar, color.green, 0, "Buy", size=size.small)
plotshape(is_sl, "SL", shape.triangledown, location.abovebar, color.red, 0, "SL", size=size.small)
plot(buy_price, "Buy Price", color.white, 1, plot.style_circles)

Golang - Find month and day of month from YearDay int32

I have a fixed data structure given to me that has the fields YearDay and TimeOfDay. YearDay is the number of days that have passed in the current year, TimeOfDay is the number of seconds that have passed in the current day (up to 86400). YearDay is an int32, while TimeOfDay is a float64.
I want to convert this to time.Now().UnixNano() form but am unsure how to convert it. The time module has a YearDay(), but no inverse function given an yearDay (int32) (and probably a year), to give me the month and day in the month.
Ideally I'd like to somehow parse
d := time.Date(time.Year(), month, day, hour, min, sec, ms, time.UTC)
where month, day, hour, min, sec, ms was somehow predetermined, or something of equivalent that I can convert easily to any form I'd like (but mainly UnixNano()).
My best imagination would be a complicated switch statement that subtracted 31, 28(29), 30, 31 ... and to see when the int is finally negative to find the month and day, but it would have to be two switch statements with a leap year check to choose which switch block to use, while doing several remainder calculations on TimeOfDay. Is there a simpler and cleaner way?
Edit: I ended up making the following function while playing around with it, but I'll definitely be using Icza's solution. Nice to know days can overflow. Thanks!
func findMonthAndDay(yearDay int32) (int32, int32) {
year := time.Now().Year()
isLeapYear := year%400 == 0 || year%4 == 0 && year%100 != 0 // Calculates if current year is leapyear
// Determines which array to send to for loop
var monthsOfYear [12]int32
if isLeapYear {
monthsOfYear = [12]int32{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
} else {
monthsOfYear = [12]int32{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
}
var currentMonth int32
var currentDayInMonth int32
// Loop through array of months
for i := range monthsOfYear {
// If yearDay - next month #OfDays positive, not correct month
if yearDay-monthsOfYear[i] > 0 {
// Subtract month #OfDays and continue
yearDay = yearDay - monthsOfYear[i]
} else {
currentMonth = int32(i + 1) // Month found (+1 due to index at 0)
currentDayInMonth = yearDay // Remainder of YearDay is day in month
break
}
}
return currentMonth, currentDayInMonth
}
You may use Time.AddDate() to add the number of days to a time.Time value. It is OK to add days greater than 31, the implementation normalizes the result.
And convert TimeOfDay to time.Duration and use Time.Add() to add it. When converting to time.Duration, we may multiply it by 1e9 to get number of nanoseconds, so fractional seconds will be retained.
Example:
t := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(t)
var yearDay int32 = 100
var timeOfDay float64 = 70000.5
t = t.AddDate(0, 0, int(yearDay))
t = t.Add(time.Duration(timeOfDay * 1e9))
fmt.Println(t)
fmt.Println("Unix:", t.Unix())
fmt.Println("UnixNano:", t.UnixNano())
Output (try it on the Go Playground):
2020-01-01 00:00:00 +0000 UTC
2020-04-10 19:26:40.5 +0000 UTC
Unix: 1586546800
UnixNano: 1586546800500000000

How do I add a pre determined stop loss and take profit?

This is my first post. I am a prop trader and really trying hard to learn how to code as it would take my trading to another level. It is quite overwhelming at the beginning, but working on things that have use to me is motivating.
I have a script for trading view that I would like to edit. I have tried myself but I am obviously doing something wrong. Any help would be very much appreciated.
I just want to add my own pre determined stop loss and take profit for the strategy, The code is below:
strategy(title="Z-Score Strategy", shorttitle="Z-Score Strategy")
Period = input(20, minval=1)
Trigger = input(0)
reverse = input(false, title="Trade reverse")
hline(Trigger, color=purple, linestyle=line)
xStdDev = stdev(close, Period)
xMA = sma(close, Period)
nRes = (close - xMA) / xStdDev
pos = iff(nRes > Trigger, 1,
iff(nRes < Trigger, -1, nz(pos[1], 0)))
possig = iff(reverse and pos == 1, -1,
iff(reverse and pos == -1, 1, pos))
if (possig == 1)
strategy.entry("Long", strategy.long)
if (possig == -1)
strategy.entry("Short", strategy.short)
barcolor(possig == -1 ? red: possig == 1 ? green : blue )
plot(nRes, color=blue, title="Z-Score")
You should close the position via strategy.exit: https://www.tradingview.com/pine-script-reference/v4/#fun_strategy{dot}exit
//#version=4
strategy("strategy")
strategy.entry("entryId", strategy.long)
strategy.exit("exitId", "entryId", profit = 5, stop=7)

Linq duplicate removal with a twist

I got a list that contains al the status items of each order.
The problem that i have is that i need to remove all the items of which the status -> logdate combination is not the highest.
e.g
var inputs = new List<StatusItem>();
//note that the 3th id is simply a modifier that adds that amount of secs
//to the current datetime, to make testing easier
inputs.Add(new StatusItem(123, 30, 1));
inputs.Add(new StatusItem(123, 40, 2));
inputs.Add(new StatusItem(123, 50, 3));
inputs.Add(new StatusItem(123, 40, 4));
inputs.Add(new StatusItem(123, 50, 5));
inputs.Add(new StatusItem(100, 20, 6));
inputs.Add(new StatusItem(100, 30, 7));
inputs.Add(new StatusItem(100, 20, 8));
inputs.Add(new StatusItem(100, 30, 9));
inputs.Add(new StatusItem(100, 40, 10));
inputs.Add(new StatusItem(100, 50, 11));
inputs.Add(new StatusItem(100, 40, 12));
var l = from i in inputs
group i by i.internalId
into cg
select
from s in cg
group s by s.statusId
into sg
select sg.OrderByDescending(n => n.date).First()
;
edit: for convenience im adding the class definition as well.
public class StatusItem
{
public int internalId;
public int statusId;
public DateTime date;
public StatusItem(int internalId, int statusId, int secMod)
{
this.internalId = internalId;
this.statusId = statusId;
date = DateTime.Now.AddSeconds(secMod);
}
}
This creates a list that returnes me the following:
order 123 status 30 date 4/9/2010 6:44:21 PM
order 123 status 40 date 4/9/2010 6:44:24 PM
order 123 status 50 date 4/9/2010 6:44:25 PM
order 100 status 20 date 4/9/2010 6:44:28 PM
order 100 status 30 date 4/9/2010 6:44:29 PM
order 100 status 40 date 4/9/2010 6:44:32 PM
order 100 status 50 date 4/9/2010 6:44:31 PM
This is ALMOST correct. However that last line which has status 50 needs to be filtered out as well because it was overruled by status 40 in the historylist. U can tell by the fact that its date is lower then the "last" status-item with the status 40.
I was hoping someone could give me some pointers because im stuck.
Edit: Final complete solution:
var k = from sg in
from i in inputs
group i by i.internalId
into cg
select
from s in cg
group s by s.statusId
into sg
select sg.OrderByDescending(n => n.date).First()
from s in sg
where s.date >= sg.Where(n => n.statusId <= s.statusId).Max(n => n.date)
group s by s.internalId
into si
from x in si
select x;
Looks like you don't currently have anything performing the filtering you need for the date, so you'd need to do something about that.
Off hand, something like this would perform the additional filtering:
var k = from sg in l
from s in sg
where s.date >= sg.Where(n => n.statusId <= s.statusId).Max(n => n.date)
group s by s.internalId;
Haven't tested it, so the grouping may not be what you want, and the comparisons may be reversed, but something like that should filter. >= and <= instead of > or < should mean that the status will always be compared to itself and not have to deal with empty set in aggregate issues.
It's not exactly in the same form you have, but it does give the correct result. I made a status item class with i, j, and k properties. Not sure what names you used for them.
var keys = inputs.Select(
input =>
new { i = input.i, j = input.j })
.Distinct();
var maxes = keys.Select(
ints =>
inputs.First(
input =>
input.i == ints.i
&& input.j == ints.j
&& input.k == inputs.Where(
i =>
i.i == ints.i
&& i.j == ints.j
).Select(i => i.k).Max()));

Resources