How to filter out signal repetition when you are using IIF(BUY,,) condition on a 5 min chart since Buy is true for each tick in 5 min candle - formula

I've created an AFL script that sends Buy, Stoploss, and Target values directly to my telegram with the help of a telegram bot. I've made it call the telegram sender function when the buy is true. But the problem is that since buy will be true for a whole candle so when I switch to for example 5 minute candle it sends me that buy signal 5 times (since I'm backtesting with a 1minute bar replay)
I tried using additional variables to set the telegram parameters value to zero when buy is not true and then process telegram sender only when the set parameter has non zero value, but still since buy will be true for the whole candle so the parameter is getting non-zero value for each tick for if the tick belonging to the same candle. For your reference here is the complete code. (With Bot API's removed)
_SECTION_BEGIN("5min EMA Longing");
FirstTradeTime = 094500;
LastTradeTime = 151500;
function writecsv( pricetowrite, wrtitethis )
{
if (StrFind(pricetowrite,"0.000"))
{
}
else
{
fh = fopen( "C:\\Users\\<username>\\Desktop\\newfile.csv", "a");
if(fh)
{
fputs(wrtitethis+"\n", fh );
fclose(fh);
ih = InternetOpenURL("https://api.telegram.org/bot<ChatID>:<API>/sendMessage?chat_id=1487299238&text="+wrtitethis);
InternetClose(ih);
}
else
{
printf("Error opening file");
}
}
}
//Current candle data
CandleOpen = TimeFrameGetPrice("O",in5Minute); //as it is fixed
CandleHigh = TimeFrameGetPrice("H",in5Minute); //as it is fixed
CandleLow = TimeFrameGetPrice("L",in5Minute); //as it is fixed
CandleClose = TimeFrameGetPrice("C",in5Minute); //as it is fixed
//Prev candle's data
PrevCanOpen = TimeFrameGetPrice("H",in5Minute,-1);
PrevCanHigh = TimeFrameGetPrice("H",in5Minute,-1);
PrevCanLow = TimeFrameGetPrice("L",in5Minute,-1);
PrevCanClose = TimeFrameGetPrice("C",in5Minute,-1);
Ema5 = ref(EMA(Close,5),-1); //5 period EMA
HighNotLow = PrevCanHigh-PrevCanLow;
Ema20 = EMA(close,20);
Rsi15 = RSI(14);
EMA20_Slope = Ema20 - ref(EMA(Close,20),-6);
//EMA20_Slope = 0;
indicator1 = PrevCanOpen<Ema5 AND PrevCanHigh<Ema5 AND PrevCanLow<Ema5 AND PrevCanClose<Ema5 AND CandleHigh>=PrevCanHigh; //main 5EMA strategy
indicator2 = EMA20_Slope>=0; //20 EMA slope or RSI indicating buy zone
BUY = indicator1 AND indicator2 AND HighNotLow>0 AND (TimeNum() >=FirstTradeTime AND TimeNum()<= LastTradeTime);
BuyPrice = HighestSince(Buy,Ref(H,-1));
stopLevelLong = ValueWhen(Buy, Ref(Low,-1));
PriceBuy = ValueWhen(Buy, BuyPrice); //entry price
stopAmountLong = PriceBuy-stopLevelLong;
targetAmountLong = 2*stopAmountLong;
Stoploss = stopAmountLong;
Target = targetAmountLong;
Plot(PriceBuy ,"Bought Price",colorGreen); //drawing entry price
Plot(PriceBuy-Stoploss ,"Stoploss",colorAqua); //drawing entry price
Plot(PriceBuy+Target ,"Target",colorYellow); //drawing entry price
ApplyStop(Type=0,Mode=2,Amount=Stoploss);
ApplyStop(Type=1,Mode=2,Amount=Target);
Sell = (((HighestSince(Buy,H)>PriceBuy+Target) OR (LOWESTSince(Buy,L)<PriceBuy-Stoploss)) AND (TimeNum() >=FirstTradeTime AND TimeNum()<= LastTradeTime)) OR TimeNum()>= LastTradeTime;
BUY = ExRem(BUY,Sell);
timenow = ValueWhen(Buy, TimeNum());
priceto = IIf(Buy,PriceBuy,null);
timenow = NumToStr(timenow,1);
timenow = StrReplace(timenow,",",".");
//logging
wrtitethis =Name()+" "+timenow +", BUY: "+NumToStr(PriceBuy)+", SL: "+NumToStr(PriceBuy-Stoploss)+", TG: "+NumToStr(PriceBuy+Target);
writecsv( NumToStr(LastValue(priceto)),wrtitethis);
//logging
Sell = ExRem(Sell,buy);
PlotShapes(IIf(Buy,shapeUpArrow,shapeNone),colorYellow,0,L,offset=-50);
PlotShapes(IIf(Sell AND (HighestSince(Buy,H)>PriceBuy+Target),shapedownArrow,shapeNone),colorGreen,0,H,offset=-50);
PlotShapes(IIf(Sell AND (LOWESTSince(Buy,L)<PriceBuy-Stoploss),shapedownArrow,shapeNone),colorRed,0,H,offset=-50);
PlotShapes(IIf(Sell AND TimeNum()>= LastTradeTime,shapedownArrow,shapeNone),colorAqua,0,H,offset=-50);
//Show bar index on selection
bi = BarIndex();
sar1 = SAR(0.01);
sarsigs = C < sar1 AND Ref(C,-1) > Ref(sar1,-1);
// Here I changed SelectedValue() to LastValue()
lastSarSiggBarNum = LastValue(ValueWhen(sarsigs, bi));
_TRACE("Last Bar Num for sarsigs: " + lastSarSiggBarNum);
PlotText(StrFormat("%1.0f", lastSarSiggBarNum), lastSarSiggBarNum, sar1[lastSarSiggBarNum], colorWhite, colorRed);
currentlySelectedBarNum = SelectedValue(bi);
_TRACE("Currently selected BarNum " + currentlySelectedBarNum);
// plot the current bar text at the close price level
PlotText(StrFormat("%1.0f", currentlySelectedBarNum), currentlySelectedBarNum, C[currentlySelectedBarNum], colorBlack, colorAqua, 10);
//Show bar index on selection
_SECTION_END();

Related

Plot a shape on previous week's high in pinescript

Trying to plot a shape on the previous week's high, but having difficulty getting it to plot. Hope someone can help here
indicator("My script", overlay = true)
previousWeekHigh = request.security(syminfo.tickerid, 'W', high[1],lookahead=barmerge.lookahead_on, gaps = barmerge.gaps_off)
isNewWeek = timeframe.change("W")
anchor_point() =>
float anchor = na
if isNewWeek
anchor := previousWeekHigh
anchor
anchorBar = anchor_point()
plotshape(anchorBar, style=shape.xcross)```
You cannot really use the plotshape() for this purpose as the position of the weekly high bar will be dynamic.
I would just use two var variables, one for the price and one for the "bars since" count. You don't even need the security() here.
Here is an example:
//#version=5
indicator("My script", overlay=true)
is_new_week = ta.change(time("W"))
bgcolor(is_new_week ? color.new(color.blue, 85) : na)
var label weekly_high_lbl = label.new(na, na, "Weekly\nHigh", yloc=yloc.abovebar, style=label.style_label_down, color=color.green, textcolor=color.white)
var line weekly_high_line = line.new(na, na, na, na, extend=extend.right, color=color.green)
var float weekly_high_price = na
var int weekly_high_barssince = 0
if (is_new_week)
// Update the label and line first
label.set_xy(weekly_high_lbl, bar_index - weekly_high_barssince, weekly_high_price)
line.set_xy1(weekly_high_line, bar_index - weekly_high_barssince, weekly_high_price)
line.set_xy2(weekly_high_line, bar_index, weekly_high_price)
// Reset the variables
weekly_high_price := high
weekly_high_barssince := 0
else
// Check for new high
if (high >= weekly_high_price)
weekly_high_price := high
weekly_high_barssince := 1
else
weekly_high_barssince := weekly_high_barssince + 1 // Increase the counter

Google Earth Engine: Extract second largest value from annual observations?

In Google Earth Engine, is it possible to extract the annual second largest and second smallest value and construct an imagecollection?
Apparently, there is no build-in reducer for this purpose.
Here is my code for getting the min, please guide me on how to get the second max and min.
Thank you!
Here is the code:
var startDate = ee.Date('2001-01-01'); // set start time for analysis
var endDate = ee.Date('2021-12-31'); // set end time for analysis
// calculate the number of year to process
var nyears = ee.Number(endDate.difference(startDate,'year'));
//init a time band
var createTimeBand= function(image) {
return image.addBands(image.metadata('system:time_start')
.divide(1e18))
// .divide(1000*60*60*24*365))
}
var sst = ee.ImageCollection('MODIS/006/MOD11A1').select('LST_Day_1km')
.filterDate(startDate, endDate)
.map(createTimeBand)
var byyearMin = ee.ImageCollection(
// map over each month
ee.List.sequence(0,nyears).map(function (n) {
// calculate the offset from startDate
var ini = startDate.advance(n,'year');
// advance just one month
var end = ini.advance(1,'year');
// filter and reduce
return sst.filterDate(ini,end)
.select(0).min()
// .sort('LST_Day_1km').reverse().first()
.multiply(0.02)
.subtract(273.15)
.set('system:time_start', ini.millis());//convert time to number
}));
var startDate = ee.Date('2001-01-01'); // set start time for analysis
var endDate = ee.Date('2021-12-31'); // set end time for analysis
// calculate the number of year to process
var nyears = ee.Number(endDate.difference(startDate,'year'));
//init a time band
var createTimeBand= function(image) {
return image.addBands(image.metadata('system:time_start')
.divide(1e18))
// .divide(1000*60*60*24*365))
}
var sst = ee.ImageCollection('MODIS/006/MOD11A1').select('LST_Day_1km')
.filterDate(startDate, endDate)
//.map(createTimeBand)
var byyearMin = ee.ImageCollection(
// map over each month
ee.List.sequence(0,nyears).map(function (n) {
// calculate the offset from startDate
var ini = startDate.advance(n,'year');
// advance just one month
var end = ini.advance(1,'year');
var sortedDays = sst.filterDate(ini,end)
.sort('LST_Day_1km')
.toList(sst.size())
var secondLargest = ee.List(sortedDays.get(1))
var secondSmallest = ee.List(sortedDays.get(-1))
var collection = ee.Image(secondLargest)
.addBands(secondSmallest).rename(['secondLargest', 'secondSmallest'])
.multiply(0.02)
.subtract(273.15)
return collection
.set('system:time_start', ini.millis()) //convert time to number
.set('Date', ee.Date(ini))
}));
print(byyearMin)

Working with Date, Time in Google Apps Script

I need help with some quick coding with google apps script, linking to my googlesheets spreadsheet.
In the googlespreadsheets, I have a cell with the value “26-Jun-2020”. It is a date.
I want to use google apps script to calculate the number of days difference between that date (“26-Jun-2020”) and today’s day, but it won’t do the calculation for me somehow.
If I print only “expiry_date[i]” using Logger.log(expiry_date[i]), it will provide the output “Fri Dec 17 2021 01:00:00 GMT-0500 (Eastern Standard Time) “
function Put_Options_Expiry_Alert() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Long equity (sell puts)");
//var timeZone = AdsApp.currentAccount().getTimeZone(); //Get timezone of current spreadsheet
var status = sheet.getRange("F:F").getValues();
var expiry_date = sheet.getRange("M:M").getValues();
var potential_capitaloutlay_USD = sheet.getRange("Z:Z").getValues();
Logger.log("Length of status = " + status.length);
Logger.log("Length of expiry_date = " + expiry_date.length);
Logger.log("Length of potential_capitaloutlay_USD = " + potential_capitaloutlay_USD.length);
for (var i = 0; i < status.length; i++) {
if (status[i] == "Entered") { //Evaluate if this is a live Put position
//Calculate the time difference of two dates using date2. getTime() – date1. getTime();
//Calculate the no. of days between two dates, divide the time difference of both the dates by no. of milliseconds in a day (1000*60*60*24)
Logger.log("expiry date is = "+expiry_date[i]);
Logger.log("today's date is = "+Date());
var days_to_expiry = dateDiffInDays(expiry_date[i],Date());
Logger.log(days_to_expiry);
}
}
}
// Function that returns the number of days difference between DateA and DateB
// DateA and DateB are javascript Date objects
function dateDiffInDays(DateA, DateB) {
var milliseconds_per_day = 1000 * 24 * 60; // number of milliseconds in a day
const utcA = Date.UTC(2021, DateA.getMonth(), DateA.getDate());
const utcB = Date.UTC(2020, DateB.getMonth(), DateB.getDate());
return Math.floor((utc2 - utc1) / milliseconds_per_day);
}
function timeDiffDays(Start, End) {
var day = 86400000;
var t1 = new Date(Start).valueOf();
var t2 = new Date(End).valueOf();
var d = t2 - t1;
return Math.floor(d / day);
}

Automatically remove R6 object

I have created a bank account class with the R6 package . It has a balance that is private (not accessible after generation) and methods to withdraw and deposit a certain amount as well as a print method. (Hadley Wickham 14.3.3)
BankAccount <- R6::R6Class("BankAccount", public = list(
# Functions to withdraw and deposit.
deposit = function(amount){
private$balance <- private$balance + amount
},
withdraw = function(amount){
if (amount < private$balance){
private$balance <- private$balance - amount
}
else {
stop("Amount withdrawn is greater than available balance by", -(private$balance - amount))
}
},
initialize = function(initial_balance){
private$balance <- initial_balance
},
print = function(){
cat("Bank balance is equal to", private$balance)
}
),
private = list(
balance = NULL
)
)
Currently, if I create a new R6 object and call the withdraw function with an amount greater than its initial balance, the function will stop and print a message. Instead, I would like the newly created object to be directly removed. How can I achieve this?

IDL: Button Widget stops updating after one push

I'm pretty new to IDL and as a way to learn I have tried to create a number guessing game. I have a Widget with three buttons: One that tells the program the number you are thinking of is larger than the one the computer asks about, one if it's smaller and one if it's correct.
My problem is that once you have pushed i.e. the larger button, if you press it again it won't do anything. E.g. the program starts to guess 500, if I press larger it guesses 750. If I now press larger again, the program doesn't respond.
My code is like this:
PRO test1_event, ev
WIDGET_CONTROL, ev.top, GET_UVALUE = stash
minimum = 0
maximum = 1000
IF (ev.Id EQ largerbutton) THEN BEGIN
minimum = (minimum+maximum)/2
maximum = maximum
ENDIF
IF (ev.Id EQ smallerbutton) THEN BEGIN
maximum = (minimum+maximum)/2
minimum = minimum
ENDIF
IF (ev.Id EQ correctbutton) THEN BEGIN
help2 = string('I got it!') ;This prints to a text widget
ENDIF
END
PRO test1
wBase = WIDGET_BASE(X_SCROLL_SIZE = 512, Y_SCROLL_SIZE = 512)
;wDraw = WIDGET_WINDOW(wBase, X_SCROLL_SIZE = 512, Y_SCROLL_SIZE = 512)
Lower = WIDGET_BUTTON(wBase, VALUE = 'Smaller', XOFFSET = 60, YOFFSET = 250)
Higher = WIDGET_BUTTON(wBase, VALUE = 'Larger', XOFFSET = 225, YOFFSET = 250)
Correct = WIDGET_BUTTON(wBase, VALUE = 'Correct', XOFFSET = 380, YOFFSET = 250)
minimum = 0
maximum = 1000
help1 = string('Please think of a number between' + string(minimum) + ' and ' + string(maximum))
help2 = string('Is your number ' + string((minimum + maximum)/2) + '?')
wText = WIDGET_TEXT(wBase, VALUE = ['Welcome to my little game. I will now try and guess a number you are thinking of.'], XSIZE = 63,XOFFSET = 50, YOFFSET = 100)
wText1 = WIDGET_TEXT(wBase, VALUE = help1, XSIZE = 63,XOFFSET = 50, YOFFSET = 120)
wText2 = WIDGET_TEXT(wBase, VALUE = help2, XSIZE = 63,XOFFSET = 50, YOFFSET = 140)
stash = {text1:wText, text2:wText1, text3:wText2, $
lower:Lower, higher:Higher, correct:Correct, minimum:minimum, maximum:maximum}
WIDGET_CONTROL, wBase, SET_UVALUE = stash, /REALIZE
XMANAGER, 'test1', wBase
end
I have tried using a while loop and also REPEAT, but then the program just goes right up to 999 if I press the larger button and to 0 if I press the smaller.
Any ideas to what I can do?
EDIT: Added the rest of the program
I think the buttons are working fine but your event handler doesn't actually do anything. First, I needed to change largerbutton, smallerbutton, and correctbutton to be stash.higher, stash.lower, stash.correct. Then, your code calculates the new minimum & maximum but it doesn't actually do anything with them.
I put a print statement into the event code and it's definitely getting the button presses.
In your event handler you probably want to use widget_control to update the text box with the new guess.

Resources