I need to format the prices on a vertical axis as treasury futures are quoted in 32nd of a point. So instead of showing 123.5 I will show 123-16. And instead of showing 97.5703125, I will show 97-182
http://www.cmegroup.com/education/files ... utures.pdf
What's the best way to do this?
Thanks!
Formatting Yaxis prices for futures, ie "123-16" not "123.5"
-
- JFreeChart Project Leader
- Posts: 11734
- Joined: Fri Mar 14, 2003 10:29 am
- antibot: No, of course not.
- Contact:
Re: Formatting Yaxis prices for futures, ie "123-16" not "12
You need a custom NumberFormat subclass. As an example, you could look at the HexNumberFormat class in the org.jfree.chart.util.* package. If you get something working, it would be a great addition to JFreeChart if you want to make it available for inclusion in the library.
David Gilbert
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
Re: Formatting Yaxis prices for futures, ie "123-16" not "12
I'd be happy to contribute a futures price formatter. I expect it would throw "InvalidFuturesPrice" if someone tried to format a number which was not a valid futures price
But how do I make sure ticks lines on the vertical axis are only displayed at values representing valid futures price values? fractional portions must be some fraction of a 32nd (up to quarters of 32nds for some products) ie:
123.0 = 123-000 // OK
123.0078125 = 123-002 //OK
123.015625 = 123-005 // OK
...
123.4 // NOT OK invalid futures price
123.5 = 123-16 or 123-160 // OK
123.6 // NOT OK invalid futures price
Thanks!
But how do I make sure ticks lines on the vertical axis are only displayed at values representing valid futures price values? fractional portions must be some fraction of a 32nd (up to quarters of 32nds for some products) ie:
123.0 = 123-000 // OK
123.0078125 = 123-002 //OK
123.015625 = 123-005 // OK
...
123.4 // NOT OK invalid futures price
123.5 = 123-16 or 123-160 // OK
123.6 // NOT OK invalid futures price
Thanks!
-
- JFreeChart Project Leader
- Posts: 11734
- Joined: Fri Mar 14, 2003 10:29 am
- antibot: No, of course not.
- Contact:
Re: Formatting Yaxis prices for futures, ie "123-16" not "12
You could set the tick size to some multiple of 1/128. I guess you might need to take care of some small rounding errors while doing the number formatting.
David Gilbert
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
Re: Formatting Yaxis prices for futures, ie "123-16" not "12
Here it is...
Feel free to modify it or add it if you think it would help helpful.
Thanks!
Code: Select all
/*
*
* -----------------------
* TreasuryPriceFormat.java
* -----------------------
*
*/
// package org.jfree.chart.util;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.HashMap;
/**
* A custom number formatter that formats futures
* prices in 32nds of a point as described here:
* <p/>
* http://en.wikipedia.org/wiki/Commodity_tick
* and here:
* http://www.cmegroup.com/trading/interest-rates/files/IR147_USTreasuryRevised_Final_low_client.pdf
*
*/
public class TreasuryPriceFormat extends NumberFormat {
private boolean decimalIncluded;
private boolean trailingZeroIncluded;
private HashMap<String, String> m = new HashMap<String, String>();
/**
* Creates a new instance. if {@code trailingZeroIncluded} is false {@code decimalIncluded}
* is ignored.
*
* @param decimalIncluded Specify if a decimal should
* appear prior to any fraction of a 32nd. ie.,
* 123.3125 could be formatted as 123-100 or 123-10.0
*
* @param trailingZeroIncluded Specify if a trailing 0 should
* appear after a whole 32nd. ie.,
* 123.3125 could be formatted as 123-100 or 123-10.
* This should likely be {@code false} for displaying
* 30 year Treasury bond prices.
*/
public TreasuryPriceFormat(boolean decimalIncluded, boolean trailingZeroIncluded) {
super();
this.decimalIncluded = decimalIncluded;
this.trailingZeroIncluded = trailingZeroIncluded;
populateHashMap();
}
/**
* Returns if a trailing 0 will be shown.
*
* @return if a trailing 0 will be shown.
*/
public final boolean isTrailingZeroIncluded() {
return this.trailingZeroIncluded;
}
/**
* Returns if a decimal is included in formatted output.
*
* @return usingDecimal
*/
public final boolean isDecimalIncluded() {
return this.decimalIncluded;
}
@Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
return null;
}
/**
* Formats the specified double as a futures price in 32nds of a point
*
* @param number the number to format.
* @param toAppendTo the buffer to append to (ignored here).
* @param pos the field position (ignored here).
* @return The string buffer.
*/
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
return format(number + "", toAppendTo, pos);
}
/**
* Formats the specified String as a futures price in 32nds of a point
*
* @param number the number to format.
* @param toAppendTo the buffer to append to (ignored here).
* @param pos the field position (ignored here).
* @return The string buffer.
*/
public StringBuffer format(String number, StringBuffer toAppendTo, FieldPosition pos) {
StringBuffer sb = new StringBuffer();
int decimalIndex = number.indexOf('.');
if (decimalIndex == -1) {
sb.append(number);
noFraction(sb);
} else {
String whole = number.substring(0, decimalIndex);
String frac = number.substring(decimalIndex + 1);
frac = frac.trim();
//remove trailing zeros.
while (frac.endsWith("0")) frac = frac.substring(0, frac.length() - 1);
sb.append(whole);
if (frac.length() == 0) {
noFraction(sb);
} else {
String s = m.get(frac);
if (s == null) throw new NumberFormatException("Invalid futures price " + number + ".");
sb.append(s);
}
}
return sb;
}
private void noFraction(StringBuffer sb) {
if (trailingZeroIncluded) {
if (decimalIncluded) {
sb.append("-00.0");
} else {
sb.append("-000");
}
} else {
sb.append("-00");
}
}
/**
* Parsing is not implemented, so this method always returns
* <code>null</code>.
*
* @param source ignored.
* @param parsePosition ignored.
* @return Always <code>null</code>.
*/
public Number parse(String source, ParsePosition parsePosition) {
return null;
}
private String f(String s) {
if (trailingZeroIncluded) {
if (decimalIncluded) {
return s;
} else {
return s.replace(".", "");
}
} else {
return s.replace(".0", "");
}
}
private void populateHashMap() {
m.put("0078125", f("-00.2"));
m.put("015625", f("-00.5"));
m.put("0234375", f("-00.7"));
m.put("03125", f("-01.0"));
m.put("0390625", f("-01.2"));
m.put("046875", f("-01.5"));
m.put("0546875", f("-01.7"));
m.put("0625", f("-02.0"));
m.put("0703125", f("-02.2"));
m.put("078125", f("-02.5"));
m.put("0859375", f("-02.7"));
m.put("09375", f("-03.0"));
m.put("1015625", f("-03.2"));
m.put("109375", f("-03.5"));
m.put("1171875", f("-03.7"));
m.put("125", f("-04.0"));
m.put("1328125", f("-04.2"));
m.put("140625", f("-04.5"));
m.put("1484375", f("-04.7"));
m.put("15625", f("-05.0"));
m.put("1640625", f("-05.2"));
m.put("171875", f("-05.5"));
m.put("1796875", f("-05.7"));
m.put("1875", f("-06.0"));
m.put("1953125", f("-06.2"));
m.put("203125", f("-06.5"));
m.put("2109375", f("-06.7"));
m.put("21875", f("-07.0"));
m.put("2265625", f("-07.2"));
m.put("234375", f("-07.5"));
m.put("2421875", f("-07.7"));
m.put("25", f("-08.0"));
m.put("2578125", f("-08.2"));
m.put("265625", f("-08.5"));
m.put("2734375", f("-08.7"));
m.put("28125", f("-09.0"));
m.put("2890625", f("-09.2"));
m.put("296875", f("-09.5"));
m.put("3046875", f("-09.7"));
m.put("3125", f("-10.0"));
m.put("3203125", f("-10.2"));
m.put("328125", f("-10.5"));
m.put("3359375", f("-10.7"));
m.put("34375", f("-11.0"));
m.put("3515625", f("-11.2"));
m.put("359375", f("-11.5"));
m.put("3671875", f("-11.7"));
m.put("375", f("-12.0"));
m.put("3828125", f("-12.2"));
m.put("390625", f("-12.5"));
m.put("3984375", f("-12.7"));
m.put("40625", f("-13.0"));
m.put("4140625", f("-13.2"));
m.put("421875", f("-13.5"));
m.put("4296875", f("-13.7"));
m.put("4375", f("-14.0"));
m.put("4453125", f("-14.2"));
m.put("453125", f("-14.5"));
m.put("4609375", f("-14.7"));
m.put("46875", f("-15.0"));
m.put("4765625", f("-15.2"));
m.put("484375", f("-15.5"));
m.put("4921875", f("-15.7"));
m.put("5", f("-16.0"));
m.put("5078125", f("-16.2"));
m.put("515625", f("-16.5"));
m.put("5234375", f("-16.7"));
m.put("53125", f("-17.0"));
m.put("5390625", f("-17.2"));
m.put("546875", f("-17.5"));
m.put("5546875", f("-17.7"));
m.put("5625", f("-18.0"));
m.put("5703125", f("-18.2"));
m.put("578125", f("-18.5"));
m.put("5859375", f("-18.7"));
m.put("59375", f("-19.0"));
m.put("6015625", f("-19.2"));
m.put("609375", f("-19.5"));
m.put("6171875", f("-19.7"));
m.put("625", f("-20.0"));
m.put("6328125", f("-20.2"));
m.put("640625", f("-20.5"));
m.put("6484375", f("-20.7"));
m.put("65625", f("-21.0"));
m.put("6640625", f("-21.2"));
m.put("671875", f("-21.5"));
m.put("6796875", f("-21.7"));
m.put("6875", f("-22.0"));
m.put("6953125", f("-22.2"));
m.put("703125", f("-22.5"));
m.put("7109375", f("-22.7"));
m.put("71875", f("-23.0"));
m.put("7265625", f("-23.2"));
m.put("734375", f("-23.5"));
m.put("7421875", f("-23.7"));
m.put("75", f("-24.0"));
m.put("7578125", f("-24.2"));
m.put("765625", f("-24.5"));
m.put("7734375", f("-24.7"));
m.put("78125", f("-25.0"));
m.put("7890625", f("-25.2"));
m.put("796875", f("-25.5"));
m.put("8046875", f("-25.7"));
m.put("8125", f("-26.0"));
m.put("8203125", f("-26.2"));
m.put("828125", f("-26.5"));
m.put("8359375", f("-26.7"));
m.put("84375", f("-27.0"));
m.put("8515625", f("-27.2"));
m.put("859375", f("-27.5"));
m.put("8671875", f("-27.7"));
m.put("875", f("-28.0"));
m.put("8828125", f("-28.2"));
m.put("890625", f("-28.5"));
m.put("8984375", f("-28.7"));
m.put("90625", f("-29.0"));
m.put("9140625", f("-29.2"));
m.put("921875", f("-29.5"));
m.put("9296875", f("-29.7"));
m.put("9375", f("-30.0"));
m.put("9453125", f("-30.2"));
m.put("953125", f("-30.5"));
m.put("9609375", f("-30.7"));
m.put("96875", f("-31.0"));
m.put("9765625", f("-31.2"));
m.put("984375", f("-31.5"));
m.put("9921875", f("-31.7"));
}
/**
* Returns a new {@code TreasuryPriceFormat} with the same
* properties as this {@code TreasuryPriceFormat}.
*/
@Override
public Object clone() {
TreasuryPriceFormat clone = (TreasuryPriceFormat) super.clone();
clone.decimalIncluded = decimalIncluded;
clone.trailingZeroIncluded = trailingZeroIncluded;
return clone;
}
}
Feel free to modify it or add it if you think it would help helpful.
Thanks!