11import 'package:flutter/material.dart' ;
22import 'package:syncfusion_flutter_charts/charts.dart' ;
3-
3+ import 'package:intl/intl.dart' ;
44void main () {
55 runApp (const MyApp ());
66}
@@ -10,26 +10,21 @@ class MyApp extends StatelessWidget {
1010
1111 @override
1212 Widget build (BuildContext context) {
13- return MaterialApp (
13+ return const MaterialApp (
1414 debugShowCheckedModeBanner: false ,
15- title: 'Flutter Demo' ,
16- theme: ThemeData (
17- colorScheme: ColorScheme .fromSeed (seedColor: Colors .deepPurple),
18- useMaterial3: true ,
19- ),
20- home: const HeatMapChart (),
15+ home: RiskHeatMapChart (),
2116 );
2217 }
2318}
2419
25- class HeatMapChart extends StatefulWidget {
26- const HeatMapChart ({super .key});
20+ class RiskHeatMapChart extends StatefulWidget {
21+ const RiskHeatMapChart ({super .key});
2722
2823 @override
29- HeatMapChartState createState () => HeatMapChartState ();
24+ RiskHeatMapChartState createState () => RiskHeatMapChartState ();
3025}
3126
32- class HeatMapChartState extends State <HeatMapChart > {
27+ class RiskHeatMapChartState extends State <RiskHeatMapChart > {
3328 List <_SP500ReturnData >? _heatMapData;
3429 TooltipBehavior ? _tooltipBehavior;
3530
@@ -48,13 +43,16 @@ class HeatMapChartState extends State<HeatMapChart> {
4843 String label = '' ;
4944 switch (seriesIndex) {
5045 case 0 :
51- label = 'Year: ${data .year }, 3M: ${data .return3Months }%' ;
46+ label =
47+ 'Year: ${data .year .year }, 3M: ${data .threeMonthsAfterFirstRateCut }%' ;
5248 break ;
5349 case 1 :
54- label = 'Year: ${data .year }, 6M: ${data .return6Months }%' ;
50+ label =
51+ 'Year: ${data .year .year }, 6M: ${data .sixMonthsAfterFirstRateCut }%' ;
5552 break ;
5653 case 2 :
57- label = 'Year: ${data .year }, 1Y: ${data .return1Year }%' ;
54+ label =
55+ 'Year: ${data .year .year }, 1Y: ${data .oneYearAfterFirstRateCut }%' ;
5856 break ;
5957 }
6058 return Container (
@@ -65,13 +63,18 @@ class HeatMapChartState extends State<HeatMapChart> {
6563 },
6664 );
6765 _heatMapData = < _SP500ReturnData > [
68- _SP500ReturnData (1987 , 10 , 0.1 , 1.7 , 7.5 ),
69- _SP500ReturnData (1989 , 10 , 7.4 , 7.5 , 11.9 ),
70- _SP500ReturnData (1995 , 10 , 10 , 5.1 , 13.4 ),
71- _SP500ReturnData (1998 , 10 , 17.2 , 26.5 , 27.3 ),
72- _SP500ReturnData (2001 , 10 , - 16.3 , - 12.4 , - 14.9 ),
73- _SP500ReturnData (2007 , 10 , - 4.4 , - 11.8 , - 27.2 ),
74- _SP500ReturnData (2019 , 10 , 3.8 , 13.3 , 14.5 ),
66+ _SP500ReturnData (DateTime (1973 ), 10 , - 10.2 , - 6.2 , - 36.0 ),
67+ _SP500ReturnData (DateTime (1974 ), 10 , - 14.7 , - 15.3 , 7.5 ),
68+ _SP500ReturnData (DateTime (1980 ), 10 , 15.0 , 28.9 , 30.3 ),
69+ _SP500ReturnData (DateTime (1981 ), 10 , - 11.0 , - 7.9 , - 17.8 ),
70+ _SP500ReturnData (DateTime (1982 ), 10 , - 4.8 , 17.4 , 36.5 ),
71+ _SP500ReturnData (DateTime (1987 ), 10 , 0.1 , 1.7 , 7.5 ),
72+ _SP500ReturnData (DateTime (1989 ), 10 , 7.4 , 7.5 , 11.9 ),
73+ _SP500ReturnData (DateTime (1995 ), 10 , 10 , 5.1 , 13.4 ),
74+ _SP500ReturnData (DateTime (1998 ), 10 , 17.2 , 26.5 , 27.3 ),
75+ _SP500ReturnData (DateTime (2001 ), 10 , - 16.3 , - 12.4 , - 14.9 ),
76+ _SP500ReturnData (DateTime (2007 ), 10 , - 4.4 , - 11.8 , - 27.2 ),
77+ _SP500ReturnData (DateTime (2019 ), 10 , 3.8 , 13.3 , 14.5 ),
7578 ];
7679 super .initState ();
7780 }
@@ -86,8 +89,6 @@ class HeatMapChartState extends State<HeatMapChart> {
8689 return Colors .green.shade500; // Medium green
8790 case var val when val >= 5.0 :
8891 return Colors .green.shade300; // Light green
89- case var val when val >= 2.5 :
90- return Colors .orange.shade200; // Lightest orange
9192 case var val when val > 0.0 :
9293 return Colors .orange.shade400; // Lighter orange
9394 case var val when val >= - 2.5 :
@@ -118,158 +119,158 @@ class HeatMapChartState extends State<HeatMapChart> {
118119 title: const ChartTitle (
119120 text: 'S&P 500 Returns After Rate Cuts' ,
120121 textStyle: TextStyle (
121- fontWeight: FontWeight .bold,
122- fontSize: 24 ,
123- color: Colors .white,
124- ),
122+ fontWeight: FontWeight .bold,
123+ fontSize: 24 ,
124+ color: Colors .white,
125+ fontFamily : "Roboto" ),
125126 ),
126- primaryXAxis: const CategoryAxis (
127- labelStyle: TextStyle (
127+ primaryXAxis: DateTimeCategoryAxis (
128+ dateFormat: DateFormat .y (), // Format to display only the year
129+ intervalType: DateTimeIntervalType .years,
130+ labelStyle: const TextStyle (
128131 fontWeight: FontWeight .bold,
129132 fontSize: 14.0 ,
130133 color: Colors .white,
131134 ),
132- majorTickLines: MajorTickLines (size: 0 ),
133- axisLine: AxisLine (width: 0 ),
135+ majorTickLines: const MajorTickLines (size: 0 ),
136+ axisLine: const AxisLine (width: 0 ),
134137 isInversed: true ,
135- title: AxisTitle (
138+ title: const AxisTitle (
136139 text: 'Year of First Rate Cut' ,
137140 textStyle: TextStyle (
138141 color: Colors .white,
139142 fontWeight: FontWeight .bold,
140143 fontSize: 18.0 ,
141144 ),
142145 ),
143- majorGridLines: MajorGridLines (width: 0 ),
146+ majorGridLines: const MajorGridLines (width: 0 ),
144147 ),
145148 primaryYAxis: NumericAxis (
146- opposedPosition: true ,
147- axisLine: const AxisLine (width: 0 ),
148- majorGridLines: const MajorGridLines (width: 0 ),
149- edgeLabelPlacement: EdgeLabelPlacement .shift,
150- majorTickLines: const MajorTickLines (size: 0 ),
151- borderWidth: 0 ,
152- labelIntersectAction: AxisLabelIntersectAction .multipleRows,
153- labelStyle: const TextStyle (
154- color: Colors .transparent, // Hide default labels
155- ),
156- multiLevelLabelStyle: const MultiLevelLabelStyle (
157- borderWidth: 0 , borderColor: Colors .transparent),
158- multiLevelLabelFormatter: (MultiLevelLabelRenderDetails details) {
159- return ChartAxisLabel (
160- details.text,
161- const TextStyle (
162- color: Colors .white,
163- decoration: TextDecoration .underline,
164- fontWeight: FontWeight .bold,
165- fontSize: 14.0 ,
166- ),
167- );
168- },
169- multiLevelLabels: const < NumericMultiLevelLabel > [
170- NumericMultiLevelLabel (
171- start: 5 , end: 30 , text: '3 months after \n rate cut' ),
172- NumericMultiLevelLabel (
173- start: 40 , end: 60 , text: '6 months after \n rate cut' ),
174- NumericMultiLevelLabel (
175- start: 70 ,
176- end: 95 ,
177- text: '1 year after \n rate cut' ,
149+ opposedPosition: true ,
150+ axisLine: const AxisLine (width: 0 ),
151+ majorGridLines: const MajorGridLines (width: 0 ),
152+ edgeLabelPlacement: EdgeLabelPlacement .shift,
153+ majorTickLines: const MajorTickLines (size: 0 ),
154+ borderWidth: 0 ,
155+ labelIntersectAction: AxisLabelIntersectAction .multipleRows,
156+ labelStyle: const TextStyle (
157+ color: Colors .transparent, // Hide default labels
158+ ),
159+ multiLevelLabelStyle: const MultiLevelLabelStyle (
160+ borderWidth: 0 , borderColor: Colors .transparent),
161+ multiLevelLabelFormatter: (MultiLevelLabelRenderDetails details) {
162+ return ChartAxisLabel (
163+ details.text,
164+ const TextStyle (
165+ color: Colors .white,
166+ decoration: TextDecoration .underline,
167+ fontWeight: FontWeight .bold,
168+ fontSize: 14.0 ,
178169 ),
179- ]),
170+ );
171+ },
172+ multiLevelLabels: const < NumericMultiLevelLabel > [
173+ NumericMultiLevelLabel (
174+ start: 5 , end: 30 , text: '3 months after \n first rate cut' ),
175+ NumericMultiLevelLabel (
176+ start: 40 , end: 60 , text: '6 months after \n first rate cut' ),
177+ NumericMultiLevelLabel (
178+ start: 70 ,
179+ end: 95 ,
180+ text: '1 year after \n first rate cut' ,
181+ ),
182+ ],
183+ ),
180184 series: _getStackedColumnSeries (),
181185 tooltipBehavior: _tooltipBehavior,
182186 );
183187 }
184188
185- List <CartesianSeries <_SP500ReturnData , String >> _getStackedColumnSeries () {
186- return < CartesianSeries <_SP500ReturnData , String >> [
187- StackedColumn100Series <_SP500ReturnData , String >(
189+ List <CartesianSeries <_SP500ReturnData , DateTime >> _getStackedColumnSeries () {
190+ return < CartesianSeries <_SP500ReturnData , DateTime >> [
191+ StackedColumn100Series <_SP500ReturnData , DateTime >(
188192 dataSource: _heatMapData! ,
193+ xValueMapper: (_SP500ReturnData data, int index) => data.year,
194+ yValueMapper: (_SP500ReturnData data, int index) =>
195+ data.returnValueIndicator,
189196 borderWidth: 5.0 ,
190197 borderRadius: const BorderRadius .all (Radius .circular (10 )),
191198 width: 1 ,
192199 borderColor: Colors .blueGrey.shade900,
193200 pointColorMapper: (_SP500ReturnData data, int index) =>
194- _buildColor (data.return3Months ),
201+ _buildColor (data.threeMonthsAfterFirstRateCut ),
195202 dataLabelSettings: DataLabelSettings (
196203 isVisible: true ,
197204 builder: (dynamic data, dynamic point, dynamic series, int pointIndex,
198205 int seriesIndex) {
199206 return Text (
200- '${data .return3Months .toString ()}%' ,
207+ '${data .threeMonthsAfterFirstRateCut .toString ()}%' ,
201208 style: const TextStyle (
202- fontWeight: FontWeight .bold,
203- fontSize: 16.0 ,
204- color: Colors .white,
205- ),
209+ fontWeight: FontWeight .bold,
210+ fontSize: 16.0 ,
211+ color: Colors .white,
212+ fontFamily : 'Roboto' ),
206213 );
207214 },
208215 labelAlignment: ChartDataLabelAlignment .middle,
209216 ),
210- xValueMapper: (_SP500ReturnData sales, int index) =>
211- sales.year.toString (),
212- yValueMapper: (_SP500ReturnData sales, int index) =>
213- sales.returnValueIndicator,
214- name: '3 Months After' ,
217+ name: '3 Months After First Rate Cut' ,
215218 ),
216- StackedColumn100Series <_SP500ReturnData , String >(
219+ StackedColumn100Series <_SP500ReturnData , DateTime >(
217220 dataSource: _heatMapData! ,
221+ xValueMapper: (_SP500ReturnData data, int index) => data.year,
222+ yValueMapper: (_SP500ReturnData data, int index) =>
223+ data.returnValueIndicator,
218224 borderWidth: 5.0 ,
219225 borderRadius: const BorderRadius .all (Radius .circular (10 )),
220226 width: 1 ,
221227 borderColor: Colors .blueGrey.shade900,
222228 pointColorMapper: (_SP500ReturnData data, int index) =>
223- _buildColor (data.return6Months ),
229+ _buildColor (data.sixMonthsAfterFirstRateCut ),
224230 dataLabelSettings: DataLabelSettings (
225231 isVisible: true ,
226232 builder: (dynamic data, dynamic point, dynamic series, int pointIndex,
227233 int seriesIndex) {
228234 return Text (
229- '${data .return6Months .toString ()}%' ,
235+ '${data .sixMonthsAfterFirstRateCut .toString ()}%' ,
230236 style: const TextStyle (
231- fontWeight: FontWeight .bold,
232- fontSize: 16.0 ,
233- color: Colors .white,
234- ),
237+ fontWeight: FontWeight .bold,
238+ fontSize: 16.0 ,
239+ color: Colors .white,
240+ fontFamily : 'Roboto' ),
235241 );
236242 },
237243 labelAlignment: ChartDataLabelAlignment .middle,
238244 ),
239- xValueMapper: (_SP500ReturnData sales, int index) =>
240- sales.year.toString (),
241- yValueMapper: (_SP500ReturnData sales, int index) =>
242- sales.returnValueIndicator,
243- name: '6 Months After' ,
245+ name: '6 Months After First Rate Cut' ,
244246 ),
245- StackedColumn100Series <_SP500ReturnData , String >(
247+ StackedColumn100Series <_SP500ReturnData , DateTime >(
246248 dataSource: _heatMapData! ,
249+ xValueMapper: (_SP500ReturnData data, int index) => data.year,
250+ yValueMapper: (_SP500ReturnData data, int index) =>
251+ data.returnValueIndicator,
247252 borderWidth: 5.0 ,
248253 borderRadius: const BorderRadius .all (Radius .circular (10 )),
249254 width: 1 ,
250255 borderColor: Colors .blueGrey.shade900,
251256 pointColorMapper: (_SP500ReturnData data, int index) =>
252- _buildColor (data.return1Year ),
257+ _buildColor (data.oneYearAfterFirstRateCut ),
253258 dataLabelSettings: DataLabelSettings (
254259 isVisible: true ,
255260 builder: (dynamic data, dynamic point, dynamic series, int pointIndex,
256261 int seriesIndex) {
257262 return Text (
258- '${data .return1Year .toString ()}%' ,
263+ '${data .oneYearAfterFirstRateCut .toString ()}%' ,
259264 style: const TextStyle (
260- fontWeight: FontWeight .bold,
261- fontSize: 16.0 ,
262- color: Colors .white,
263- ),
265+ fontWeight: FontWeight .bold,
266+ fontSize: 16.0 ,
267+ color: Colors .white,
268+ fontFamily : 'Roboto' ),
264269 );
265270 },
266271 labelAlignment: ChartDataLabelAlignment .middle,
267272 ),
268- xValueMapper: (_SP500ReturnData sales, int index) =>
269- sales.year.toString (),
270- yValueMapper: (_SP500ReturnData sales, int index) =>
271- sales.returnValueIndicator,
272- name: '1 Year After' ,
273+ name: '1 Year After First Rate Cut' ,
273274 ),
274275 ];
275276 }
@@ -285,14 +286,14 @@ class _SP500ReturnData {
285286 _SP500ReturnData (
286287 this .year,
287288 this .returnValueIndicator,
288- this .return3Months ,
289- this .return6Months ,
290- this .return1Year ,
289+ this .threeMonthsAfterFirstRateCut ,
290+ this .sixMonthsAfterFirstRateCut ,
291+ this .oneYearAfterFirstRateCut ,
291292 );
292293
293- final int year;
294+ final DateTime year;
294295 final num returnValueIndicator;
295- final num return3Months ;
296- final num return6Months ;
297- final num return1Year ;
296+ final num threeMonthsAfterFirstRateCut ;
297+ final num sixMonthsAfterFirstRateCut ;
298+ final num oneYearAfterFirstRateCut ;
298299}
0 commit comments