I have a following table of periods which describes how often to ..say.. feed my fish:
--------------------------------------------------------
Period: Jan Feb March April May Jun Jul ... n - 1 .... n
--------------------------------------------------------
Val_1: 5 2 3 6 3 2 4 x x
Val_2 ...
--------------------------------------------------------
And I have a period given with two DateTimes, start and end, ie:
DateTime start = new DateTime(2010, 3, 11);
DateTime end = new DateTime(2012, 7, 12);
..in which time the feeding process occurs. How can I get the values from the table in every period in correlation with the period given by start and end ?
For example, the period given by start and end is 2.5 years, but my table only describes 12 months. How can I loop over every period in the table WITHIN the whole period given by start and end ?
I came up with something like this:
class PeriodTableValue
{
DateTime period; // Ignore year component of datetime
double val_1;
double val_2;
}
void FeedMyFish(double howmuch, DateTime period_start, DateTime period_end)
{
...
}
...
PeriodTableValue[] table = ...
DateTime start = ...
DateTime end = ...
DateTime d1 = start;
for(int i = 0; i < table.Length; i++)
{
DateTime d2 = table[i].period;
int nI = find the occurrances of period table[i]. How ???
for(int j = 0; j < nI; j++)
{
FeedMyFish(..parameters ???)
}
d1 = d2;
}
And I'm stuck right here. Please advise.
Thanks!
This article includes support for various period types and the search for intersection periods:
// ----------------------------------------------------------------------
public void TimePeriodIntersectorSample()
{
TimePeriodCollection periods = new TimePeriodCollection();
periods.Add( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 05 ), new DateTime( 2011, 3, 15 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 12 ), new DateTime( 2011, 3, 18 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 22 ), new DateTime( 2011, 3, 28 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 24 ), new DateTime( 2011, 3, 26 ) ) );
TimePeriodIntersector<TimeRange> periodIntersector =
new TimePeriodIntersector<TimeRange>();
ITimePeriodCollection intersectedPeriods = periodIntersector.IntersectPeriods( periods );
foreach ( ITimePeriod intersectedPeriod in intersectedPeriods )
{
Console.WriteLine( "Intersected Period: " + intersectedPeriod );
}
// > Intersected Period: 05.03.2011 - 10.03.2011 | 5.00:00
// > Intersected Period: 12.03.2011 - 15.03.2011 | 3.00:00
// > Intersected Period: 22.03.2011 - 26.03.2011 | 4.00:00
} // TimePeriodIntersectorSample
Related
I have a date table. I have a measure that calculates the net sales. I want to calculate net sales for the same day of the week last month.
Example: Net Sales for Friday, July 1 2022 VS Net Sales for Friday, June 03, 2022.
I am using this code to get the same day last month:
Same Week Day last month =
VAR CurrentDay =
MAX ( 'Dates'[Date] )
VAR WeekDaysDelta =
WEEKDAY ( EOMONTH ( CurrentDay, -1 ) ) - WEEKDAY ( EOMONTH ( CurrentDay, -2 ) )
VAR DaysAdjust =
IF (
WeekDaysDelta > 3,
WeekDaysDelta - 7,
IF ( WeekDaysDelta < -3, WeekDaysDelta + 7, WeekDaysDelta )
)
VAR SameWeekDay =
EOMONTH ( CurrentDay, -2 ) + DAY ( CurrentDay ) + DaysAdjust
RETURN
SameWeekDay
I'm trying to come up with something to Sync weekdays between years
So far I can do it for a 4 year gap just by subtracting 364 days
For example
Monday Feb 1 2021 - 364 days becomes Monday Feb 3rd 2020
Friday Feb 19 2021 - 364 days becomes Friday Feb 21nd 2020
Tuesday Mar 2 2021 - 364 days becomes Tuesday Mar 3rd 2020
notice how the weekday is in perfect sync (Monday to Monday, Tuesday to Tuesday etc)
and I can do this for 2 years just by using 728 days (364 * 2)
and so on for 3 and 4 years
my problem is after 4 years it stops working
if I do the same thing for 5 Years (364*5)
Monday Feb 1st 2021 becomes Monday Feb 8th 2016
however I would want it to be Monday Feb 1st 2016
I cant seem to crack how to deal with this for 5 years on
This is using Zeller’s Rule to get the day number, and then just modifying the actual date when subtracting 365 days to get the day name to match. I'm sure there are edge cases (e.g. I believe this would currently allow a result of something like "March 33"), but this should get you started:
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const months = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
const dayNum = (day, month, year) => {
if (month <= 2) {
year--;
month += 12;
}
month-=2;
const lastTwoDigitsOfYear = year % 100;
const firstTwoDigitsOfYear = (year - lastTwoDigitsOfYear) / 100
let F = day + Math.floor((13*month-1)/5) + lastTwoDigitsOfYear + Math.floor(lastTwoDigitsOfYear/4) +Math.floor(firstTwoDigitsOfYear/4)-2*firstTwoDigitsOfYear
let f = F >= 0 ? (F % 7) : 7 + (F % 7);
return f
}
// Ok, so we can get the day for any date.
const syncedYearAdd = (day, month, year, numYears) => {
const d1 = dayNum(day, month, year);
const d2 = dayNum(day, month, year + numYears);
if (d1 < d2) {
day -= (d2 - d1)
} else if (d1 > d2) {
day += (d1 - d2);
}
if (day < 0) {
day += 7;
}
console.log(days[d1], day, months[month-1], year + numYears)
}
// Monday Feb 1st 2021
for (let i = 0; i <= 5; i++) {
syncedYearAdd(1, 2, 2021, i * -1)
}
I have set of emitted values (stock market transactions) with time and price and vol like this...
TIME PRICE VOL
13:45:01 12 1
13:45:01 12 1
13:45:01 12 10
13:45:01 13 1
13:45:01 13 3
13:45:02 13 1
And I just want to merge values within the same second and same value and accumulate VOL so the resulting observable will be emitting such values based on source above:
TIME PRICE ACCUMULATED VOL
13:45:01 12 12
13:45:01 13 4
13:45:02 13 1
This is some kind of grouping and then reducing. I'm reading documentation but can't figure out which operators to use...
Can somebody help?
Assuming stockSource is the realtime stream that push buy/sell item. You can use scan to accumulate your data and compute accumulation count there.
stockSource.pipe(scan((acc,curr)=>{
const foundObj=acc.find(obj=>obj.PRICE===curr.PRICE);
if(!foundObj){ return [...acc,curr]}
foundObj.ACCUMULATED++;
return acc
},[])).subscribe()
A Custom Operator
I think there must be a better way to do this, but it didn't come to me, so I made a custom operator.
This might be overkill? No idea, You can try it out/ test it yourself if you're so inclined.
Note that for many operators, returning from(thing) is the same as returning thing. So when I return an array from concatMap, that array is turned into a stream for me.
function customOperator(){
return s => defer(() => {
let currentTime = "";
let buffer = {};
return s.pipe(
concatMap(({time, price, vol}) => {
let ret = [];
if(currentTime != time){
ret = Object.values(buffer);
buffer = {}
}
let accumVol = buffer[price]?.accumulatedVol;
accumVol = accumVol != null? accumVol : 0;
buffer[price] = {
time,
price,
accumulatedVol: accumVol + vol
};
currentTime = time;
return ret;
}),
s => concat(s, defer(() => Object.values(buffer)))
)
})
}
function makeTransaction(time, price, vol){
return ({time, price, vol});
}
of(
makeTransaction("13:45:01", 12, 1),
makeTransaction("13:45:01", 12, 1),
makeTransaction("13:45:01", 12, 10),
makeTransaction("13:45:01", 13, 1),
makeTransaction("13:45:01", 13, 3),
makeTransaction("13:45:02", 13, 1)
).pipe(
customOperator()
).subscribe(console.log);
Unless I misunderstood your requirements, this looks like a job for groupBy:
Generate a key to group items by time and price
There will be one stream per set
Reduce each stream into a single reduced emission to accumulate all volumes
Merge back each stream into the output
const transactions$ =
of( {time: '13:45:01', price: 12, volume: 1}
, {time: '13:45:01', price: 12, volume: 1}
, {time: '13:45:01', price: 12, volume: 10}
, {time: '13:45:01', price: 13, volume: 1}
, {time: '13:45:01', price: 13, volume: 3}
, {time: '13:45:02', price: 13, volume: 1});
const groups$ =
transactions$.pipe( groupBy(t => `${t.price}#${t.time}`)
, mergeMap(group$ =>
group$.pipe(reduce((tt, {time, price, volume}) =>
({time, price, volume: volume + tt.volume}),
{volume: 0}))));
groups$.subscribe(t => console.log(JSON.stringify(t)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.3.0/rxjs.umd.min.js" integrity="sha512-y3JTS47nnpKORJX8Jn1Rlm+QgRIIZHtu3hWxal0e81avPrqUH48yk+aCi+gprT0RMAcpYa0WCkapxe+bpBHD6g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
const {of} = rxjs;
const {groupBy, mergeMap, reduce} = rxjs.operators;
</script>
I am using an ArrayList to store objects of the class called SocialTimes. SocialTimes holds a string and 2 numbers. I'm trying to sort based on the Hour and Minute. I have no clue of how to do it. Can someone help me?
public class SocialTimes
{
string DateToPostStr = "";
int HourToPost = 0;
int MinuteToPost = 0;
public SocialTimes(string DateToPostStr, int HourToPost, int MinuteToPost)
{
this.DateToPostStr = DateToPostStr;
this.HourToPost = HourToPost;
this.MinuteToPost = MinuteToPost;
}
public string getDateToPostStr()
{
return this.DateToPostStr;
}
public int getHourToPost()
{
return this.HourToPost;
}
public int getMinuteToPost()
{
return this.MinuteToPost;
}
public static implicit operator SocialTimes(ArrayList v)
{
throw new NotImplementedException();
}
}
public class myComparer : IComparer
{
int IComparer.Compare(Object xx, Object yy)
{
SocialTimes x = (SocialTimes)xx;
SocialTimes y = (SocialTimes)yy;
return x.getHourToPost().CompareTo(y.getHourToPost());
}
}
So here is a method to test the sort ArrayList...
private void testHourMinuteSort()
{
ArrayList projects = new ArrayList();
projects.Add(new SocialTimes("03/14/20", 17, 7));
projects.Add(new SocialTimes("03/14/20", 10, 39));
projects.Add(new SocialTimes("03/14/20", 12, 7));
projects.Add(new SocialTimes("03/14/20", 3, 16));
projects.Add(new SocialTimes("03/14/20", 21, 8));
projects.Add(new SocialTimes("03/14/20", 20, 56));
projects.Add(new SocialTimes("03/14/20", 3, 2));
projects.Sort(new myComparer());
string hoursminutes = "";
foreach (SocialTimes item in projects)
{
hoursminutes = hoursminutes + String.Format("Hour: {0} Minute: {1}", item.getHourToPost(), item.getMinuteToPost()) + Environment.NewLine;
}
MessageBox.Show(hoursminutes);
}
hoursminutes:
Hour: 3 Minute: 16
Hour: 3 Minute: 2
Hour: 10 Minute: 39
Hour: 12 Minute: 7
Hour: 17 Minute: 7
Hour: 20 Minute: 56
Hour: 21 Minute: 8
I need the sort to sort by hours and minutes like below.
Hour: 3 Minute: 2
Hour: 3 Minute: 16
Hour: 10 Minute: 39
Hour: 12 Minute: 7
Hour: 17 Minute: 7
Hour: 20 Minute: 56
Hour: 21 Minute: 8
Convert the values to minutes and compare, not just hours.
int x1 = t1.Hours * 60 + t1.Minutes;
As it is now, times with the same number of (whole) hours will be sorted “randomly” with respect to each other because the minutes are not compared.
Alternatively, just use LINQ and something like:
s.OrderBy(x => x.Hours).ThenBy(x => x.Minutes)
It would probably also be more clear to use a a Date and/or TimeSpan which represents dates and/or ranges of time well. In that case the above code would be simplified as only one value would be compared.
Using a proper generic collection type such as List<SocialTimes> is also a much more modern and type-safe way to deal with collections.
I'm trying to develop an Expert Advisor, so far I can understand and write this which will place orders when a new bar opens.
int BarsCount = 0;
int start()
{ if ( Bars > BarsCount )
{ OrderSend( Symbol(), OP_BUY, 0.01, Ask, 2, NULL, NULL );
BarsCount = Bars;
}
return( 0 );
}
how to get the highest value of standard deviation for last 2 hours to a variable?
E.g.: lets say the EA runs in a 30 mins chart and the bar1 has the standard deviation value 0.003, and bar2 has 0.001, bar3 has 0.004 and bar4 has 0.001.
So, the highest value for past 4 hours is bar3 which has the value of 0.004, so how to get that value to a variable?
I'm trying to make the EA place orders when this formula is true:
( ( current_value_of_standard_deviation
/ highest_value_of_standard_deviation_for_last_2_hours
)
* 100
) > 10
Use built-in tools:
input int MA_period = 27;
int BarsCount = 0;
int nCells2CMP= ( PERIOD_H1 * 2 / PERIOD_CURRENT ) - 1;
double Sig2H[100];
void OnInit(){
...
}
void OnTick(){
if ( Bars > BarsCount ){
if ( BarsCount == 0 ){
for ( int i = MA_period; i > 0; i-- ){
Sig2H[i] = iStdDev( _Symbol,
PERIOD_CURRENT,
0,
MODE_SMA,
PRICE_CLOSE,
i
);
}
}
for ( int i = MA_period; i > 1; i-- ) Sig2H[i] = Sig2H[i-1];
Sig2H[1] = iStdDev( _Symbol, // symbol
PERIOD_CURRENT, // timeframe
MA_period, // MA averaging period
0, // MA shift
MODE_SMA, // MA averaging method
PRICE_CLOSE, // applied price
1 // shift
);
}
Sig2H[0] = iStdDev( _Symbol, // symbol
PERIOD_CURRENT, // timeframe
MA_period, // MA averaging period
0, // MA shift
MODE_SMA, // MA averaging method
PRICE_CLOSE, // applied price
0 // shift
);
if ( 0.1 < ( Sig2H[0]
/ Sig2H[ArrayMaximum( Sig2H,
nCells2CMP,
1
)
]
)
){...}
}