Gamestudio Links
Zorro Links
Newest Posts
Issues with converting .csv to .t6
by jcl. 07/16/19 14:46
IG plugin initial release
by YG8. 07/16/19 10:02
First Steps for backtesting with ASCII data
by Charttrader. 07/16/19 08:50
New Zorro version 2.15
by jcl. 07/16/19 08:42
Beginners Workshop
by jcl. 07/15/19 06:29
Dukascopy plugin (yet another version)
by dh85. 07/15/19 05:03
lock profit without trail
by Grat. 07/14/19 15:53
What are you working on?
by rayp. 07/12/19 15:32
AUM Magazine
Latest Screens
The Space Between
Pogostuck: Rage With Your Friends
Worst Case Z
AckCon'18 - Lotter vs the World 2 - Preview Release
Who's Online Now
9 registered members (Peeyotch, chsmac85, AndrewAMD, MatPed, Grat, kvm, Matt_Aufderheide, YG8, 1 invisible), 677 guests, and 10 spiders.
Key: Admin, Global Mod, Mod
Newest Members
Charttrader, bjomu, catharticlapse, carmyss121, Evox
18255 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 2 of 2 1 2
Re: multi timeframe bars [Re: pcz] #464388
02/09/17 11:53
02/09/17 11:53
Joined: Feb 2017
Posts: 6
India,South Africa
Kkaos Offline
Newbie
Kkaos  Offline
Newbie

Joined: Feb 2017
Posts: 6
India,South Africa
Great link, thank you laugh


58 400 hours forex experience,( +-20 years ) and counting...
...........yet we learn something new everyday.

Don't be a dick, listen to EVERYTHING!
Re: multi timeframe bars [Re: Kkaos] #476832
04/10/19 05:35
04/10/19 05:35
Joined: Nov 2015
Posts: 5
R
ricky_k Offline
Newbie
ricky_k  Offline
Newbie
R

Joined: Nov 2015
Posts: 5
@purpledawn

I know this is an old thread but wondering if you've been able to update/use the code you posted for zorro custom bars. I'm interested in experimenting with portfolios using custom bars (such as tick, renko & kase bars).

Include File:
Code:
#ifndef CUSTOMBARS
/// GENERAL CUSTOM BAR CODE - can be put in a separate include
typedef struct {
int LastBarIdx;
int LastBarNum;
int* OpenBar;
vars OpenDate;
vars Open;
vars High;
vars Low;
vars Close;
vars Price;
vars Volume;
} CustomBars;


function initCustomBars(CustomBars* customBars){
if (is(INITRUN)) {
} else {
if (customBars->Open == NULL) { //allocate bars when NumBars is available
customBars->OpenBar = malloc(NumBars * sizeof(int)); if(customBars->OpenBar == NULL)msg("Error could not allocate %i OpenBar",NumBars);memset(customBars->OpenBar, 0, NumBars * sizeof(int));
customBars->OpenDate = malloc(NumBars * sizeof(var)); if(customBars->OpenDate == NULL)msg("Error could not allocate %i OpenDate",NumBars);memset(customBars->OpenDate, 0, NumBars * sizeof(var));
customBars->Open = malloc(NumBars * sizeof(var)); if(customBars->Open == NULL)msg("Error could not allocate %i Open",NumBars);memset(customBars->Open, 0, NumBars * sizeof(var));
customBars->High = malloc(NumBars * sizeof(var)); if(customBars->High == NULL)msg("Error could not allocate %i High",NumBars);memset(customBars->High, 0, NumBars * sizeof(var));
customBars->Low = malloc(NumBars * sizeof(var)); if(customBars->Low == NULL)msg("Error could not allocate %i Low",NumBars);memset(customBars->Low, 0, NumBars * sizeof(var));
customBars->Close = malloc(NumBars * sizeof(var)); if(customBars->Close == NULL)msg("Error could not allocate %i Close",NumBars);memset(customBars->Close, 0, NumBars * sizeof(var));
customBars->Price = malloc(NumBars * sizeof(var)); if(customBars->Price == NULL)msg("Error could not allocate %i Price",NumBars);memset(customBars->Price, 0, NumBars * sizeof(var));
customBars->Volume = malloc(NumBars * sizeof(var)); if(customBars->Volume == NULL)msg("Error could not allocate %i Volume",NumBars);memset(customBars->Volume, 0, NumBars * sizeof(var));
customBars->LastBarIdx = NumBars;
customBars->LastBarNum=0;
}
}
}
function freeCustomBars(CustomBars* customBars){
//print(TO_CSV,"Bar:%i freeing OpenBar");
if (customBars->OpenBar != 0) free(customBars->OpenBar);customBars->OpenBar=0;
//print(TO_CSV,"Bar:%i freeing OpenDate");
if (customBars->OpenDate != NULL) free(customBars->OpenDate);customBars->OpenDate=0;
//print(TO_CSV,"Bar:%i freeing OpenBars");
if (customBars->Open != NULL) free(customBars->Open);customBars->Open=0;
//print(TO_CSV,"Bar:%i freeing High");
if (customBars->High != NULL) free(customBars->High);customBars->High=0;
//print(TO_CSV,"Bar:%i freeing Low");
if (customBars->Low != NULL) free(customBars->Low);customBars->Low=0;
//print(TO_CSV,"Bar:%i freeing Close");
if (customBars->Close != NULL) free(customBars->Close);customBars->Close=0;
//print(TO_CSV,"Bar:%i freeing Price");
if (customBars->Price != NULL) free(customBars->Price);customBars->Price=0;
//print(TO_CSV,"Bar:%i freeing Volume %A",customBars->Volume);
if (customBars->Volume != NULL) free(customBars->Volume);customBars->Volume=0;
//print(TO_CSV,"Bar:%i finished freeing bars n");
}
function enlarge(CustomBars* customBars){
//use if need to add more bars than originally allocated
int lastNumBars= customBars->LastBarNum;
int numCBars = ceil(lastNumBars*1.5); //expand by 50%
msg("in enlarge, lastNumBars:%i newNumBars:%i",lastNumBars,numCBars);

int* OpenBar = malloc(numCBars * sizeof(int)); if(OpenBar == NULL)msg("Error could not allocate %i OpenBar",numCBars); memset(OpenBar, 0, numCBars * sizeof(int));
vars OpenDate = malloc(numCBars * sizeof(var)); if(OpenDate == NULL)msg("Error could not allocate %i OpenDate",numCBars);memset(OpenDate, 0, numCBars * sizeof(var));
vars Open = malloc(numCBars * sizeof(var)); if(Open == NULL)msg("Error could not allocate %i Open",numCBars);memset(Open, 0, numCBars * sizeof(var));
vars High = malloc(numCBars * sizeof(var)); if(High == NULL)msg("Error could not allocate %i High",numCBars);memset(High, 0, numCBars * sizeof(var));
vars Low = malloc(numCBars * sizeof(var)); if(Low == NULL)msg("Error could not allocate %i Low",numCBars);memset(Low, 0, numCBars * sizeof(var));
vars Close = malloc(numCBars * sizeof(var)); if(Close == NULL)msg("Error could not allocate %i Close",numCBars);memset(Close, 0, numCBars * sizeof(var));
vars Price = malloc(numCBars * sizeof(var)); if(Price == NULL)msg("Error could not allocate %i Price",numCBars);memset(Price, 0, numCBars * sizeof(var));
vars Volume = malloc(numCBars * sizeof(var));if(Volume == NULL)msg("Error could not allocate %i Volume",numCBars); memset(Volume, 0, numCBars * sizeof(var));


memcpy(&OpenBar[numCBars- lastNumBars], customBars->OpenBar, lastNumBars*sizeof(int));
memcpy(&OpenDate[numCBars- lastNumBars], customBars->OpenDate, lastNumBars*sizeof(var));
memcpy(&Open[numCBars- lastNumBars], customBars->Open, lastNumBars*sizeof(var));
memcpy(&High[numCBars- lastNumBars], customBars->High, lastNumBars*sizeof(var));
memcpy(&Low[numCBars- lastNumBars], customBars->Low, lastNumBars*sizeof(var));
memcpy(&Close[numCBars- lastNumBars], customBars->Close, lastNumBars*sizeof(var));
memcpy(&Price[numCBars- lastNumBars], customBars->Price, lastNumBars*sizeof(var));
memcpy(&Volume[numCBars- lastNumBars], customBars->Volume, lastNumBars*sizeof(var));

//msg("freeing custom barS");
freeCustomBars(customBars); //for unknown reasons can get script crash freeing allocated mem
//msg("custom bars freed");


customBars->OpenBar = OpenBar;
customBars->OpenDate = OpenDate;
customBars->Open = Open;
customBars->High = High;
customBars->Low = Low;
customBars->Close = Close;
customBars->Price = Price;
customBars->Volume = Volume;

customBars->LastBarIdx = customBars->LastBarIdx + numCBars-lastNumBars;

}
function addCustomBar(CustomBars* customBars, var op, var hi, var lo, var cl, var vol){
//msg("in add custom1");
int ridx = customBars->LastBarIdx;
//print(TO_CSV,"Bar:%i closed custom bar %i op:%f hi:%f lo:%f cl:%f new bar(%f, %f, %f, %f)n",Bar,customBars->LastBarIdx,(customBars->Open)[ridx],(customBars->High)[ridx],(customBars->Low)[ridx],(customBars->Close)[ridx], op, hi, lo, cl);
ridx = customBars->LastBarIdx-1;
if (ridx < 0){
enlarge(customBars);
ridx = customBars->LastBarIdx-1;
//msg("enlarge custom bars, ridx now: %i",ridx);
}
(customBars->Open)[ridx]=op;
//msg("in add custom op: %f", op);
(customBars->High)[ridx]=hi;
(customBars->Low)[ridx]=lo;
(customBars->Close)[ridx]=cl;
(customBars->Price)[ridx]=(hi+lo+cl)/3.0;
(customBars->Volume)[ridx]=vol;

(customBars->OpenBar)[ridx]=Bar;
(customBars->OpenDate)[ridx]=wdate(0);
customBars->LastBarNum = customBars->LastBarNum+1;
customBars->LastBarIdx = ridx;
}
function updateLastCustomBar(CustomBars* customBars, var hi, var lo, var cl, var vol){
int ridx = customBars->LastBarIdx;
(customBars->High)[ridx]=max((customBars->High)[ridx],hi);
(customBars->Low)[ridx]=min((customBars->Low)[ridx],lo);
(customBars->Close)[ridx]=cl;
(customBars->Price)[ridx]=(hi+lo+cl)/3.0;
(customBars->Volume)[ridx]=(customBars->Volume)[ridx]+vol;
}

bool hasBars(CustomBars* customBars){
return (customBars->LastBarIdx) != NumBars;
}
var last(CustomBars* customBars, vars customIndexedSeries){
int idx = customBars->LastBarIdx ;
return customIndexedSeries[idx];
}
var price(CustomBars* customBars, int offset){
return last(customBars, customBars->Price);
}
vars priceSeries(CustomBars* customBars){
int idx = customBars->LastBarIdx ;
return &(customBars->Price)[idx];
}

var priceHigh(CustomBars* customBars, int offset){
return last(customBars, customBars->High);
}
vars priceHighSeries(CustomBars* customBars){
int idx = customBars->LastBarIdx ;
return &(customBars->High)[idx];
}
var priceLow(CustomBars* customBars, int offset){
return last(customBars, customBars->Low);
}
vars priceLowSeries(CustomBars* customBars){
int idx = customBars->LastBarIdx ;
return &(customBars->Low)[idx];
}

var priceOpen(CustomBars* customBars, int offset){
return last(customBars, customBars->Open);
}
vars priceOpenSeries(CustomBars* customBars){
int idx = customBars->LastBarIdx ;
return &(customBars->Open)[idx];
}

var priceClose(CustomBars* customBars, int offset){
return last(customBars, customBars->Close);
}
vars priceCloseSeries(CustomBars* customBars){
int idx = customBars->LastBarIdx ;
return &(customBars->Close)[idx];
}

var marketVol(CustomBars* customBars, int offset){
return last(customBars, customBars->Volume);
}
vars marketVolSeries(CustomBars* customBars){
int idx = customBars->LastBarIdx ;
return &(customBars->Volume)[idx];
}



function plot1(CustomBars* customBars, int barNum, string name, int colorup, int colordn){
int i = NumBars - barNum;
int startIdx = (customBars->OpenBar)[i];
int endIdx =NumBars-1; if (i > customBars->LastBarIdx) endIdx = (customBars->OpenBar)[i-1]-1;
if (startIdx == endIdx && endIdx < NumBars)
endIdx = endIdx+1;
if (PlotBars != 0){
//avoid too many bars error by not plotting outside plot zone
if(PlotBars > 0 && startIdx > PlotBars){
return;
}
if(PlotBars < 0 && endIdx < abs(PlotBars)){
return;
}
}

startIdx = NumBars - startIdx-1; endIdx = NumBars-endIdx-1;



if (colorup == 0)
colorup = BLUE;
if (colordn == 0)
colordn = RED;

int plotcolor = colorup;
bool showMsg = true;
bool isdecreasing = false;
if (i < (customBars->LastBarNum-1))
isdecreasing = (customBars->Close)[i] < (customBars->Close)[i+1]; //less than previous close
else
isdecreasing = (customBars->Close)[i] < (customBars->Open)[i];
if ( isdecreasing ){
plotcolor = colordn;
}

var lo = (customBars->Low)[i];
var hi = (customBars->High)[i];

string upName = strf("%s-Up",name);
string dnName = strf("%s-Dn",name);

if (!isdecreasing){
plotGraph(upName,startIdx,lo,LINE,plotcolor); // start point
plotGraph(upName,startIdx,hi,LINE,plotcolor); // 1st corner
plotGraph(upName,endIdx,hi,LINE,plotcolor); // 2nd corner
plotGraph(upName,endIdx,lo,LINE,plotcolor); // 3rd corner
plotGraph(upName,startIdx,lo,LINE|END,plotcolor); // 4th corner and end point
}
else {
plotGraph(dnName,startIdx,lo,LINE,plotcolor); // start point
plotGraph(dnName,startIdx,hi,LINE,plotcolor); // 1st corner
plotGraph(dnName,endIdx,hi,LINE,plotcolor); // 2nd corner
plotGraph(dnName,endIdx,lo,LINE,plotcolor); // 3rd corner
plotGraph(dnName,startIdx,lo,LINE|END,plotcolor); // 4th corner and end point
}

}
function plot(CustomBars* customBars, string name, int colorup, int colordn){
if (Bar != NumBars-1) return;

int i;
for (i = 1; i <= customBars->LastBarNum; i++){
//msg("plot bar");
plot1(customBars, i, name, colorup, colordn);
}
}


function plotLine(CustomBars* customBars, string name, vars customBarSeries, int type, int color){
int barNum; int endIdx = NumBars-1;
for (barNum = 1; barNum <= customBars->LastBarNum; barNum++){
int i = NumBars - barNum;
endIdx =NumBars-1; if (i > customBars->LastBarIdx) endIdx = (customBars->OpenBar)[i-1]-1;
endIdx = NumBars-endIdx-1;
plotGraph(name, endIdx,customBarSeries[i],LINE, color);
}
plotGraph(name, endIdx,customBarSeries[NumBars-1],LINE | END, color);
}
//plot a series indexed by customBars, ie have same number of values as customBars
function plot(CustomBars* customBars, string name, vars customBarSeries, int type, int color){
if (Bar != NumBars-1) return;
if (type == 0 or type & LINE){
//draw line graph
plotLine(customBars, name, customBarSeries, type, color);
}
else {
//...todo, handle other graph types for indexed series
}

}
/// END GENERAL CUSTOM BAR CODE - can be put in a separate include


//code to customize for each type of custom bar
function makeRandomBars(CustomBars* customBars, var probability){
if (is(INITRUN) or is(EXITRUN))
return;
initCustomBars(customBars);

static bool newBar = true;
var op = priceOpen(0);
var hi=priceHigh(0); var lo=priceLow(0); var cl=priceClose(0); var vol=marketVol(0);

if (newBar){
addCustomBar(customBars, op, hi, lo, cl, vol);
newBar = false;
}
else {
updateLastCustomBar(customBars, hi, lo, cl, vol);
}

//logic to decide when to stop bar
if (random() > (1-probability)){ //eg: close rand bar approx every probabilty base bars
newBar = true;
}
}

//renko bars
var upround(var num, var mintick){
var z = mintick*ceil(num/mintick);
return z;
}
var dnround(var num, var mintick){
var z =mintick*floor(num/mintick);
return z;
}
function addUpRenkoBoxes(CustomBars* customBars, int* rdir,var* ropen, var* rhi, var* rlo, var* rcl, var* upbox, var* dnbox, var fwdPips, var revPips, var hi, var vol, var mintick){
while (hi >= upround(*ropen + *upbox, mintick)){
*rhi = max(*rhi, upround(*ropen + *upbox,mintick));
updateLastCustomBar(customBars, *rhi, *rlo, upround(*ropen + *upbox,mintick), vol);
*ropen = *rlo = upround(*ropen + *upbox,mintick); *rdir = 1;
*upbox = fwdPips; *dnbox = revPips;
addCustomBar(customBars, *ropen, *rhi, *rlo, *ropen, 0);
}
*rhi = max(*rhi,hi);
}
function addDnRenkoBoxes(CustomBars* customBars, int* rdir,var* ropen, var* rhi, var* rlo, var* rcl, var* upbox, var* dnbox, var fwdPips, var revPips, var lo, var vol, var mintick){
while (lo <= dnround(*ropen - *dnbox, mintick)){
*rlo = min(*rlo, dnround(*ropen - *dnbox,mintick));
updateLastCustomBar(customBars, *rhi, *rlo, dnround(*ropen - *dnbox,mintick), vol);

*ropen = *rhi = dnround(*ropen - *dnbox,mintick); *rdir = -1;
*upbox = revPips; *dnbox = fwdPips;
addCustomBar(customBars, *ropen, *rhi, *rlo, *ropen, 0);
}
*rlo = min(*rlo,lo);
}
function makeRenkoBars(CustomBars* customBars, var numFwdPips, var numRevPips, var mintick, var* tmprdir, vars tmpohlcv){
static bool firstBarCreated = false;
if (is(INITRUN))
firstBarCreated = false;
if (is(INITRUN) or is(EXITRUN))
return;
initCustomBars(customBars);

static int rdir;
static var rop,rhi,rlo,rcl,rvol; //use static vars so can pass by reference
rop = tmpohlcv[0]; //initalize and store into passed in array so makeRenko can be called multiple times
rhi = tmpohlcv[1];
rlo = tmpohlcv[2];
rcl = tmpohlcv[3];
rvol = tmpohlcv[4];
rdir = *tmprdir;

if (mintick == 0)
mintick =PIP;

var op=priceOpen(0); var hi=priceHigh(0); var lo=priceLow(0); var cl=priceClose(0); var vol=marketVol(0);

var fwdPips = numFwdPips*PIP; var revPips = numRevPips*PIP;
if (rdir == 0 && rop == 0 && rcl == 0){
rop = op; rhi=rop; rlo=rop; rcl=rop;
addCustomBar(customBars, rop, rhi, rlo, rcl, 0); //open first bar
firstBarCreated = true;
}
if (rdir == 0){

if (rcl>rop && (rhi - rop) > fwdPips){
rdir = 1;
}
else if (rcl< rop && (rop - rlo) > fwdPips){
rdir = -1;
}
else if ((rhi - rop) > fwdPips){
rdir = 1;
}
else if ((rop - rlo) > fwdPips){
rdir = -1;
}
}

var upbox = fwdPips; var dnbox = revPips;
if (rdir == -1){
upbox = revPips; dnbox = fwdPips;
}
if ((rdir > 0 && cl >= op) || (rdir < 0 && cl >= op)){
//assume open lo hi cl
addDnRenkoBoxes(customBars, &rdir,&rop, &rhi, &rlo, &rcl, &upbox, &dnbox, fwdPips, revPips, lo, vol, mintick);
addUpRenkoBoxes(customBars, &rdir,&rop, &rhi, &rlo, &rcl, &upbox, &dnbox, fwdPips, revPips, hi, vol, mintick);
}
else if ((rdir < 0 && cl <= op) || (rdir > 0 && cl <= op)){
//assume open hi lo cl
addUpRenkoBoxes(customBars, &rdir,&rop, &rhi, &rlo, &rcl, &upbox, &dnbox, fwdPips, revPips, lo, vol, mintick);
addDnRenkoBoxes(customBars, &rdir,&rop, &rhi, &rlo, &rcl, &upbox, &dnbox, fwdPips, revPips, hi, vol, mintick);
}
else {
//assume open lo hi cl
addDnRenkoBoxes(customBars, &rdir,&rop, &rhi, &rlo, &rcl, &upbox, &dnbox, fwdPips, revPips, lo, vol, mintick);
addUpRenkoBoxes(customBars, &rdir,&rop, &rhi, &rlo, &rcl, &upbox, &dnbox, fwdPips, revPips, hi, vol, mintick);
}

tmpohlcv[0] = rop;
tmpohlcv[1] = rhi;
tmpohlcv[2] = rlo;
tmpohlcv[3] = rcl;
tmpohlcv[4]= rvol;
*tmprdir= rdir;

}
#define CUSTOMBARS
#endif



Test code:
Code:
#include<CustomBars.c>

//testing custom bars
function run() {
//msg("create mybars");
PlotBars = 10000;
BarPeriod = 1; //if changing barperiod to higher number, depending on the boxsize, makeRenko may need to enlarge its bar array multiple times if there are many more renko bars than NumBars. This may fail

static CustomBars myBars;
//makeRandomBars(&myBars, 0.01);

static int rdir;
static var rohlcv[5] = {0,0,0,0,0};
makeRenkoBars(&myBars, 10, 3*10, PIP/10.0, &rdir, rohlcv); //10:fwdBox 3*10:reversal box PIP/10.0: mintick rounding

static CustomBars myBars2;
static int rdir2;
static var rohlcv2[5] = {0,0,0,0,0};
makeRenkoBars(&myBars2, 4*10, 4*3*10, PIP/10.0, &rdir2, rohlcv2);



plot(&myBars,"renko1",BLUE, RED);
plot(&myBars2,"renko2",0x0000AA, 0xAA0000);


if (hasBars(&myBars) && myBars.LastBarNum >= 21){
vars offsetRandClose = priceCloseSeries(&myBars);
var rsma21 = SMA(offsetRandClose, 21); //real time calculation of sma of past 21 renko bars

plot("rk1_sma21",rsma21,0,BLUE);
}
if (hasBars(&myBars2) && myBars2.LastBarNum >= 21){
vars offsetRandClose2 = priceCloseSeries(&myBars2);
var rsma212 = SMA(offsetRandClose2, 21); //real time calculation of sma of past 21 renko bars

plot("rk2_sma21",rsma212,0,0x0000CC);
}


if (is(EXITRUN)) {
msg("is Exit Run!");
freeCustomBars(&myBars);
freeCustomBars(&myBars2);
}
}




However when I test the above code (Zorro S 1.96.4) I receive this error:

Z Client S 1.96.4
(c) oP group Germany 2018
Registered to:
CustomBars_TEST -stay

CustomBars_TEST compiling..
Error in 'custombars.c' line 8:
syntax error
< vars OpenDate;
>.



I also gather from the syntax highlighting that some of the functions in the include file may clash with predefined Zorro functions.

Again just wondering if you (or anyone) has updated and/or still uses this code.

Re: multi timeframe bars [Re: ricky_k] #476848
04/12/19 13:38
04/12/19 13:38
Joined: Jan 2017
Posts: 5
P
purpledawn Offline OP
Newbie
purpledawn  Offline OP
Newbie
P

Joined: Jan 2017
Posts: 5
Hello Rick, I did develop that code further.
See the attached files -- custombars.c is an include, put in your include folder; custom_bars.c is a sample strategy using that code.
It took me a while to debug -- Enjoy!

Attached Files
custombars.c (8 downloads)
custom_bars.c (7 downloads)
Re: multi timeframe bars [Re: purpledawn] #476862
04/13/19 16:22
04/13/19 16:22
Joined: Nov 2015
Posts: 5
R
ricky_k Offline
Newbie
ricky_k  Offline
Newbie
R

Joined: Nov 2015
Posts: 5
purpledawn,
Thanks buddy laugh ! I'll test out the code and let you know if there's any issues that come up.

Also if I can get Kase bars (equal true range / constant volatility bars) working I'll re-post the updated code...
Cheers
ricky

Last edited by ricky_k; 04/13/19 16:26.
Page 2 of 2 1 2

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1