Is there a way in Amibroker backtest to specify buy price? - amibroker

Is there a way to place buy order at a certain value?
I am trying to buy at the break of previous day high on a 5 min tf:
DayH = TimeFrameGetPrice("H", inDaily, -1); // yesterdays high
DayL = TimeFrameGetPrice("L", inDaily, -1); // low
DayC = TimeFrameGetPrice("C", inDaily, -1); // close
DayO = TimeFrameGetPrice("O", inDaily); // current day open
Buy = H >= DayH AND DayO < DayH;
BuyPrice = DayH;
But I am not able to get the buy price similar to yesterday's high, its always something more or less

Use SetTradeDelays()
Buy = High
SetTradeDelays(-1,-1,-1,-1);

Related

Amibroker AFL first 15min candle High

I want to find high of the first 15 min candle.
I am using the below code.
bi = BarIndex();
arrayitem = SelectedValue(bi) -bi[0];
firstbarHigh = High[arrayitem ];
This code is giving me the CLOSE price for the 1st candle. I want High price of the first 15min candle.
Plz help me.
Check this out
newday = Day() != Ref(Day(),-1); //check if new day or not
starttime = ValueWhen(newday,TimeNum());
IBendtime = starttime+1500;
minh = ValueWhen(newday,TimeFrameGetPrice("H",in5Minute*3));
minl = ValueWhen(newday,TimeFrameGetPrice("L",in5Minute*3));

Google Earth Engine - counts days of the longest dry period in a time period

I'm trying to map the max number of consecutive days with rain <1 mm in Google Earth Engine.
This is the link to the code
https://code.earthengine.google.com/22b5c20d2700a2ffb5989f892838ac58
First I reclassify the collection with 0 if rain <=1 and 1 if >1.
Then I run the code that should count the days of the longest dry period, but it is able to do so only if the dry period reach the end of the time period.
For instance if I am looking for the longest dry period in 4 days timestep i get the following series:
rain days 1 2 3 4 output
0,0,1,1 = 0 dry days
0,1,0,0 = 2 dry days
0 = rain<=1 and
1 = rain>1 (as per the first step)
Does anyone can help in solving this?
Thanks
I don't think you were far off in your code that you provided. To keep track of the dry spells you have to use .iterate(). I took a stab at your application in a little different way where instead of classifying the data before the iteration, I calculate which pixels are dry each day and carry over the accumulated days that a pixel is dry, otherwise it is set to zero:
// DATA
var collection = ee.ImageCollection("UCSB-CHG/CHIRPS/DAILY");
// Define time range
var startyear = 2000;
var endyear = 2017;
var startmonth = 1;
var endmonth = 12;
// Set date in ee date format
var startdate = ee.Date.fromYMD(startyear,startmonth,1);
var enddate = ee.Date.fromYMD(endyear,endmonth,31);
// Filter data
var datain_t = collection.filterDate(startdate, enddate)
.filter(ee.Filter.calendarRange(startmonth,endmonth, 'month'))
.select("precipitation").map(function(img){
return img.addBands(ee.Image.constant(0).uint8().rename('counter'));
})
.sort('system:time_start');
// // START
var dataset = datain_t
.filterDate("2016-08-01","2016-08-30")
.sort('system:time_start:');
print(dataset,"dataset");
var precipThresh = 1; // mm
function drySpells(img, list){
// get previous image
var prev = ee.Image(ee.List(list).get(-1));
// find areas gt precipitation threshold (gt==0, lt==1)
var dry = img.select('precipitation').lt(precipThresh);
// add previous day counter to today's counter
var accum = prev.select('counter').add(dry).rename('counter');
// create a result image for iteration
// precip < thresh will equal the accumulation of counters
// otherwise it will equal zero
var out = img.select('precipitation').addBands(
img.select('counter').where(dry.eq(1),accum)
).uint8();
return ee.List(list).add(out);
}
// create first image for iteration
var first = ee.List([ee.Image(dataset.first())]);
// apply dry speall iteration function
var maxDrySpell = ee.ImageCollection.fromImages(
dataset.iterate(drySpells,first)
).max(); // get the max value
// display results
Map.addLayer(maxDrySpell.select('counter'),{min:0,max:30,palette:'#9ecae1,#ffffff,#ffeda0,#feb24c,#f03b20'},'Max Dry Spells');
Here is the link to the code: https://code.earthengine.google.com/80b4c0f7e82a5f0da316af1d2a55dd59
Don't try to run this analysis for too long of a time period or Earth Engine will give an error. I hope this helps!

Prevent Amibroker from entering the same day as its exit in the same symbol

I am attempting to create a share/stock portfolio based system that will enter at the open and possibly exit on the same day at close if the conditions are met. I have this basicaly working. The thing i cant get going is that I would like my stock system to only ever have 1 open postion in a company at any time.
It seems that if there is both an exit and an entry on the same day, amibroker backtesting is allowing the same company to be purchased on the open, if that same company has a sell order on that same day. Here is an example of this:
Notice at point 1 - we would be entering at the open on the 17th
At point 2, we get a sell signal that day, so we should exit at Close on the 24th.
However at point 3 - we have an entry for the same company on the same day.
To be clear - I would like to allow multiple entries on the same day - this is working. The only thing i would like to figure out is to prevent the backtester from entering the SAME company on the SAME day it exits, as due to the system rules, we would have one day of having 2 positions in the 1 company.
Here is the sample code to replicate this:
SetOption("AllowSameBarExit", True );
SetOption("SettlementDelay", 1 );
Buy = C > MA(C,10);
Sell = C < MA(C,10) OR C > O;
// trade on todays open
SetTradeDelays( 0, 0, 0, 0 );
BuyPrice = Open;
SellPrice = Close;
SetPositionSize( 20, spsPercentOfEquity );
I have read and re-read the page on portfolio timing: here but I still cant figure out how to prevent the entries for the same company on the same day as an exit.
Any help would be greatly appreciated!
UPDATE
It appears that using the OR C > O in the SELL condition is effecting this. If I remove the OR C > O part, I get the correct behaviour. It is entering on the NEXT day. Now Im wondering how to use that exit without reverting back to same bar same company entry and exit...
Thanks to Tomasz from Amibroker for posting the below solution:
SetOption("AllowSameBarExit", True );
BuyPrice = Open;
SellPrice = Close;
Buy = Ref( Close > MA( Close, 10 ), -1 );
Sell = Close > Open OR Close < MA( Close,10);
// removing buys you don't want
intrade = False;
for( i = 0; i < BarCount; i++ )
{
if( NOT intrade )
{
if( Buy[ i ] )
{
intrade = True;
// same bar sell
if( Sell[ i ] ) intrade = False;
}
}
else
{
if( Sell[ i ] )
{
intrade = False;
Buy[ i ] = False; // remove buy if exited this bar
}
}
}
You can find : a detailed discussion here

XtraScheduler complex recurrence

Let's say I have a simple recurrent event
**Do stuff once every 5th day at 3am **
That would be
Appointment apt = scheduler.Storage.CreateAppointment(AppointmentType.Pattern);
apt.Start = DateTime.Today.AddHours(3);
apt.End = apt.Start.AddMinutes(15);
apt.Subject = "My Subject";
apt.Location = "My Location";
apt.Description = "My Description";
apt.RecurrenceInfo.Type = RecurrenceType.Daily;
apt.RecurrenceInfo.Start = apt.Start;
apt.RecurrenceInfo.Periodicity = 5;
apt.RecurrenceInfo.Range = RecurrenceRange.NoEndDate;
Now, I would need a complex recurrent event
**Do stuff every 6hours every 5th day at 3am **
Is this even possible?
No, it's impossible to implement with a single pattern event. But you can do it with 2 events. One - every 6 hours and other - every 5th day at 3 am.

"Week of the year" Algorithm needs improvements

I have an algorithm which scans through data read from a .csv file(approx 3700 lines) and assess's which trading week of the year each entry is in by running a count++ for every Sunday of that year and assigning the count value as the trading week when the date falls within that week.
It's working but performance is lagging. It is the 3rd function running using Task.Factory.StartNew (I have also tried parallel.Invoke).
Results of timing tests.
before: 00:00:05.58
after: 00:00:23.27
UPDATE
Added break after each trading week is set. Time improved but still slow.
new time: 00:00:15.74
For our purposes the 1st week of the year is week 1(not 0) and is defined as from the first day of the year until the Sunday. If the first day of the year is a Sunday the length of week 1 is 1 day.
private void SetDefiniteWeeks()
{
string FileLoc = FilePath + Market + ".csv";
string[] Data = File.ReadAllLines(FileLoc);
var FileData = from D in Data
let DataSplit = D.Split(',')
select new
{
Date = DateTime.Parse(DataSplit[0]),
ClosingPrice = double.Parse(DataSplit[4])
};
//assign each date to it's relevant week
TradingWeek TW;
List<TradingWeek> tradingWeek = new List<TradingWeek>();
foreach (var pe in FileData)
{
// DateTime dt = pe.Date;
int Year = pe.Date.Year;
string End_of_Week = "Sunday";
int WeekCount = 0;
DateTime LoopDate_Begin = new DateTime(Year,1,1);
DateTime LoopDate_End = new DateTime(Year,12,31);
do
{
if (LoopDate_Begin.DayOfWeek.ToString() == End_of_Week)
{
WeekCount++;
if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7))
{
TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
break;
}
}
LoopDate_Begin = LoopDate_Begin.AddDays(1);
} while (LoopDate_Begin.Date.ToString() != LoopDate_End.Date.ToString());
}
}
Please help.
UPDATE
NEW TIME
00:00:06.686
A vast improvement. Thanks all for your help.
Revised code:
CalendarWeekRule cw = CalendarWeekRule.FirstDay;
var calendar = CultureInfo.CurrentCulture.Calendar;
var trad_Week = (from pe in FileData
select new TradingWeek
{
Date = pe.Date,
Week = (calendar.GetWeekOfYear(pe.Date, cw,DayOfWeek.Sunday))
}).ToList();
Im not sure if this is what you want but after reading the comments I got the feeling that this might work (?)
var calendar = CultureInfo.CurrentCulture.Calendar;
var tradingWeek = (from pe in FileData
select new TradingWeek
{
Date = pe.Date,
Week = calendar.GetWeekOfYear(pe.Date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
}).ToList();
Edit: Changed to CalendarWeekRule.FirstDay since it's (more?) what OP is looking for.
Three quick thoughts:
Why are you only adding one day each time and checking to see if it's Sunday. Surely once you have found your first Sunday you can add seven days to find the next one?
If you order your pes by DateTime before you start then you don't need to restart at the beginning of the year for each one, you can pick up where you left off.
As Nicolas says, break after adding the trading week. No need to go through the rest of the year after you already know what the answer is.
I guess you'll end up with something like this (may or may not actually work, but should be close enough)
TradingWeek TW;
List<TradingWeek> tradingWeek = new List<TradingWeek>();
string End_of_Week = "Sunday";
var orderedData = FileData.OrderBy(x => x.Date)
DateTime LoopDate_Begin = new DateTime(orderedData[0].Date.Year,1,1);
int WeekCount = 1;
while (LoopDate_Begin.DayOfWeek.ToString() != End_of_Week)
{
LoopDate_Begin = LoopDate_Begin.AddDays(1);
}
foreach (var pe in orderedData)
{
do
{
if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7))
{
TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
break;
}
WeekCount++;
LoopDate_Begin = LoopDate_Begin.AddDays(7);
} while (true); //need to be careful here
}
if I get you correctly, you don't need to look any further as soon as you've added your TradingWeek
So, you can
break;
after
tradingWeek.Add(TW);
You could then even leave out the
&& LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7)
condition since the first part is going to be true only once: for your desired interval.
You might even go for a loopless approach by dividing the number of days since your starting week by 7 - and doing some cleaning up work ;)
Can you get rid of your do loop altogether by calculating the Week Number directly? Something like the accepted answer here.
Following #nicolas78's response, something like this should work
int Year = pe.Date.Year;
DateTime Year_Begin = new DateTime(Year,1,1);
int Jan1DayOfWeek = Year_Begin.DayOfWeek;
foreach (var pe in FileData)
{
int WeekCount = (pe.Date.DayOfYear - Jan1DayOfWeek) % 7 + 1;
TradingWeek TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
}
Depending on how DayOfWeek and DayOfYear count, that is from 0 or 1, and how your mod operation work, you may need to tweak the WeekCount computation a bit.
There's a built-in feature to get the week of the year based on the date in .NET. An example is shown below, but it may need some tweaking to fit your business scenario:
System.Globalization.CultureInfo myCI = new System.Globalization.CultureInfo("en-US");
int week = myCI.Calendar.GetWeekOfYear(DateTime.Now.ToUniversalTime(), System.Globalization.CalendarWeekRule.FirstFourDayWeek, System.DayOfWeek.Sunday);
You don't need to count at all - just do a quick calculation. This assumes that a partial week at the start of the year is week 1 and week 2 begins on the first Monday.
List<TradingWeek> tradingWeek = new List<TradingWeek>();
foreach (var pe in FileData)
{
var date = pe.Date;
while (date.DayOfWeek != DayOfWeek.Sunday)
date = date.AddDays(1);
var week = date.DayOfYear/7+1;
var TW = new TradingWeek {Week = week, Date = pe.Date};
tradingWeek.Add(TW);
}

Resources