Jasper Reports Server 6.2 does not apply setNumberFormatOverride - java

I am trying to customize a StackedBar3D chart in Jasper Reports to show ticks in one hour increments for values which are in milliseconds. I achieved this with the following code in JasperServer 6.1 running on windows. My problem is when I try to execute the same report and jar in JasperServer 6.2 running on Centos it applies tick unit but numberformatoverride is ignored showing ticks in millions. Weird thing is I also executed the same report successfully with the same data running with Java (without server) with Jasper Reports 6.2 library.
public class TickCustomizer implements JRChartCustomizer, Serializable
{
private static final long serialVersionUID = 4445304350656126487L;
public void customize ( JFreeChart chart, JRChart jasperChart )
{
CategoryPlot plot = chart.getCategoryPlot();
ValueAxis rangeAxis = plot.getRangeAxis();
NumberAxis numberAxis = (NumberAxis) rangeAxis;
numberAxis.setTickUnit( new NumberTickUnit( 3600000 ) );
numberAxis.setTickLabelsVisible( true );
numberAxis.setTickMarksVisible( true );
numberAxis.setNumberFormatOverride( new DecimalFormat()
{
private static final long serialVersionUID = 1L;
public StringBuffer format ( double number, StringBuffer toAppendTo, FieldPosition pos )
{
return toAppendTo.append( (int) ( number / 3600000 ) );
}
#Override
public StringBuffer format ( long number, StringBuffer toAppendTo, FieldPosition pos )
{
return toAppendTo.append( (int) ( number / 3600000 ) );
}
#Override
public Number parse ( String source ) throws ParseException
{
return null;
}
} );
plot.setRangeAxis( numberAxis );
}

Related

JavaFX: Bind SimpleLongProperty to a Label and format long value to human readable filesize

I have a Label which is binded to two Properties. The first value (deletedFilesCountProperty) is a simple int without needing for formatting. But how can I format the second property (SimpleLongProperty) to a human readable filesize value?
Example:
deletedFilesSize's value is 1000000.
The label should show "1MB" instead.
Can I call the humanReadableByteCount function inside the Binding to let this function format the value?
My code so far:
public class MainController implements Initializable {
private final SimpleIntegerProperty deletedFilesCount = new SimpleIntegerProperty();
private final SimpleLongProperty deletedFilesSize = new SimpleLongProperty();
#FXML
Label deletedFilesLabel;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
deletedFilesLabel.textProperty().bind(Bindings.format("Deleted files: %d (%d)", deletedFilesCountProperty(), deletedFilesSizeProperty()));
}
/**
* formats a long number to a human readable file size value
* returns something like: 2MB or 4GB and so on instead of very long Long values.
*/
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit)
return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
}
Thanks.
Use Bindings.createStringBinding(...). A simple example would look like:
fileSizeLabel.bind(Bindings.createStringBinding(
() -> humanReadableByteCount(deletedFilesSizeProperty().get(), false),
deletedFilesSizeProperty()
));
Your specific example would look something like:
deletedFilesLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format(
"Deleted files: %d (%s)",
deletedFilesCountProperty().get(),
humanReadableByteCount(deletedFilesSizeProperty().get(), false)
),
deletedFilesCountProperty(),
deletedFilesSizeProperty()
));

Different EMA (Exponential Moving Average) than on Binance

I am writing a Java program by using the Binance JAVA API to retrieve the 1-minute interval candelsticks of a trading pair. Using this Java class, I want to calculate the EMA (Exponential Moving Average) of the past 10 days.
The Binance JAVA API websocket implementation gets the latest depth events, which also contains the current closing price that I use to update the EMA calculation by calling the EMA#update method.
However, I notice that the EMA showing on the Binance's graph, does not correspond to the ones I get from my code. Also, I notice that the values need some time to 'settle' before giving (somewhat) same values compared to those shown on Binance.
On TradingView I found a formula to calculate the EMA (that shows the same EMA value as on Binance), but that is different than the one used in the EMA class. However, even when using this formula, the values are very different than the one on Binance.
Could someone help me figure out what the issue is and how to obtain the same values?
UPDATE 1: code provided
import java.util.*;
import java.util.stream.Collectors;
import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.BinanceApiRestClient;
import com.binance.api.client.BinanceApiWebSocketClient;
import com.binance.api.client.domain.market.Candlestick;
import com.binance.api.client.domain.market.CandlestickInterval;
import core.util.text.DecimalFormat;
import core.util.text.StringUtil;
public class test_003
{
private Map<Long, Candlestick> candlesticksCache = new TreeMap<>();
private EMA EMA_10;
private EMA EMA_20;
public static void main(String[] pArgs)
{
new test_003();
}
private test_003()
{
Locale.setDefault(Locale.US);
candlesticksCacheExample("ADAUSDT", CandlestickInterval.ONE_MINUTE);
}
private void candlesticksCacheExample(String symbol, CandlestickInterval interval)
{
initializeCandlestickCache(symbol, interval);
startCandlestickEventStreaming(symbol, interval);
}
private void initializeCandlestickCache(String symbol, CandlestickInterval interval)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance();
BinanceApiRestClient client = factory.newRestClient();
List<Candlestick> candlestickBars_10 = client.getCandlestickBars(symbol.toUpperCase(), interval, Integer.valueOf(11), null, null);
List<Candlestick> candlestickBars_20 = client.getCandlestickBars(symbol.toUpperCase(), interval, Integer.valueOf(21), null, null);
List<Double> closingPriceList_10 = candlestickBars_10.stream().map(c -> Double.valueOf(c.getClose())).collect(Collectors.toList());
List<Double> closingPriceList_20 = candlestickBars_20.stream().map(c -> Double.valueOf(c.getClose())).collect(Collectors.toList());
EMA_10 = new EMA(closingPriceList_10, Integer.valueOf(10));
EMA_20 = new EMA(closingPriceList_20, Integer.valueOf(20));
}
private void startCandlestickEventStreaming(String symbol, CandlestickInterval interval)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance();
BinanceApiWebSocketClient client = factory.newWebSocketClient();
client.onCandlestickEvent(symbol.toLowerCase(), interval, response -> {
Long openTime = response.getOpenTime();
Candlestick updateCandlestick = candlesticksCache.get(openTime);
if (updateCandlestick == null)
{
// new candlestick
updateCandlestick = new Candlestick();
}
// update candlestick with the stream data
updateCandlestick.setOpenTime(response.getOpenTime());
updateCandlestick.setOpen(response.getOpen());
updateCandlestick.setLow(response.getLow());
updateCandlestick.setHigh(response.getHigh());
updateCandlestick.setClose(response.getClose());
updateCandlestick.setCloseTime(response.getCloseTime());
updateCandlestick.setVolume(response.getVolume());
updateCandlestick.setNumberOfTrades(response.getNumberOfTrades());
updateCandlestick.setQuoteAssetVolume(response.getQuoteAssetVolume());
updateCandlestick.setTakerBuyQuoteAssetVolume(response.getTakerBuyQuoteAssetVolume());
updateCandlestick.setTakerBuyBaseAssetVolume(response.getTakerBuyQuoteAssetVolume());
// Store the updated candlestick in the cache
candlesticksCache.put(openTime, updateCandlestick);
double closingPrice = Double.valueOf(updateCandlestick.getClose());
EMA_10.update(closingPrice);
EMA_20.update(closingPrice);
System.out.println(StringUtil.replacePlaceholders("Closing price: %1 | EMA(10): %2 - EMA(20): %3", response.getClose(),
DecimalFormat.format(EMA_10.get(), "#.#####"),
DecimalFormat.format(EMA_20.get(), "#.#####")));
});
}
public class EMA
{
private double currentEMA;
private final int period;
private final double multiplier;
private final List<Double> EMAhistory;
private final boolean historyNeeded;
private String fileName;
public EMA(List<Double> closingPrices, int period)
{
this(closingPrices, period, false);
}
public EMA(List<Double> closingPrices, int period, boolean historyNeeded)
{
currentEMA = 0;
this.period = period;
this.historyNeeded = historyNeeded;
this.multiplier = 2.0 / (double) (period + 1);
this.EMAhistory = new ArrayList<>();
init(closingPrices);
}
public double get()
{
return currentEMA;
}
public double getTemp(double newPrice)
{
return (newPrice - currentEMA) * multiplier + currentEMA;
}
public void init(List<Double> closingPrices)
{
if (period > closingPrices.size()) return;
//Initial SMA
for (int i = 0; i < period; i++)
{
currentEMA += closingPrices.get(i);
}
currentEMA = currentEMA / (double) period;
if (historyNeeded) EMAhistory.add(currentEMA);
//Dont use latest unclosed candle;
for (int i = period; i < closingPrices.size() - 1; i++)
{
update(closingPrices.get(i));
}
}
public void update(double newPrice)
{
// EMA = (Close - EMA(previousBar)) * multiplier + EMA(previousBar)
currentEMA = (newPrice - currentEMA) * multiplier + currentEMA;
if (historyNeeded) EMAhistory.add(currentEMA);
}
public int check(double newPrice)
{
return 0;
}
public String getExplanation()
{
return null;
}
public List<Double> getEMAhistory()
{
return EMAhistory;
}
public int getPeriod()
{
return period;
}
}
}
UPDATE 2
The problem is that onCandlestickEvent is not just called when a candle is completed, but actually multiple times per minute (every 2 seconds or so). The data that you are receiving in the response spans the time from when the candle is opened until the event time of the response, whether the candle is completed or not.
To see what I mean, you could replace the System.out() statement in your startCandlestickEventStreaming method with the following:
System.out.println(response.getOpenTime() + ";" +
response.getEventTime() + ";" +
response.getCloseTime());
You will see that the close time of the candle actually lies in the future.
In order to update your EMA correctly, you will have to wait until the candle has actually been completed. You could store the open time of the tentative candle in a member variable, check if it has changed since the last time onCandlestickEvent was called, and then update your EMA with the final close value of the candle:
client.onCandlestickEvent(symbol.toLowerCase(), interval, response -> {
Long openTime = response.getOpenTime();
Candlestick updateCandlestick = candlesticksCache.get(openTime);
if (updateCandlestick == null)
{
// new candlestick
updateCandlestick = new Candlestick();
}
// update candlestick with the stream data
...
// Store the updated candlestick in the cache
candlesticksCache.put(openTime, updateCandlestick);
if (openTime > m_LastOpenTime)
{
// need to get the close of the PREVIOUS candle
Candlestick previousCandle = candlesticksCache.get(m_LastOpenTime);
double closingPrice = Double.valueOf(previousCandle.getClose());
EMA_10.update(closingPrice);
EMA_20.update(closingPrice);
System.out.println(StringUtil.replacePlaceholders("Closing price: %1 | EMA(10): %2 - EMA(20): %3", response.getClose(),
DecimalFormat.format(EMA_10.get(), "#.#####"),
DecimalFormat.format(EMA_20.get(), "#.#####")));
m_LastOpenTime = openTime;
}
});
You'll probably get an exception on the first response, because there are no candles on the stack yet and we don't have a m_LastOpenTime. You could get the current server time before calling client.onCandlestickEvent():
private void startCandlestickEventStreaming(String symbol, CandlestickInterval interval)
{
BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance();
BinanceApiWebSocketClient client = factory.newWebSocketClient();
BinanceApiRestClient restClient = factory.newRestClient();
m_LastOpenTime = restClient.getServerTime();
client.onCandlestickEvent(symbol.toLowerCase(), interval, response -> {
...
}
}
I noticed there's actually a much simpler way than my other answer. I'm leaving that one up, however, because it could still be relevant for dealing with a dodgy connection where you can't necessarily rely on always getting the final candlestick with your response.
The response.getBarFinal()) method allows for testing whether the response you have received is the final candlestick or if it is just an intermediate one. If you change your code as follows, your EMA will only get updated with the final close value of the candle as it should be:
if (response.getBarFinal())
{
double closingPrice = Double.valueOf(updateCandlestick.getClose());
EMA_10.update(closingPrice);
EMA_20.update(closingPrice);
System.out.println(StringUtil.replacePlaceholders("Closing price: %1 | EMA(10): %2 - EMA(20): %3", response.getClose(),
DecimalFormat.format(EMA_10.get(), "#.#####"),
DecimalFormat.format(EMA_20.get(), "#.#####")));
}

Java JFree chart realtime chart convert domain label from millis to HH:MM:SS

I created a real time chart with JFreechart where the Domain axis is epoch millis. I would like the labels to display HH:MM:SS.
Here is the block of code that I use to load the chart with data. I am very new to Java and any suggestions are very much appreciated.
Thread thread = new Thread(){
public void run() {
try (Scanner scanner = new Scanner(chosenPort.getInputStream())) { // Read Data from Serial Port
int x = 0; // Set data
while(scanner.hasNextLine()) {
long epoch = System.currentTimeMillis();
chart.getXYPlot().getDomainAxis().setRange(epoch - 30000.00, epoch + 1000.00);
try{
String line = scanner.nextLine();
int number = Integer.parseInt(line); //
series.add(epoch,number); // add Data to Chart
p1.repaint();
}catch(Exception e) {}
}
}
}
};
I was using an XYseries Line chart instead of a time series chart. By using JFreeChart chart = ChartFactory.createTimeSeriesChart instead of JFreeChart chart = ChartFactory.createXYLineChart the correct date/time values were interpreted and displayed automatically.

Real time on x-axis with adjustable scale on x-axis?

I want to implement a trend graph with real time data coming continuously,for which am having time on x-axis with format "HH:MM:SS". Now my requirement is to have adjustable scale like 10min or 15min etc....And also how could i limit the time values on x-axis ?
Please help me.
Thanks!
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.SeriesException;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class TimeSeries_AWT extends ApplicationFrame
{
public TimeSeries_AWT( final String title )
{
super( title );
final XYDataset dataset = createDataset( );
final JFreeChart chart = createChart( dataset );
final ChartPanel chartPanel = new ChartPanel( chart );
chartPanel.setPreferredSize( new java.awt.Dimension( 560 , 370 ) );
chartPanel.setMouseZoomable( true , false );
setContentPane( chartPanel );
}
private XYDataset createDataset( )
{
final TimeSeries series = new TimeSeries( "Random Data" );
Second current = new Second( );
double value = 100.0;
for (int i = 0; i < 4000; i++)
{
try
{
value = value + Math.random( ) - 0.5;
series.add(current, new Double( value ) );
current = ( Second ) current.next( );
}
catch(SeriesException e )
{
System.err.println("Error adding to series");
}
}
return new TimeSeriesCollection(series);
}
private JFreeChart createChart( final XYDataset dataset )
{
return ChartFactory.createTimeSeriesChart(
"Computing Test",
"Seconds",
"Value",
dataset,
false,
false,
false);
}
public static void main( final String[ ] args )
{
final String title = "Time Series Management";
final TimeSeries_AWT demo = new TimeSeries_AWT( title );
demo.pack( );
RefineryUtilities.positionFrameRandomly( demo );
demo.setVisible( true );
}
}
If you see output, the time is constant just static not changing dynamically. and while if time updates dynamically,i want the scale or tickunits to be adjusted dynamically at runtime like for example in the output graph the scale time is 5min. but i want that to be controlled at runtime to be anything like 10min,20min,40min etc...
And another thing is in the output graph we can see 14 values on x-axis.which changes automatically when the graph is resized.but i want to control how many to be seen on the x-axis means i want to show some particular x time values on x-axis.which should also be configurable at launch of application.

Jfreechart: How exclude weekend days from chart?

How exclude one or two day from jfreechart? I have input date without saturday and chart without saturday, but in axis there all date.
I have all added item on screen. How viewing <= 100 item on screen and if scrolling to right item add more.
UPDATE:
I make CandleChart, used JfreeChart library.
Between 12 and 14 days chart should not be interrupted.
This is string:
One or few day is maybe off-time.
12.10.2012 19:00 1.2951 1.296 1.2947 1.2956
12.10.2012 20:00 1.2956 1.296 1.295 1.2954
**12.10.2012 21:00 1.2955 1.2959 1.2948 1.2949**
**14.10.2012 22:00 1.2952 1.296 1.2948 1.2953**
14.10.2012 23:00 1.2955 1.2955 1.2942 1.2947
This is code:
static TimeSeries t1 = new TimeSeries("");
RegularTimePeriod day = new Day();
RegularTimePeriod hour = new Hour();
private static OHLCDataset createPriceDataset(String FILENAME_SD)
{
OHLCSeries s1 = new OHLCSeries(FILENAME_SD);
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
}
File sdPath = Environment.getExternalStorageDirectory();
sdPath = new File(sdPath.getAbsolutePath() + "/" + DIR_SD);
File sdFile = new File(sdPath, FILENAME_SD);
try {
BufferedReader in = new BufferedReader(new FileReader(sdFile));
DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm");
String inputLine;
in.readLine();
while ((inputLine = in.readLine()) != null) {
String[] data = inputLine.split("\\s+");
Date date = df.parse(data[0] + " " + data[1]);
double open = Double.parseDouble( data[2] );
double high = Double.parseDouble( data[3] );
double low = Double.parseDouble( data[4] );
double close = Double.parseDouble( data[5] );
// double volume = Double.parseDouble( st.nextToken() );
//double adjClose = Double.parseDouble( st.nextToken() );
s1.add(new Hour(date), open, high, low, close);
t1.add(new Hour(date), open);
}
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
OHLCSeriesCollection dataset = new OHLCSeriesCollection();
dataset.addSeries(s1);
return dataset;
}
Also, diagram zoom depends on how mach string in file. How drawing candles no more than 100 on screen?
This is chart from file with many strings:
This is chart from file with few strings:
If it's particularly candlestick you want to do this with, I do not believe that JFreechart class supports it. You could use Box And Whisker to imitate the behavior while using category based data. For the charts you've shown the axis represents continuous data, categorical axis are for discrete data.
Example code is shown here:
http://www.java2s.com/Code/Java/Chart/JFreeChartBoxAndWhiskerDemo.htm
With that you can choose your own discrete points to be represented on the graph.
If it's for anything other than candlesticks, Graham was right and DefaultCategoryDataset would be more useful:
http://www.jfree.org/jfreechart/api/javadoc/org/jfree/data/category/DefaultCategoryDataset.html

Categories

Resources