stock_market_data 0.1.4 copy "stock_market_data: ^0.1.4" to clipboard
stock_market_data: ^0.1.4 copied to clipboard

Package to get base indicators from the stock and base stats like buy and hold CAGR and total drawdown

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:stock_market_data/stock_market_data.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode _themeMode = ThemeMode.light;

  void _toggleTheme() {
    setState(() {
      _themeMode = _themeMode == ThemeMode.light
          ? ThemeMode.dark
          : ThemeMode.light;
    });
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'Flutter Demo',
    themeMode: _themeMode,
    debugShowCheckedModeBanner: false,
    theme: ThemeData.light(),
    darkTheme: ThemeData.dark(),
    home: HomeScreen(onToggleTheme: _toggleTheme),
  );
}

class HomeScreen extends StatelessWidget {
  final VoidCallback onToggleTheme;

  const HomeScreen({required this.onToggleTheme, super.key});

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(
      title: const Text('Stock Market Example'),
      actions: [
        IconButton(
          icon: const Icon(Icons.brightness_6),
          onPressed: onToggleTheme,
        ),
      ],
    ),
    body: Container(
      padding: const EdgeInsets.all(20),
      child: const SingleChildScrollView(
        child: Column(
          children: [
            SizedBox(
              height: 355,
              width: double.infinity,
              child: BuyAndHoldResult(exampleTicker: 'AAPL'),
            ),
            SizedBox(
              height: 355,
              width: double.infinity,
              child: BuyAndHoldResult(exampleTicker: 'VUSA.AS'),
            ),
            SizedBox(
              height: 355,
              width: double.infinity,
              child: BuyAndHoldResult(exampleTicker: 'ES=F, GC=F'),
            ),
          ],
        ),
      ),
    ),
  );
}

class BuyAndHoldResult extends StatefulWidget {
  final String exampleTicker;

  const BuyAndHoldResult({required this.exampleTicker, super.key});

  @override
  State<BuyAndHoldResult> createState() => _BuyAndHoldResultState();
}

class _BuyAndHoldResultState extends State<BuyAndHoldResult> {
  final TextEditingController controller = TextEditingController();
  BuyAndHoldStrategyResult backTest = BuyAndHoldStrategyResult();
  bool loading = true;
  String error = '';

  @override
  void initState() {
    super.initState();
    controller.text = widget.exampleTicker;
    load();
  }

  @override
  Widget build(BuildContext context) => Column(
    children: [
      const Text('Ticker from yahoo finance'),
      TextField(controller: controller),
      MaterialButton(
        onPressed: load,
        color: Theme.of(context).primaryColor,
        child: const Text('Load'),
      ),
      Expanded(
        child: error.isNotEmpty
            ? Text('Error: $error')
            : loading
            ? const Center(child: CircularProgressIndicator())
            : ListView(
                padding: const EdgeInsets.all(8),
                children: [
                  const SizedBox(height: 20),
                  _BackTestResult(backTest),
                  const SizedBox(height: 20),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      MaterialButton(
                        onPressed: () => Navigator.of(context).push(
                          MaterialPageRoute(
                            builder: (context) =>
                                _IndicatorsData(controller.text),
                          ),
                        ),
                        color: Colors.teal,
                        child: const Text('Indicators'),
                      ),
                      const SizedBox(width: 20),
                      MaterialButton(
                        onPressed: () => Navigator.of(context).push(
                          MaterialPageRoute(
                            builder: (context) =>
                                _YearStatsWidget(controller.text),
                          ),
                        ),
                        color: Colors.orange,
                        child: const Text('Year stats'),
                      ),
                    ],
                  ),
                ],
              ),
      ),
    ],
  );

  Future<void> load() async {
    try {
      setState(() {
        error = '';
        loading = true;
      });

      backTest = await StockMarketDataService().getBackTestResultForSymbol(
        controller.text,
      );

      setState(() => loading = false);
    } catch (e) {
      setState(() {
        error = 'Error getting the symbol ${controller.text}:\n $e';
        loading = false;
      });
    }
  }
}

class _BackTestResult extends StatelessWidget {
  final BuyAndHoldStrategyResult backTest;

  const _BackTestResult(this.backTest);

  @override
  Widget build(BuildContext context) => Column(
    children: [
      _row('CAGR', backTest.cagr.toStringAsFixed(2)),
      _row('Max Drawdown', backTest.maxDrawdown.toStringAsFixed(2)),
      _row('MAR', backTest.mar.toStringAsFixed(2)),
      _row('Trading years', backTest.tradingYears.toStringAsFixed(2)),
      _row('Start date', backTest.startDate.toString()),
      _row('End date', backTest.endDate.toString()),
      _row('Current drawdown', backTest.currentDrawdown.toStringAsFixed(2)),
      _row('End price', backTest.endPrice.toStringAsFixed(2)),
    ],
  );

  Widget _row(String label, String value) => Row(
    children: [
      Expanded(child: Text(label)),
      Expanded(child: Text(value)),
    ],
  );
}

class _YearStatsWidget extends StatefulWidget {
  final String symbol;

  const _YearStatsWidget(this.symbol);

  @override
  State<_YearStatsWidget> createState() => _YearStatsWidgetState();
}

class _YearStatsWidgetState extends State<_YearStatsWidget> {
  List<YahooFinanceCandleData> prices = [];
  List<YearlyStats> yearlyStats = [];

  @override
  void initState() {
    super.initState();
    load();
  }

  Future<void> load() async {
    final YahooFinanceResponse response = await const YahooFinanceDailyReader()
        .getDailyDTOs(widget.symbol);

    prices = response.candlesData;
    yearlyStats = YearlyCalculations.calculate(prices);

    setState(() {});
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('Year stats')),
    body: Column(
      children: [
        const Row(
          children: [
            Expanded(child: Text('Year')),
            Expanded(child: Text('Variation')),
            Expanded(child: Text('Drawdown')),
          ],
        ),
        const SizedBox(height: 10),
        Expanded(
          child: ListView.builder(
            itemCount: yearlyStats.length,
            itemBuilder: (context, index) {
              final y = yearlyStats[index];
              return Row(
                children: [
                  Expanded(child: Text(y.year.toString())),
                  Expanded(child: Text(y.variation.toStringAsFixed(2))),
                  Expanded(child: Text(y.drawdown.toStringAsFixed(2))),
                ],
              );
            },
          ),
        ),
      ],
    ),
  );
}

class _IndicatorsData extends StatefulWidget {
  final String symbol;

  const _IndicatorsData(this.symbol);

  @override
  State<_IndicatorsData> createState() => _IndicatorsDataState();
}

class _IndicatorsDataState extends State<_IndicatorsData> {
  final TextEditingController indicatorsController = TextEditingController(
    text:
        'SMA_20,EMA_20,RSI_20,STDDEV_20,VWMA_20,BB_20,%R_20,MFI_14,BOP_14,P_1',
  );

  List<YahooFinanceCandleData> prices = [];

  Future<void> load() async {
    prices = await StockMarketDataService().getCandlesWithIndicators(
      widget.symbol,
      indicatorsController.text.split(','),
    );

    prices = prices.reversed.toList();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: AppBar(title: const Text('Indicators')),
    body: ListView.builder(
      itemCount: prices.length + 1,
      itemBuilder: (context, index) {
        if (index == 0) {
          return Container(
            margin: const EdgeInsets.all(10),
            child: Column(
              children: [
                const Text('Indicators'),
                TextField(controller: indicatorsController, maxLines: 3),
                MaterialButton(
                  onPressed: load,
                  color: Theme.of(context).primaryColor,
                  child: const Text('Load'),
                ),
              ],
            ),
          );
        }

        final candle = prices[index - 1];
        return _PriceWithIndicators(candle);
      },
    ),
  );
}

class _PriceWithIndicators extends StatelessWidget {
  final YahooFinanceCandleData candle;

  const _PriceWithIndicators(this.candle);

  @override
  Widget build(BuildContext context) => Card(
    child: Container(
      margin: const EdgeInsets.all(10),
      child: Column(
        children: [
          Text('Date: ${candle.date}'),
          Text('Close: ${candle.close}'),
          ...candle.indicators.entries.map(
            (entry) => Text('${entry.key}: ${entry.value?.toStringAsFixed(2)}'),
          ),
        ],
      ),
    ),
  );
}
9
likes
160
points
215
downloads

Publisher

verified publisherincaview.com

Weekly Downloads

Package to get base indicators from the stock and base stats like buy and hold CAGR and total drawdown

Homepage
Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

flutter, yahoo_finance_data_reader

More

Packages that depend on stock_market_data