From 6ba4f1896cba1665c2f27a7dc3fe66190c8fee63 Mon Sep 17 00:00:00 2001 From: 7u83 <7u83@maiol.ru> Date: Sat, 18 Feb 2017 23:32:03 +0100 Subject: [PATCH] More chart improvements --- src/main/java/chart/Chart.java | 318 ++++++++++++++++-------------- src/main/java/sesim/OHLCData.java | 138 +++++++------ 2 files changed, 248 insertions(+), 208 deletions(-) diff --git a/src/main/java/chart/Chart.java b/src/main/java/chart/Chart.java index 74a8c22..b4b4d79 100644 --- a/src/main/java/chart/Chart.java +++ b/src/main/java/chart/Chart.java @@ -31,22 +31,18 @@ import sesim.Scheduler; public class Chart extends javax.swing.JPanel implements QuoteReceiver, Scrollable { class ChartDef { - - } - - - - protected int em_size = 1; - - protected float bar_width = 2.0f; - - - public void setBarWidth(float bw){ - bar_width=bw; } - - + + protected int em_size = 1; + protected double x_unit_width = 1.0; + + protected float bar_width = 0.9f * 2.0f; + + public void setBarWidth(float bw) { + bar_width = bw; + } + //protected float bar_width_em = 1; protected float y_legend_width = 10; @@ -64,13 +60,11 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver, Scrollab this.setCompression(10000); } - - /** * Creates new form Chart */ public Chart() { - if (Globals.se==null){ + if (Globals.se == null) { return; } @@ -83,53 +77,49 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver, Scrollab } Globals.se.addQuoteReceiver(this); - + // scrollPane=new JScrollPane(); - // scrollPane.setViewportView(this); - - + // scrollPane.setViewportView(this); } - private String [] ctxMenuCompressionText = { + private String[] ctxMenuCompressionText = { "5 s", "10 s", "15 s", "30 s", "1 m", "2 m", "5 m", "10 m", "15 m", "30 m", "1 h", "2 h", "4 h", "1 d", "2 d" }; - private Integer[] ctxMenuCompressionValues ={ - 5*1000, 10*1000, 15*1000, 30*1000, - 60*1000, 2*60*1000, 5*60*1000, 10*60*1000, 15*60*1000, 30*60*1000, - 1*3600*1000,2*3600*1000, 4*3600*1000, - 1*24*3600*1000, 2*24*3600*1000 + private Integer[] ctxMenuCompressionValues = { + 5 * 1000, 10 * 1000, 15 * 1000, 30 * 1000, + 60 * 1000, 2 * 60 * 1000, 5 * 60 * 1000, 10 * 60 * 1000, 15 * 60 * 1000, 30 * 60 * 1000, + 1 * 3600 * 1000, 2 * 3600 * 1000, 4 * 3600 * 1000, + 1 * 24 * 3600 * 1000, 2 * 24 * 3600 * 1000 }; - + void initCtxMenu() { - for (int i=0; i { - ctxMenuCompActionPerformed(evt); + for (int i = 0; i < this.ctxMenuCompressionValues.length; i++) { + JMenuItem item = new JMenuItem(this.ctxMenuCompressionText[i]); + + item.addActionListener((java.awt.event.ActionEvent evt) -> { + ctxMenuCompActionPerformed(evt); }); - this.compMenu.add(item); + this.compMenu.add(item); + } } - } - + private void ctxMenuCompActionPerformed(java.awt.event.ActionEvent evt) { String cmd = evt.getActionCommand(); - for (int i=0;i it = data.iterator(); @@ -433,26 +464,34 @@ System.out.printf("Dim: %d %d %d %d\n", dim.x,dim.y,dim.width,dim.height); RenderCtx ctx = new RenderCtx(); -// MinMax mm = data.getMinMax(first_bar, last_bar); -// if(mm==null) -// return ; + c_rect.x = 0; + c_rect.y = 50; + c_rect.height = 100; ctx.rect = c_rect; ctx.scaling = (float) r.height / (c_mm.getMax() - c_mm.getMin()); ctx.min = c_mm.getMin(); ctx.g = g; - ctx.iwidth = (bar_width * em_size) * 0.9f; // em_width - em_width / 5f; + ctx.iwidth = (float) ((x_unit_width * em_size) * 0.9f); - //g.setClip(clip_bounds.x, clip_bounds.y, (int)(clip_bounds.width-this.y_legend_width*this.em_size), clip_bounds.height); - for (int i = first_bar; i < last_bar && i < data.size(); i++) { - OHLCDataItem di = data.get(i); - int x = (int) (i * em_size * bar_width); //em_width; - this.drawItem(ctx, x - em_width, x, prev, di); //, ctx.scaling, data.getMin()); + this.ct = ChartType.CANDLESTICK; + drawChart(ctx); - // myi++; - prev = di; + c_mm = data.getVolMinMax(first_bar, last_bar); - } + System.out.printf("Volminmax: %f %f\n", c_mm.min, c_mm.max); + c_mm.min = 0f; + c_rect.x = 0; + c_rect.y = 250; + c_rect.height = 50; + ctx.rect = c_rect; + ctx.scaling = (float) r.height / (c_mm.getMax() - c_mm.getMin()); + ctx.min = c_mm.getMin(); + ctx.g = g; + ctx.iwidth = (float) ((x_unit_width * em_size) * 0.9f); + + this.ct = ChartType.VOL; + drawChart(ctx); //System.out.printf("Scaling: %f %f %f %f %f\n",diff,(float)r.height,data.getMin(),data.getMax(),yscaling); /* while (it.hasNext()) { OHLCDataItem di = it.next(); @@ -467,7 +506,6 @@ System.out.printf("Dim: %d %d %d %d\n", dim.x,dim.y,dim.width,dim.height); */ } - private float c_font_height; @Override @@ -476,45 +514,33 @@ System.out.printf("Dim: %d %d %d %d\n", dim.x,dim.y,dim.width,dim.height); // Calculate the number of pixels for 1 em em_size = g.getFontMetrics().stringWidth("M"); - this.gdim = this.getParent().getSize(gdim); this.getParent().setPreferredSize(gdim); - Object o = this.getParent(); - + //Object o = this.getParent(); JViewport vp = (JViewport) this.getParent(); - vp.getExtentSize(); - - - - this.clip_bounds=g.getClipBounds(); - - Dimension r = vp.getExtentSize(); - - System.out.printf("Repainting called %d %d %d %d\n", r.width,r.height,clip_bounds.width,clip_bounds.height); - - clip_bounds.width=r.width; - clip_bounds.height=r.height; - clip_bounds.x=0; - clip_bounds.y=0; - Point vvp = vp.getViewPosition(); - clip_bounds.x=vvp.x; - clip_bounds.y=vvp.y; - - this.clip_bounds=vp.getViewRect(); - + + //this.clip_bounds=g.getClipBounds(); + this.clip_bounds = vp.getViewRect(); +// vp.setViewPosition(new Point(0,0)); // System.out.printf("X:%d %d\n",gdim.width,gdim.height); - first_bar = (int) (clip_bounds.x / (this.bar_width * this.em_size)); - last_bar = 1 + (int) ((clip_bounds.x + clip_bounds.width - (this.y_legend_width * em_size)) / (this.bar_width * this.em_size)); + first_bar = (int) (clip_bounds.x / (this.x_unit_width * this.em_size)); + last_bar = 1 + (int) ((clip_bounds.x + clip_bounds.width - (this.y_legend_width * em_size)) / (this.x_unit_width * this.em_size)); +// int vpwidth=(int) ((last_bar-first_bar)*x_unit_width*em_size); + num_bars=data.size() + (int) (clip_bounds.width / (this.x_unit_width * this.em_size))+5; + + c_font_height = g.getFontMetrics().getHeight(); - - System.out.printf("First %d, last %d\n", first_bar,last_bar); + + + System.out.printf("First %d, last %d\n", first_bar, last_bar); + draw((Graphics2D) g); } @@ -568,11 +594,10 @@ System.out.printf("Dim: %d %d %d %d\n", dim.x,dim.y,dim.width,dim.height); return; }; - this.invalidate(); - + // this.invalidate(); this.ctxMenu.setVisible(true); this.ctxMenu.show(this, evt.getX(), evt.getY()); - + this.invalidate(); this.repaint(); @@ -584,8 +609,7 @@ System.out.printf("Dim: %d %d %d %d\n", dim.x,dim.y,dim.width,dim.height); invalidate(); repaint(); } - - + @Override public void UpdateQuote(Quote q) { // System.out.print("Quote Received\n"); diff --git a/src/main/java/sesim/OHLCData.java b/src/main/java/sesim/OHLCData.java index abb29cd..4200d24 100644 --- a/src/main/java/sesim/OHLCData.java +++ b/src/main/java/sesim/OHLCData.java @@ -31,58 +31,79 @@ import java.util.*; * * @author 7u83 <7u83@mail.ru> */ -public class OHLCData { +public class OHLCData { - private float max=0; - private float min=0; - - private int frame_size=60000; - int max_size=100; - - - - public OHLCData(){ + private float max = 0; + private float min = 0; + + private int frame_size = 60000; + int max_size = 100; + + public OHLCData() { } - - public OHLCData(int frame_size){ - - this.frame_size=frame_size; + + public OHLCData(int frame_size) { + + this.frame_size = frame_size; } public float getMax() { return max; } - - public float getMin(){ + + public float getMin() { return min; } - - public int size(){ + + public int size() { return data.size(); } - - - public int getFrameSize(){ + + public int getFrameSize() { return this.frame_size; } - - public MinMax getMinMax(int first, int last){ - - if (first>=data.size()) - return null; - + + public MinMax getMinMax(int first, int last) { + + if (first >= data.size()) { + OHLCDataItem di = data.get(data.size() - 1); + return new MinMax(di.low, di.high); + } + OHLCDataItem di = data.get(first); - MinMax minmax=new MinMax(di.low,di.high); - - for (int i=first+1; i minmax.max) { + minmax.max = di.high; + } + } + return minmax; + } + + public MinMax getVolMinMax(int first, int last) { + + if (first >= data.size()) { + OHLCDataItem di = data.get(data.size() - 1); + return new MinMax(di.volume, di.volume); + } + + OHLCDataItem di = data.get(first); + MinMax minmax = new MinMax(di.volume, di.volume); + + for (int i = first + 1; i < last && i < data.size(); i++) { + di = data.get(i); + if (di.volume < minmax.min) { + minmax.min = di.volume; + } + if (di.volume > minmax.max) { + minmax.max = di.volume; } - if (di.high>minmax.max){ - minmax.max=di.high; - } } return minmax; } @@ -95,57 +116,52 @@ public class OHLCData { } public ArrayList data = new ArrayList<>(); - - public OHLCDataItem get(int n){ + + public OHLCDataItem get(int n) { return data.get(n); } - - - private void updateMinMax(float price){ - if (price > max){ - + + private void updateMinMax(float price) { + if (price > max) { + max = price; } - if (price < min){ + if (price < min) { min = price; } } - - public Iterator iterator(){ + + public Iterator iterator() { return data.iterator(); - } + } // Start and end of current frame private long current_frame_end = 0; - private long current_frame_start =0; + private long current_frame_start = 0; public boolean realTimeAdd(long time, float price, float volume) { - - + if (time >= current_frame_end) { - if (current_frame_end==0){ - - this.min=price; - this.max=price; + if (current_frame_end == 0) { + + this.min = price; + this.max = price; } - - long last_frame_start=current_frame_start; + + long last_frame_start = current_frame_start; current_frame_start = getFrameStart(time); - - - + current_frame_end = current_frame_start + frame_size; - + //System.out.printf("TA %d TE %d\n",this.current_frame_start,this.current_frame_end); - data.add(new OHLCDataItem(this.current_frame_start, price, volume)); this.updateMinMax(price); return true; } this.updateMinMax(price); - + OHLCDataItem d = data.get(data.size() - 1); boolean rc = d.update(price, volume); return rc;