Edit: I rigged a smaller example so you can reproduce it if you want.
I have a OHLC XTS table I'm using (of Euro/$)
> theBars
Open High Low Close
2014-06-17 01:42:26 13835 13836 13835 13836
2014-06-17 01:42:59 13836 13838 13835 13837
2014-06-17 01:43:21 13837 13838 13837 13837
2014-06-17 01:43:51 13837 13837 13837 13837
2014-06-17 01:44:23 13837 13837 13837 13837
2014-06-17 01:44:51 13837 13838 13837 13838
2014-06-17 01:45:28 13837 13840 13837 13840
2014-06-17 01:45:59 13840 13842 13840 13842
2014-06-17 01:46:22 13842 13843 13842 13843
2014-06-17 01:46:58 13843 13844 13843 13844
2014-06-17 01:47:29 13843 13844 13843 13843
2014-06-17 01:47:58 13843 13843 13841 13843
2014-06-17 01:48:22 13843 13843 13842 13843
2014-06-17 01:48:59 13843 13843 13842 13842
2014-06-17 01:49:05 13842 13842 13841 13841
2014-06-17 01:49:54 13841 13841 13840 13841
2014-06-17 01:50:18 13841 13841 13841 13841
2014-06-17 01:50:44 13840 13840 13839 13840
2014-06-17 01:52:55 13839 13839 13838 13839
2014-06-17 01:53:42 13838 13839 13838 13838
2014-06-17 01:54:22 13837 13838 13837 13838
2014-06-17 01:54:58 13837 13838 13836 13837
2014-06-17 01:55:29 13836 13836 13834 13835
2014-06-17 01:55:59 13835 13837 13835 13837
2014-06-17 01:56:28 13837 13839 13837 13838
2014-06-17 01:56:59 13838 13838 13837 13837
2014-06-17 01:57:29 13837 13838 13837 13838
2014-06-17 01:57:59 13838 13838 13838 13838
2014-06-17 01:58:29 13838 13838 13836 13837
2014-06-17 01:58:58 13837 13837 13836 13836
2014-06-17 01:59:29 13836 13841 13836 13840
2014-06-17 01:59:59 13840 13840 13835 13837
2014-06-17 02:00:29 13837 13837 13836 13836
2014-06-17 02:00:58 13836 13836 13835 13836
2014-06-17 02:01:29 13835 13837 13835 13837
2014-06-17 02:01:58 13837 13837 13836 13836
and I'm plotting points on it with
points.default(x=timeIndex*tMult+1, #aligns with tMult = 3 when candles are candles, 1 when they are matchsticks
y=as.numeric(dataCol[i]), #the price, its around 13818
cex=dotSize,
pch=dotType,
col=thecolor)
Which works as intended. In this example, here are the values
x y cex pch col
"19" "13841" "2" "2" "green"
x y cex pch col
"19" "13841" "3" "2" "#7070FF"
x y cex pch col
"19" "13841" "4" "2" "#7070FF"
(The center of each point is the same because it was multiple trades at one price at the same time) I'm also graphing some technical indicators with
plot(addMACD(fast,slow,signal,maType,histogram))
and
plot(addSMA(n,overlay = overlay))
etc. which also work as intended just using the default values.
If I do a technical which overlays the technical onto the graph like bbands and SMA, the points can be graphed simultaneously. However, if I have a plot like MACD which is in a separate box that segregates the graph into two graphs in the same plot window, I can no longer plot the points. Why?!
The y-axis is reindexed according to the indicator added. I found that it's better to reindex it myself, then plot the graph by adjusting where the points should be. I'll include all the constants I found through that search here.
assuming your data is in OHLC in a variable called "theBars", do this par(usr=c(0,1,min(theBars),max(theBars)),xpd=TRUE)
I did all of this on a 1920x1200 resolution monitor, so all of the pixel measurements are in terms of that. This is compatible with any resolution by using par("fin")
Also, this executes in a fraction of a second. This was written for clarity, not speed.
Horizontal alignment across [0,1] with varying numbers of candles:
if(numBars < 10) stop("cannot plot less than 10 candles")
horizNumerator <- if(numBars == 10) 1547 else
if(numBars == 11) 1559 else
if(numBars == 12) 1568 else
if(numBars == 13) 1574 else
if(numBars == 14) 1581 else
if(numBars == 15) 1588 else
if(numBars == 16) 1592 else
if(numBars == 17) 1597 else
if(numBars == 18) 1601 else
if(numBars == 19) 1603 else
if(numBars == 20) 1606 else
if(numBars <= 30) 1626 + (numBars-30)/(10/20) else
if(numBars <= 40) 1636 + (numBars-40)/(10/10) else
if(numBars <= 50) 1641 + (numBars-50)/(10/7) else
if(numBars <= 60) 1646 + (numBars-60)/(10/5) else
if(numBars <= 100) 1651 + (numBars-100)/(40/5) else
if(numBars <= 140) 1655 + (numBars-140)/(40/4) else
if(numBars <= 312) 1658 + (numBars-312)/(172/3) else
if(numBars > 312) 1662
horizUnit <- (horizNumerator/1802)/(length(theBars[,1])-1)*ifelse(plotNum<2,1,1693/1655)*par("fin")[1]/20
startHoriz <- ifelse(plotNum<2,55/1802,35/1802)*par("fin")[1]/20
Vertical alignment, with plotNum
being the number of indicators already plotted and deltaP <- max(theBars)-min(theBars)
:
This deals with the indicators squishing the plot area
pixelStretch <- (switch(as.character(plotNum),"0"=975,"1"=665,"2"=551,"3"=465, "4"=400,"5"=352,"6"= 313))/(983)
deltaP <- max(theBars)-min(theBars)
This deals with the max moving slightly higher after an indicator is plotted
maxRaise <- if(plotNum == 0) 0 else
if(plotNum == 1) 15 else
if(plotNum == 2) 31 else
if(plotNum > 2) 36
maxRaise <- maxRaise*par("fin")[2]/12.0625/983
then plot points in a data column dataCol
like this
points.default(x=startHoriz + horizUnit*timeIndex,
y= maxRaise * deltaP + max(theBars)-((max(theBars)-as.numeric(dataCol[i]))*(pixelStretch)),
cex=dotSize,
pch=dotType,
col=thecolor)