Double aggregation of queryset in django - django

I need perform what is essentially a double aggregation. First, I need to get the average for the same events from different sources per ticker. Next, I need to get the sum of different events per ticker.
I can't figure out how to do this using Django. I've tried:
query1 = queryset.values('ticker', 'event_id').annotate(value_usd=Avg('value_usd'), shares=Avg('shares'), days_to_trade=Avg('days_to_trade'), num_trades=Count('ticker'))
query2 = query1.values('ticker').annotate(value_usd=Sum('value_usd'), shares=Sum('shares'), days_to_trade=Sum('days_to_trade'), num_trades=Count('security'))
but I receive an error django.core.exceptions.FieldError: Cannot compute Sum('value_usd'): 'value_usd' is an aggregate.
My raw data looks like this:
[{
'ticker': 'ACVA-US',
'source': 'INTERNAL',
'event_id': 300,
'value_usd': 3000.0,
'shares': 300.0,
'days_to_trade': 3.0,
'num_trades': 1
},
{
'ticker': 'ACVA-US',
'source': 'INTERNAL',
'event_id': 200,
'value_usd': 2000.0,
'shares': 200.0,
'days_to_trade': 2.0,
'num_trades': 1
},
{
'ticker': 'ACVA-US',
'source': 'EXTERNAL',
'event_id': 200,
'value_usd': 1000.0,
'shares': 100.0,
'days_to_trade': 1.0,
'num_trades': 1
}]
I need to perform what is essentially a double-aggregation. First, I need to take the average of items with the same ticker+event, which would look like:
[{
'ticker': 'ACVA-US',
'event_id': 300,
'value_usd': 3000.0,
'shares': 300.0,
'days_to_trade': 3.0,
'num_trades': 1
},
{
'ticker': 'ACVA-US',
'event_id': 200,
'value_usd': 1500.0,
'shares': 150.0,
'days_to_trade': 1.5,
'num_trades': 2
}]
Next, I need to sum up items across tickers, which would look like:
[{
'ticker': 'ACVA-US',
'value_usd': 4500.0,
'shares': 450.0,
'days_to_trade': 4.5,
'num_trades': 3
}]
I was hoping to do this without having to create a db view that performs the first aggregation, but so far I can't figure it out. I need to perform this at the queryset level without dropping into raw SQL because a bunch of other filtering occurs before and after this. Any advice?

Related

ApexCharts - Custom bar colour

Is it possible to customise the colour of each bar in a column chart ?
This is the kind of data I'm having using React:
const [data, setData] = useState([{
data: [{
x: 'Apple',
y: 54,
color: '#CCCCCC'
}, {
x: 'Orange',
y: 66,
color: '#FF0000'
}]
}]);
But the colours here is are not applied to the chart.
I've tried with the 'distributed' option set to true as well.
plotOptions: {
bar: {
distributed: true,
},
},
There are two ways to achieve this, you're very close to both of them.
1. Pass the color with the data
Very similar to what you've tried, but use fillColor as the key instead.
data: [{
x: 'Apple',
y: 54,
fillColor: '#CCCCCC'
}, {
x: 'Orange',
y: 66,
fillColor: '#FF0000'
}]
2. distributed option
For this to work, it needs to be nested inside the options object:
options: {
plotOptions: {
bar: {
distributed: true
}
}
},
If this doesn't work, it's worth making sure that there aren't any invalid attributes (e.g. color) somewhere that might be causing issues.
As I'm sure you've already discovered, there are some examples of various ways to use colors in a column chart in the ApexCharts docs.

Nivo not showing any tooltip

I'm trying to mimic the tooltip shown in nivo homepage line graph. My code so far:
<ResponsiveLine
data={data}
margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
xScale={{
format: '%Y-%m-%d',
type: 'time',
precision: 'day',
}}
yScale={{
type: 'linear',
max: 500,
min: 100,
}}
areaBaselineValue={100}
xFormat="time:%Y-%m-%d"
enablePoints={false}
enableGridX={false}
gridYValues={[100, 300, 500]}
useMesh
isInteractive
enableCrosshair
crosshairType="x"
colors={['#4F82CE', '#7BE0B1', '#990620']}
enableArea
enableSlices="x"
axisBottom={{
tickValues: [
new Date(2022, 0, 1),
new Date(2022, 4, 1),
],
format: '%b %d',
}}
axisLeft={null}
axisRight={{
tickValues: [100, 300, 500],
}}
/>
My output
There doesn't seem to be any tooltip showing, but other than providing my own custom tooltip, I wasn't able to find any way of showing it there.

ApexCharts bubble - Change quarter background color

I am using ng-apexcharts, and I want to change only quarter of the background to another color like in the following example:
enter image description here
Currently using annotations with offestY, but we cant understand what is the offestY value and how we can make it 50% of the graph size.
Code example:
chart: {
type: 'bubble',
height: auto,
...
},
annotations: {
xaxis: [
{
x: 50,
x2: 100,
fillColor: '#f15252',
opacity: 0.1,
offsetY: -70, // How to calculate this value to be exactly 50% offest?
}
],
},
thanks!
I found a solution, maybe it will help someone:
events: {
mounted: (chart, options) => {
const offsetX = options.globals.gridWidth / 2;
this.chart.addYaxisAnnotation({
y: 5,
y2: 10,
fillColor: '#f15252',
opacity: 0.1,
offsetX,
});
},
}

google visualization bar chart stacking two bars

I have a google visualization bar chart sample here where the data format is as given below.
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses', 'Profit'],
['2014', 1000, 400, 200],
['2015', 1170, 460, 250],
['2016', 660, 1120, 300],
['2017', 1030, 540, 350]
]);
How to make expenses and profits bar stacked where as sales is a separate bar?
At the moment the Google Charts API doesn't have this in built feature, but with some remodeling of the DataTable and Chart Options you can still achieve this.
My Solution
The Stacked Bar should contain values of only Expenses and Profit, to avoid a Stacked bar with Sales the value in the data column for Sales is represented as zero. A separate Sales bar is created by having a similar data row, but with the value of Sales present, and the rest zero. The Date data type needs to be specified in order to group all bar charts with the same date, if this isn't implemented, then there will be a gap between each bar chart with the same year.
More information on Date representation of Columns is available here.
var data = google.visualization.arrayToDataTable([
[ {label: 'Year', id: 'year', type: 'date'},
{label: 'Sales', id: 'Sales', type: 'number'},
{label: 'Expenses', id: 'Expenses', type: 'number'},
{label: 'Profit', id: 'Profit', type: 'number'}],
[{v:new Date('2014'), f:'2014'}, 0, 400, 200],
[{v:new Date('2014'), f:'2014'}, 1000, 0, 0],
[{v:new Date('2015'), f:'2015'}, 0, 460, 250],
[{v:new Date('2015'), f:'2015'}, 1170, 0, 0],
[{v:new Date('2016'), f:'2016'}, 0, 1120, 300],
[{v:new Date('2016'), f:'2016'}, 600, 0, 0],
[{v:new Date('2017'), f:'2017'}, 0, 540, 350],
[{v:new Date('2017'), f:'2017'}, 1030, 0, 0]
]);
To achieve the stacked bar, the google charts configuration option isStacked: true is used. To avoid the vertical axis acting like a timeline with months and days, the vertical axis is formatted to display the Year using vAxis: {format: 'yyyy'}. More information on formatting is available here. To avoid spacing between different Year Bars, the feature bar: {groupWidth: '90%'} is used.
var options = {
chart: {
title: 'Company Performance',
subtitle: 'Sales, Expenses, and Profit: 2014-2017',
},
bars: 'horizontal', // Required for Material Bar Charts.
hAxis: {format: 'decimal'},
vAxis: {
format: 'yyyy'
},
height: 400,
colors: ['#1b9e77', '#d95f02', '#7570b3'],
isStacked: true,
bar: {groupWidth: '90%'}
};

How to change color of annotation text in google-charts

How do you change the color of an annotation text in Google Chart Tools LineChart ?
Here is an example
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Sales');
data.addColumn({id: 'title', label: 'Title', type: 'string', role: 'annotation'});
data.addRows([
[new Date(2012, 3, 5), 80, null],
[new Date(2012, 3, 12), 120, 'New Product'],
[new Date(2012, 3, 19), 80, null],
[new Date(2012, 3, 26), 65, null],
[new Date(2012, 4, 2), 70, null],
]);
var options = {
title: 'Sales by Week',
displayAnnotations: true,
hAxis: {title: 'Date',
titleTextStyle: {color: 'grey'}},
colors: ['#f07f09']
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
I want the line to be orange and the annotation text in grey. Currently the annotation text is orange.
No need for extra style data column and plumbing code to fill it for every row with ugly (and even incomplete above) formatting string. Only resort to separate styling column if you want to have different annotation color for the different data points.
There's a global setting, search for annotations.textStyle in https://developers.google.com/chart/interactive/docs/gallery/linechart
var options = {
annotations: {
textStyle: {
fontName: 'Times-Roman',
fontSize: 18,
bold: true,
italic: true,
// The color of the text.
color: '#871b47',
// The color of the text outline.
auraColor: '#d799ae',
// The transparency of the text.
opacity: 0.8
}
}
};
Here is a concept code for your case (notice different initialization google.charts, very important):
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
google.charts.load('current', { 'packages': ['corechart', 'line', 'bar'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Sales');
data.addColumn({id: 'title', label: 'Title', type: 'string', role: 'annotation'});
data.addRows([
[new Date(2012, 3, 5), 80, null],
[new Date(2012, 3, 12), 120, 'New Product'],
[new Date(2012, 3, 19), 80, null],
[new Date(2012, 3, 26), 65, null],
[new Date(2012, 4, 2), 70, null],
]);
var options = {
chart: {
title: 'Sales by Week'
},
hAxis: {
title: 'Date',
titleTextStyle: {color: 'grey'}
},
annotations: {
textStyle: {
color: 'grey',
}
}
colors: ['#f07f09']
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
You can also change other text formatting of the annotation, like bold, italic, font type, etc. Here is an example where most of the text is configured to be bold:
var options = {
chart: {
title: title
},
hAxis: {
textStyle: {
bold: true
}
},
vAxis: {
format: 'decimal',
textStyle: {
bold: true
}
},
legendTextStyle: {
bold: true
},
titleTextStyle: {
bold: true
},
width: chart_width,
//theme: 'material', // material theme decreases the color contrast and sets the black color items (all text) to 171,171,171 grey -> washed out
annotations: {
alwaysOutside: true,
highContrast: true, // default is true, but be sure
textStyle: {
bold: true
}
}
};
More examples with source repo link: https://mrcsabatoth.github.io/GoogleChartsTalk/
Actually you can. Color of the annotations is the same as line color. Just put a dot in the place you want to make an annotation and set a dot's color to the desirable annotation color.
data.addColumn({type: 'string', role: 'style'});
data.addColumn({type:'string', role:'annotation'});
and then when you add data
'point { size: 14; shape-type: circle; fill-color: #63A74A','Your annotation'
See example at
http://www.marketvolume.com/stocks/stochasticsmomentumindex.asp?s=SPY&t=spdr-s-p-500
If your annotations are not "touching", ie. the points you'd like to annotate are not next to each other, you could add a second line and add the annotations to that line.
In the JSON example below I have a date and a "total balance", as well as an "Ann" line.
"cols":[
{
"id":"date",
"label":"date",
"type":"date",
"p":{
"role":"domain"
}
},
{
"id":"total-balance",
"label":"Total balance",
"type":"number",
"p":{
"role":"data"
}
},
{
"id":"ann",
"label":"Ann",
"type":"number",
"p":{
"role":"data"
}
},
{
"type":"string",
"p":{
"role":"annotation"
}
},
{
"type":"string",
"p":{
"role":"annotationText"
}
}
],
The annotation comes after the "Ann" column so it'll be added to the "Ann" data points.
In my JSON, the date and "total-balance" are always filled in. "Ann" and the annotations are usually empty:
"rows":[
{
"c":[
{
"v":"Date(2013, 0, 1)"
},
{
"v":1000
},
{
"v":null
},
{
"v":null
},
{
"v":null
}
]
},
{
"c":[
{
"v":"Date(2013, 0, 8)"
},
{
"v":1001
},
{
"v":null
},
{
"v":null
},
{
"v":null
}
]
},
When I need an annotation, the "Ann" cell gets the same value as the total balance, and the annotation is added:
{
"c":[
{
"v":"Date(2013, 1, 26)"
},
{
"v":2000
},
{
"v":2000
},
{
"v":"Something!"
},
{
"v":"Something happened here!"
}
]
},
In your GChart's configuration, you can now set two colours. One for the normal line, and one for the "Ann".
colors: ['black','red']
If you have no annotations "touching", GCharts will not draw a line between them and the points will remain "invisible", while the annotations show up at exactly the right place.
Short answer: no, you can't change the text color through standard options (you could write something to find that text in the SVG and change its color with javascript, but that is beyond my level).
You can see an answer from ASGallant on Google Groups here, and his example here.
// code borrowed from Google visualization API playground, slightly modified here
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawVisualization);
function drawVisualization() {
// Create and populate the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'x');
data.addColumn({type: 'string', role: 'annotation'});
data.addColumn({type: 'string', role: 'annotationText'});
data.addColumn('number', 'Cats');
data.addColumn('number', 'Blanket 1');
data.addColumn('number', 'Blanket 2');
data.addRow(["A", null, null, 1, 1, 0.5]);
data.addRow(["B", null, null, 2, 0.5, 1]);
data.addRow(["C", null, null, 4, 1, 0.5]);
data.addRow(["D", null, null, 8, 0.5, 1]);
data.addRow(["E", 'foo', 'foo text', 7, 1, 0.5]);
data.addRow(["F", null, null, 7, 0.5, 1]);
data.addRow(["G", null, null, 8, 1, 0.5]);
data.addRow(["H", null, null, 4, 0.5, 1]);
data.addRow(["I", null, null, 2, 1, 0.5]);
data.addRow(["J", null, null, 3.5, 0.5, 1]);
data.addRow(["K", null, null, 3, 1, 0.5]);
data.addRow(["L", null, null, 3.5, 0.5, 1]);
data.addRow(["M", null, null, 1, 1, 0.5]);
data.addRow(["N", null, null, 1, 0.5, 1]);
// Create and draw the visualization.
var chart = new google.visualization.LineChart(document.getElementById('visualization'));
chart.draw(data, {
annotation: {
1: {
style: 'line'
}
},
curveType: "function",
width: 500,
height: 400,
vAxis: {
maxValue: 10
}
});
}
The best you can do is to change the style of the line, but it doesn't look like you can currently change the color of the line.
Has this been updated using the 'style' option where one could add a new column {"type":"string","role":"style"} and in each row we would have {"v":"point {size: 4; fill-color: #3366cc;}"}? This allows the annotation to have the same color as the point/marker (which could be changed for each point) but does not allow it to be bold. One example of the data to try would be,
var data =new google.visualization.DataTable(
{
"cols":[
{"label":"Log GDP Per-Capita ","type":"number"},
{"label":"New Chart",
"type":"number"},
{"type":"string","role":"annotation"},
{"type":"string","role":"style"}
],
"rows":[
{"c":[{"v":10.21932},{"v":12.3199676},{"v":"ABW"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":10.68416},{"v":8.4347518},{"v":"ARE"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":9.634226},{"v":12.0774068},{"v":"ATG"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":10.83869},{"v":1.8545959},{"v":"AUS"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":10.7687},{"v":7.4919999},{"v":"AUT"},{"v":"point {size: 4; fill-color: #3366cc;}"}]}
]
}
);