====== Projekt konceptualny ======
===== 1. Sformułowanie zadania projektowego =====
Projekt Giełdowych Analiz Dodawacz (GAD) będzie aplikacją umożliwiającą gromadzenie rekomendacji danych giełdowych oraz ich wymianę pomiędzy użytkownikami serwisu. Program będzie udostępniany klientom poprzez interfejs www.
Produkt zainteresować może w szczególności osoby mające więcej wspólnego z analizą danych giełdowych, np. czynnych graczy. Dodatkowo, będzie on przydatnym narzędziem dla tych, którzy zaczynają swoją przygodę z tym tematem – pozwoli zapoznać się z mechanizmami rządzącymi giełdą oraz umożliwi sprawdzenie się w roli potencjalnego inwestora.
Użytkownicy aplikacji korzystać będą z fikcyjnej waluty, której środki pozyskiwane będą w konsekwencji udanych (trafnych) przewidywań zachowań rynku giełdowego. W określonych warunkach, zgromadzone środki podlegać będą wymianie na prawdziwe pieniądze. Dla doświadczonych inwestorów stać więc może źródłem pozyskiwania realnych funduszy, natomiast dla pozostałych – serwisem pomocnym przy alokowaniu pieniędzy w akcje konkretnych spółek.
===== 2. Analiza stanu wyjściowego =====
Możemy wyróżnić szereg serwisów internetowych udostępniających rekomendacje giełdowe zarówno płatnie jak i darmowo. Serwisy darmowe działają zwykle z opóźnieniem – nawet kilkudniowym – co bardzo często ogranicza możliwości wykorzystania rekomendacji. Serwisy płatne, zwykle opierające się na stałym abonamencie, zwykle udostępniają wytworzone przez siebie rekomendacje wszystkim abonentom w tym samym momencie czasu – na stronie lub drogą e-mailową.
Metod prognozowania jest bardzo wiele, niektóre opierają się na różnych wskaźnikach giełdowych i ich porównywaniu, inne na skomplikowanych algorytmach statystycznych, biorących pod uwagę dane krótko lub długookresowe, jednak nie spotkaliśmy się z serwisem działającym na bazie sieci neuronowej.
Warto również wspomnieć o istniejących programach mających wspomagać granie na giełdzie. Tu również można wyróżnić darmowe i płatne wersje, jednak większość z nich oferuje jedynie swego rodzaju segregację danych i różnego typu wykresy statystyczne, które mogą stanowić podstawę do rekomendacji.
Wszystkie rozwiązania skierowane są pod graczy giełdowych o różnym stopniu zaawansowania.
Nasze rozwiązanie jest innowacyjne na skalę kraju. Główną zaletą będzie możliwość interaktywnego tworzenia i dobierania danych do sieci neuronowej, co nie zostało wprowadzone na rynek przez nikogo. Kolejnym atutem jest łączenie w sobie możliwości serwisu płatnego jak i darmowego, pozwalającego tworzyć i udostępniać rekomendacje, jak również sieci neuronowe wykorzystywane do analizy danych, a nawet uzyskanie na tym pewnego dochodu – użytkownik, którego rekomendacje są dobre i często wykorzystywane będzie w stanie na tym zarobić.
===== 3. Analiza wymagań użytkownika (wstępna) =====
W projekcie wyróżnia się dwa rozdaje użytkowników: Zalogowany Użytkownik (zwany dalej Użytkownikiem) oraz Gość.
=== Wymagania Użytkownika ===
- Konieczne (Must):
* Przeglądania historycznych danych o kursach akcji
* Dodanie własnych rekomendacji, nie wynikających z wyników sieci neuronowej, a z jego własnej wiedzy i doświadczenia
* Wygenerowania sieci neuronowej, uczącej się na podstawie podzbioru historycznych danych giełdowych, według zdefiniowanych przez użytkownika parametrów
* Zdefiniowania poziomu dostępności do rekomendacji swojej sieci. (minimalnie: dostępne dla wszystkich, dostępne dla zalogowanych, prywatne)
* Przeglądanie wyników własnej sieci, wyników sieci ogólnodostępnych oraz globalnych statystyk (minimalnie: najczęściej rekomendowane, najlepsze rekomendacje ostatniego dnia, najlepsze rekomendacje ostatniego tygodnia)
- Powinny się pojawić (Should):
* Użytkownik będzie posiadał „konto” z wirtualnymi pieniędzmi za które będzie mógł kupować dostęp do niektórych części serwisu
* Ustawienie poziomu dostępu do rekomendacji na „za opłatą” oraz ustalenie wysokości opłaty
- Opcjonalne (Could):
* Przeglądanie analizy technicznej
* Możliwość wykorzystania wyników analizy technicznej jako wejście sieci neuronowej
* Otrzymywanie powiadomień mailowych o nowych rekomendacjach własnej sieci
* Możliwość „zapisania się” na otrzymywanie powiadomień mailowych o rekomendacjach konkretnych użytkowników
=== Wymagania Gościa ===
* Zarejestrowanie się oraz późniejsze zalogowanie przy użyciu loginu oraz hasła – Gość staje się Użytkownikiem
* Przeglądania historycznych danych o kursach akcji
* Przeglądanie wyników wyników sieci ogólnodostępnych oraz globalnych statystyk (minimalnie: najczęściej rekomendowane, najlepsze rekomendacje ostatniego dnia, najlepsze rekomendacje ostatniego tygodnia)
===== 4. Określenie scenariuszy użycia =====
=== Rejestracja ===
- Użytkownik wprowadza pożądany login, posiadany adres e-mail oraz hasło (opcjonalnie imię i nazwisko, dane adresowe itp. - do przemyślenia + może system weryfikacji z obrazka)
- Jeśli w bazie użytkowników nie ma użytkownika o takim samym loginie, bądź adresie e-mail tworzone jest nowe konto użytkownika, w przeciwnym wypadku użytkownik informowany jest o konflikcie
- (Weryfikacja adresu e-mail?)
=== Logowanie ===
- Użytkownik wprowadza login i hasło
- Jeśli dane odpowiadają danym w bazie to ładowana jest strona startowa użytkownika, zawierającą przeznaczone dla niego rekomendacje, w przeciwnym wypadku użytkownik jest informowany o błędzie
=== Odzyskiwanie hasła ===
- Użytkownik wprowadza adres e-mail powiązany z jego kontem
- Jeśli w bazie danych jest przechowywana informacja o użytkowniku z takim adresem mailowym, na adres ten wysłany zostaje e-mail m.in. z loginem oraz linkiem, pod którym możliwe będzie wprowadzenie nowego hasła
- Użytkownik dwukrotnie wprowadza nowe hasło; po wysłaniu zwalidowanego formularza hasło użytkownika zostaje zmienione na to nowo wprowadzone
=== Tworzenie sieci neuronowej ===
- Użytkownik ze swojej strony głównej wybiera odnośnik "Dodaj nową sieć"
- Pojawia się formularz pozwalający na wybranie parametrów sieci, takich jak:
* Typ sieci
* Ilość warstw/neuronów
* Algorytmu uczenia sieci
- Następny formularz pozwala na ustawienie danych wejściowych, takich jak:
* Wybór indeksu (WIG, WIG20, MIDWIG, itp.)
* Wybór akcji
* Wybór typu danych branych pod uwagę (kurs otwarcia/zamknięcia, wolumin, kurs średni)
* Dane analizy technicznej
- Formularz finalizacyjny pozwalający na:
* Nadanie sieci nazwy
* Ustawienie dostępności sieci (publiczna/prywatna)
* Ustawienia dotyczące powiadomień
=== Dodawanie rekomendacji ===
- Użytkownik ze swojej strony głównej wybiera odnośnik "Dodaj nową rekomendację"
- Użytkownik wypełnia odpowiednie pola formularza:
* Nazwę rekomendacji
* Spółkę
* Przewidywany kurs
* Dzień na który aktualna będzie rekomendacja
* Opcjonalne: Pole z opisem na czym bazuje swoje wnioski
=== Przegląd danych historycznych ===
- Użytkownik ze swojej strony głównej wybiera odnośnik "Kursy"
=== Przegląd statystyk ===
- Użytkownik ze swojej strony głównej wybiera odnośnik "Statystyki"
- Pojawia się strona z różnego rodzaju statystykami:
* Najlepsze rekomendacje tygodnia/miesiąca/roku
* Najlepiej rekomendujący użytkownicy tygodnia/miesiąca/roku
* Najlepiej przewidujące sieci tygodnia/miesiąca/roku (Może być trudne w ocenie?)
=== Przegląd rekomendacji własnych oraz obserwowanych ===
- Lista będzie dostępna na stronie głównej użytkownika, wraz ze źródłami pochodzenia
=== Przegląd rekomendacji cudzych ===
- Użytkownik ze swojej strony głównej wybiera odnośnik "Dostępne rekomendacje"
- Pojawia się lista dostępnych rekomendacji wraz z odnośnikami do dodawania do obserwowanych oraz rekomendującego. Dodatkowo dostępne są różne opcje filtrowania (kiedy dodana, czego dotyczy (indeksy/spółki))
===== 5. Identyfikacja funkcji =====
=== Rejestracja ===
Funkcja rejestrująca użytkownika w systemie; wymaga podania loginu, hasła oraz adresu e-mail, na który (w przypadku rejestracji zakończonej sukcesem) przesłany zostanie mail z linkiem aktywacyjnym.
=== Logowanie ===
Funkcja autoryzacyjna, pozwalająca na logowanie z wykorzystaniem loginu oraz hasła, przekazanych w procesie rejestracji; funkcja sprawdza poprawność wprowadzonej pary login-hasło z danymi znajdującymi się w bazie. Hasło sprawdzane jest w formie zaszyfrowanej.
=== Wylogowanie ===
Funkcja realizująca zakończenie aktualnie trwającej sesji użytkownika; w przypadku poprawnego wylogowania z systemu, użytkownik przekierowywany jest na stronę główną aplikacji.
=== Odzyskiwanie/zmiana hasła ===
W sytuacji, gdy użytkownik nie jest w stanie zalogować się do systemu, może skorzystać z opcji przypomnienia (a właściwie: odzyskiwania) hasła; polega to na przesłaniu na powiązany z kontem adres e-mail linka, pod którym możliwe jest wprowadzenie nowego hasła dla danego użytkownika.
=== Modyfikacja danych użytkownika ===
Funkcja pozwalająca na wprowadzanie zmian w profilu użytkownika zarejestrowanego; edycji podlegają hasło, adres e-mail i informacje dodatkowe; w przypadku zmiany hasła, wymagane jest wprowadzenie hasła aktualnego oraz dwukrotnie nowego; zmiana adresu mailowego wymaga jego aktywacji poprzez e-mail aktywacyjny.
=== Pobranie danych ===
Funkcja umożliwia pobranie z bazy wartości indeksów giełdowych jednej lub więcej spółek dla zadanego przedziału czasowego.
=== Pobranie rekomendacji ===
Funkcja umożliwia wyciągnięcie z bazy informacji o rekomendacjach użytkownika zalogowanego (o ile istnieje) oraz rekomendacji osób, których ustawienia prywatności na to pozwalają (rekomendacje publiczne/dla zalogowanych).
=== Dodanie rekomendacji zwykłej ===
Funkcja umożliwiająca wprowadzenie do bazy rekomendacji; wymaga podania wartości indeksu, identyfikatora spółki, której rekomendacja dotyczy oraz dnia, na który stan przewidujemy.
=== Dodanie rekomendacji opartej o sieć neuronową ===
Funkcja realizująca dodanie rekomendacji opartej o sieć neuronową, z przekazanym zestawem parametrów dla tej sieci; sieć taka będzie mieć za zadanie, na podstawie analiz danych historycznych określonych spółek dokonywać estymacji wskaźników giełdowych.
=== Edycja poziomu dostępności rekomendacji ===
Funkcja umożliwiająca zmianę dostępności rekomendacji dla innych użytkowników systemu.
Dopuszczalne opcje:
* rekomendacja publiczna (każdy może ją widzieć)
* tylko zalogowanych
* rekomendacja prywatna (dostępna tylko dla użytkownika, który ją utworzył)
=== Funkcja oceniająca ===
Funkcja obliczająca na ile zbieżne są wartości przewidziane do rzeczywistych, występujących w danym dniu.
===== 6. Analiza hierarchii funkcji projektowanej aplikacji (FHD – Functional Hierarchy Diagram) =====
=== Funkcje obsługi kont użytkowników ===
* obsługa nowych użytkowników
* rejestracja nowego użytkownika (minimalnie login, e-mail, hasło)
* funkcja sprawdzająca, czy podany login/e-mail nie istnieje w bazie
* właściwa rejestracja (dodanie konta do bazy)
* powiadomienie mailowe o rejestracji
* funkcja generująca link do aktywacji konta (potwierdzenia adresu e-mail)
* funkcja wysyłająca odpowiedni e-mail
* aktywacja konta
* obsługa użytkowników zarejestrowanych
* funkcja odpowiadająca za logowanie do serwisu
* funkcja odpowiadająca za opcję przypominania hasła
=== Funkcje obsługi rekomendacji ===
* dodanie rekomendacji dla wybranej spółki, przewidywanego kursu oraz dnia, którego prognoza ma dotyczyć
* dodanie rekomendacji w oparciu o sieć neuronową
* ustawienie parametrów sieci
* sprawdzenie, czy rekomendacja dla tej spółki w podanym dniu nie została wcześniej zdefiniowana przez tego samego użytkownika (przeciwdziałanie zwiększeniu szansy na trafną prognozę poprzez wprowadzanie wielu kursów)
* weryfikacja trafności rekomendacji
=== Funkcje obsługi danych historycznych oraz statystyk ===
* wyświetlanie danych historycznych dla konkretnej spółki (spółek) z zadanego przedziału czasowego
* (ocena rekomendacji, oceny trafności?)
===== 7. Diagram przepływu danych (DFD - Data Flow Diagram) =====
{{:pl:dydaktyka:ztb:2011:projekty:gielda:gaddfd.png|}}
===== 8. Wybór encji (obiektów) i ich atrybutów =====
=== Użytkownik ===
* id
* login
* hasło (zakodowane)
* e-mail
* data rejestracji
* data ostatniego logowania
* flaga aktywności
* rola
=== Spółka ===
* id spółki
* nazwa
* indeks (WIG, WIG20, midWIG itp.)
=== Rekomendacja ===
* id rekomendacji
* nazwa rekomendacji
* id spółki
* id (właściciel rekomendacji)
* dzień na który przewidujemy
* przewidywana wartość
* dostępność rekomendacji
* opis/komentarz do rekomendacji
* id sieci neuronowej (jeśli dotyczy)
=== Sieć neuronowa ===
* id sieci neuronowej
* nazwa sieci
* id (właściciela sieci)
* typ sieci
* zestaw parametrów opisujących sieć (warstwy/liczby neuronów/wagi neuronów)
* (czy dane z których uczymy nie będą dotyczyły tylko sieci z rekomendacjami? To pozwoli na wielokrotne wykorzystanie?)
===== 9. Powiązania pomiędzy encjami (ERD - Entity-Relationship Diagram) =====
{{:pl:dydaktyka:ztb:2011:projekty:gielda:gad_erd.png|}}
===== 10. Diagramy przejść między stanami (STD - State Transition Diagram) =====
{{:pl:dydaktyka:ztb:2011:projekty:gielda:gadstd1.png?800}}
====== Projekt logiczny ======
===== 1. Projektowanie tabel, kluczy, kluczy obcych, powiązań między tabelami, indeksów, etc. w oparciu o zdefiniowany diagram ERD =====
=== Zaprojektowane klucze obce i powiązania między tabelami ===
^ Nazwa klucza ^ Tabela nadrzędna ^ Tabela zależna ^ Kolumna nadrzędna ^ Kolumna zależna ^ Typ relacji ^ ON DELETE ^ ON UPDATE ^
| fk_neural_networks_neurons_f_neurons | neurons | neural_networks_neurons | neuron_id | neuron_id_from | 1 : 1, m | NO ACTION | CASCADE |
| fk_neural_networks_neurons_t_neurons | neurons | neural_networks_neurons | neuron_id | neuron_id_to | 1 : 1, m | NO ACTION | CASCADE |
| fk_neurons_neural_networks | neural_networks | neurons | network_id | network_id | 1 : 1, m | NO ACTION | CASCADE |
| fk_recommendations_access_levels | access_levels | recommendations | access_level_id | access_level_id | 1 : 1, m | NO ACTION | CASCADE |
| fk_recommendations_companies | companies | recommendations | company_code | company_code | 1 : 1, m | NO ACTION | CASCADE |
| fk_recommendations_neural_networks | neural_networks | recommendations | network_id | network_id | 1 : 0, 1, m | NO ACTION | CASCADE |
| fk_recommendations_users | users | recommendations | user_id | owner_id | 1 : 1, m | NO ACTION | CASCADE |
| fk_stock_values_companies | companies | stock_values | company_code | company_code | 1 : 1, m | NO ACTION | CASCADE |
| fk_users_roles | roles | users | role_id | role_id | 1 : 1, m | NO ACTION | CASCADE |
=== Nałożone indeksy ===
* recommendations_company_code_Idx - dot. kolumny company_code w tabeli recommendations
* recommendations_owner_id_Idx - dot. kolumny owner_id w tabeli recommendations
* recommendations_prediction_day_Idx - dot. kolumny prediction_day w tabeli recommendations
=== Kompletny kod w języku MySQL tworzący strukturę bazodanową ===
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE IF NOT EXISTS `access_levels` (
`access_level_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`description_short` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`description_long` varchar(200) COLLATE utf8_polish_ci NOT NULL,
PRIMARY KEY (`access_level_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `companies` (
`company_code` varchar(10) COLLATE utf8_polish_ci NOT NULL,
`company_name` varchar(45) COLLATE utf8_polish_ci NOT NULL,
PRIMARY KEY (`company_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
CREATE TABLE IF NOT EXISTS `neural_networks` (
`network_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`inputs_no` int(10) unsigned NOT NULL DEFAULT '0',
`outputs_no` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `neural_networks_neurons` (
`neuron_id_from` int(10) unsigned NOT NULL,
`neuron_id_to` int(10) unsigned NOT NULL,
`weight` double unsigned NOT NULL,
PRIMARY KEY (`neuron_id_from`,`neuron_id_to`),
KEY `fk_neural_networks_neurons_t_neurons` (`neuron_id_to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
CREATE TABLE IF NOT EXISTS `neurons` (
`neuron_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`network_id` int(10) unsigned NOT NULL,
`bias` double NOT NULL,
PRIMARY KEY (`neuron_id`),
KEY `fk_neurons_neural_networks` (`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `recommendations` (
`recommendation_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`owner_id` int(10) unsigned NOT NULL,
`company_code` varchar(10) COLLATE utf8_polish_ci NOT NULL,
`predicted_value` decimal(10,2) unsigned NOT NULL,
`prediction_day` date NOT NULL,
`network_id` int(10) unsigned DEFAULT NULL,
`access_level_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`recommendation_id`),
KEY `recommendations_company_code_Idx` (`company_code`),
KEY `recommendations_owner_id_Idx` (`owner_id`),
KEY `recommendations_prediction_day_Idx` (`prediction_day`),
KEY `fk_recommendations_access_levels` (`access_level_id`),
KEY `fk_recommendations_neural_networks` (`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `stock_values` (
`company_code` varchar(10) COLLATE utf8_polish_ci NOT NULL,
`date` date NOT NULL,
`value` decimal(10,2) NOT NULL,
PRIMARY KEY (`company_code`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`login` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`email` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`password` varchar(32) COLLATE utf8_polish_ci NOT NULL,
`registration_time` datetime NOT NULL,
`last_login_time` datetime NOT NULL,
`is_active` tinyint(3) unsigned NOT NULL DEFAULT '0',
`role_id` int(10) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`user_id`),
KEY `fk_users_user_roles` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `user_roles` (
`role_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`description` varchar(45) COLLATE utf8_polish_ci NOT NULL,
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
INSERT INTO `user_roles` (`role_id`, `description`) VALUES
(1, 'Użytkownik');
ALTER TABLE `neural_networks_neurons`
ADD CONSTRAINT `fk_neural_networks_neurons_t_neurons` FOREIGN KEY (`neuron_id_to`) REFERENCES `neurons` (`neuron_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_neural_networks_neurons_f_neurons` FOREIGN KEY (`neuron_id_from`) REFERENCES `neurons` (`neuron_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `neurons`
ADD CONSTRAINT `fk_neurons_neural_networks` FOREIGN KEY (`network_id`) REFERENCES `neural_networks` (`network_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `recommendations`
ADD CONSTRAINT `fk_recommendations_users` FOREIGN KEY (`owner_id`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_recommendations_access_levels` FOREIGN KEY (`access_level_id`) REFERENCES `access_levels` (`access_level_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_recommendations_companies` FOREIGN KEY (`company_code`) REFERENCES `companies` (`company_code`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_recommendations_neural_networks` FOREIGN KEY (`network_id`) REFERENCES `neural_networks` (`network_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `stock_values`
ADD CONSTRAINT `fk_stock_values_companies` FOREIGN KEY (`company_code`) REFERENCES `companies` (`company_code`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `users`
ADD CONSTRAINT `fk_users_user_roles` FOREIGN KEY (`role_id`) REFERENCES `user_roles` (`role_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
===== 2. Słowniki danych =====
- roles: tabela słownikowa przechowująca identyfikatory poszczególnych ról użytkowników systemu (administrator, zwykły użytkownik itp.)
* role_id (id roli; klucz główny, wartość unikalna) - INT UNSIGNED NOT NULL AUTO_INCREMENT,
* description (określenie roli) - VARCHAR(45) NOT NULL.
- users: tabela przechowująca informacje o użytkownikach systemu
* user_id (id użytkownika; klucz główny, wartość unikalna) - INT UNSIGNED NOT NULL AUTO_INCREMENT,
* login (nazwa użytkownika) - VARCHAR(45) NOT NULL,
* email (adres e-mail) - VARCHAR(45) NOT NULL,
* password (hasło użytkownika, zaszyfrowane algorytmem md5) - VARCHAR(32) NOT NULL,
* registration_time (data rejestracji w systemie) - DATETIME NOT NULL,
* last_login_time (data ostatniego zalogowania) - DATETIME NOT NULL,
* is_active (flaga określająca, czy użytkownik jest aktywny) - TINYINT(1) NOT NULL DEFAULT 0,
* role_id (id roli z tabeli roles) - INT NOT NULL DEFAULT 1.
- recommendations: tabela, w której przechowywane są rekomendacje (przewidywane wartości na konkretne terminy) spółek, wprowadzane przez użytkowników systemu
* recommendation_id (unikalny identyfikator rekomendacji, klucz główny) - INT UNSIGNED NOT NULL AUTO_INCREMENT,
* owner_id (identyfikator autora/właściciela z tabeli users) - INT UNSIGNED NOT NULL,
* company_code (identyfikator firmy z tabeli companies) - VARCHAR(10) NOT NULL,
* predicted_value (przewidywana wartość akcji na konkretną datę) - DECIMAL NOT NULL,
* predicted_day (dzień, którego dotyczy szacowanie wartości) - DATE NOT NULL,
* access_level (poziom dostępu, z tabeli access_levels) - INT NOT NULL,
* network_id (opcjonalny identyfikator sieci neuronowej, która wyznaczyła rekomendację) - INT UNSIGNED NULL DEFAULT NULL.
- companies: tabela z identyfikatorami firm
* company_code (unikalny kod spółki, klucz główny) - VARCHAR(10) NOT NULL,
* company_name (pełna nazwa spółki) - VARCHAR(45) NOT NULL,
* index_id
- stock_values: tabela z faktycznymi wartościami spółek w konkretnych dniach
* company_code (kod spółki, z tabeli companies) - VARCHAR(10) NOT NULL,
* date (data zanotowania wartości wskaźnika) - DATE NOT NULL,
* value (wartość spółki w określonym dniu) - DECIMAL NOT NULL.
- access_levels: tabela słownikowa dla opisów poszczególnych ustawień prywatności
* access_level_id (unikalny identyfiaktor poziomu dostępu, klucz główny) - INT UNSIGNED NOT NULL AUTO_INCREMENT,
* description_short (krótki opis poziomu dostępu) - VARCHAR(45) NOT NULL,
* description_long (pełny opis poziomu dostępu) - VARCHAR(200) NOT NULL.
- neural_networks: tabela określająca podstawowe parametry sieci neuronowych (nazwę, liczbę wejść i wyjść)
* network_id (unikalny identyfikator sieci neuronowej, klucz główny) - INT UNSIGNED NOT NULL AUTO_INCREMENT,
* name (nazwa sieci neuronowej) - VARCHAR(45) NOT NULL,
* inputs (liczba wejść) - INT NOT NULL DEFAULT 0,
* outputs (liczba wyjść) - INT NOT NULL DEFAULT 0.
- neurons: tabela precyzująca parametr 'bias' każdego neuronu
* neuron_id (unikalny identyfikator neuronu, klucz główny) - INT UNSIGNED NOT NULL AUTO_INCREMENT,
* network_id (identyfikator sieci neuronowej z tabeli neural_networks) - INT NOT NULL,
* bias (parametr 'bias' konkretnego neuronu) - DOUBLE NOT NULL.
- neural_networks_neurons: tabela definiująca połączenia między poszczególnymi neuronami w ramach sieci neuronowej
* neuron_id_from (identyfikator neuronu, od którego wychodzi połączenie, element złożonego klucza głównego) - INT UNSIGNED NOT NULL,
* neuron_id_to (identufikator neuronu, do którego wchodzi połączenie, element złożonego klucza głównego) - INT UNSIGNED NOT NULL,
* weight (waga połączenia między neuronami) - DOUBLE NOT NULL.
===== 3. Analiza zależności funkcyjnych i normalizacja tabel (dekompozycja do 3NF, BCNF, 4NF, 5NF) =====
=== Analiza zależności funkcyjnych ===
== Pierwsza postać normalna (1NF) ==
**Wymagania:**
* wartości atrybutów we wszystkich tabelach są atomiczne (niepodzielne),
* każda tabela posiada klucz główny,
* znaczenie danych nie zależy od kolejności rekordów.
**Przedstawiana baza jest 1NF.**
== Druga postać normalna (2NF) ==
**Wymagania:**
* zachodzą warunki na 1NF,
* każda kolumna jest funkcyjnie zależna od __całego__ klucza głównego.
**Przedstawiana baza jest 2NF.**
== Trzecia postać normalna (3NF) ==
**Wymagania:**
* zachodzą warunki na 2NF,
* wszystkie pola, które nie wchodzą w skład klucza głównego są od niego zależne __bezpośrednio__.
**Przedstawiana baza jest 3NF.**
===== 4. Projektowanie operacji na danych - przykładowe zapytania =====
Rejestracja użytkownika
INSERT INTO users
(login, email, password, registration_time)
VALUES
('justin', 'justin@domain.com', '61c81371ae4404d7100202d90bee987e', NOW())
Sprawdzenie, czy nie istnieją użytkownicy o podanym e-mailu/loginie (jeśli zwrócona wartość != 0, istnieją)
SELECT
COUNT(1) FROM users
WHERE
login='justin' OR email='justinmail@domain.com'
Modyfikacja danych użytkownika
UPDATE users SET
(login, email)
VALUES
('harry', 'harry@domain.com')
Dodanie nowej spółki
INSERT INTO companies
(company_code, company_name)
VALUES
('NS', 'Nowa spółka')
Pobranie danych historycznych wybranych spółek
SELECT
company_code, date, value FROM stock_values
WHERE
company_code IN ('XXX', 'YYY', 'ZZZ')
AND
date BETWEEN 2011-03-04 AND 2011-05-21
Dodanie dziennego ratingu dla spółki
INSERT INTO stock_values
(company_code, date, value)
VALUES
('NS', DATE(NOW()), 123)
Pobranie rekomendacji użytkownika zalogowanego oraz tych, które są dla niego widoczne
SELECT
* FROM recommendations
INNER JOIN
access_levels
ON
access_levels.access_level_id=recommendations.access_level_id
WHERE
owner_id={{id_uzytkownika_zalogowanego}}
OR
access_levels.description_short IN ('publiczny', 'dla_zalogowanych')
Dodanie rekomendacji dla wybranej spółki, przewidywanego kursu oraz dnia, którego prognoza ma dotyczyć - wraz z ustaleniem poziomu dostępu
INSERT INTO recommendations
(owner_id, company_code, predicted_value, prediction_day, access_level_id)
VALUES
({{id_uzytkownika_zalogowanego}}, 'NS', 444, '2011-10-10', (
SELECT access_level_id FROM access_levels WHERE description_short='publiczny')
)
Dodanie rekomendacji dla wybranej spółki, z wykorzystaniem parametryzowanej sieci neuronowej
====== Raport końcowy ======
===== 1. Implementacja bazy danych =====
{{:pl:dydaktyka:ztb:2011:projekty:gielda:gad_erd.png|}}
W oparciu o powyższy diagram ERD, utworzono pustą bazę danych na silniku MySQL o strukturze zaprezentowanej na poniższym listingu:
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE IF NOT EXISTS `access_levels` (
`access_level_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`description_short` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`description_long` varchar(200) COLLATE utf8_polish_ci NOT NULL,
PRIMARY KEY (`access_level_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `companies` (
`company_code` varchar(10) COLLATE utf8_polish_ci NOT NULL,
`company_name` varchar(45) COLLATE utf8_polish_ci NOT NULL,
PRIMARY KEY (`company_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
CREATE TABLE IF NOT EXISTS `neural_networks` (
`network_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`inputs_no` int(10) unsigned NOT NULL DEFAULT '0',
`outputs_no` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `neural_networks_neurons` (
`neuron_id_from` int(10) unsigned NOT NULL,
`neuron_id_to` int(10) unsigned NOT NULL,
`weight` double unsigned NOT NULL,
PRIMARY KEY (`neuron_id_from`,`neuron_id_to`),
KEY `fk_neural_networks_neurons_t_neurons` (`neuron_id_to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
CREATE TABLE IF NOT EXISTS `neurons` (
`neuron_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`network_id` int(10) unsigned NOT NULL,
`bias` double NOT NULL,
PRIMARY KEY (`neuron_id`),
KEY `fk_neurons_neural_networks` (`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `recommendations` (
`recommendation_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`owner_id` int(10) unsigned NOT NULL,
`company_code` varchar(10) COLLATE utf8_polish_ci NOT NULL,
`predicted_value` decimal(10,2) unsigned NOT NULL,
`prediction_day` date NOT NULL,
`network_id` int(10) unsigned DEFAULT NULL,
`access_level_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`recommendation_id`),
KEY `recommendations_company_code_Idx` (`company_code`),
KEY `recommendations_owner_id_Idx` (`owner_id`),
KEY `recommendations_prediction_day_Idx` (`prediction_day`),
KEY `fk_recommendations_access_levels` (`access_level_id`),
KEY `fk_recommendations_neural_networks` (`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `stock_values` (
`company_code` varchar(10) COLLATE utf8_polish_ci NOT NULL,
`date` date NOT NULL,
`value` decimal(10,2) NOT NULL,
PRIMARY KEY (`company_code`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`login` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`email` varchar(45) COLLATE utf8_polish_ci NOT NULL,
`password` varchar(32) COLLATE utf8_polish_ci NOT NULL,
`registration_time` datetime NOT NULL,
`last_login_time` datetime NOT NULL,
`is_active` tinyint(3) unsigned NOT NULL DEFAULT '0',
`role_id` int(10) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`user_id`),
KEY `fk_users_user_roles` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `user_roles` (
`role_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`description` varchar(45) COLLATE utf8_polish_ci NOT NULL,
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;
INSERT INTO `user_roles` (`role_id`, `description`) VALUES
(1, 'Użytkownik');
ALTER TABLE `neural_networks_neurons`
ADD CONSTRAINT `fk_neural_networks_neurons_t_neurons` FOREIGN KEY (`neuron_id_to`) REFERENCES `neurons` (`neuron_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_neural_networks_neurons_f_neurons` FOREIGN KEY (`neuron_id_from`) REFERENCES `neurons` (`neuron_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `neurons`
ADD CONSTRAINT `fk_neurons_neural_networks` FOREIGN KEY (`network_id`) REFERENCES `neural_networks` (`network_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `recommendations`
ADD CONSTRAINT `fk_recommendations_users` FOREIGN KEY (`owner_id`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_recommendations_access_levels` FOREIGN KEY (`access_level_id`) REFERENCES `access_levels` (`access_level_id`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_recommendations_companies` FOREIGN KEY (`company_code`) REFERENCES `companies` (`company_code`) ON DELETE NO ACTION ON UPDATE CASCADE,
ADD CONSTRAINT `fk_recommendations_neural_networks` FOREIGN KEY (`network_id`) REFERENCES `neural_networks` (`network_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `stock_values`
ADD CONSTRAINT `fk_stock_values_companies` FOREIGN KEY (`company_code`) REFERENCES `companies` (`company_code`) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `users`
ADD CONSTRAINT `fk_users_user_roles` FOREIGN KEY (`role_id`) REFERENCES `user_roles` (`role_id`) ON DELETE NO ACTION ON UPDATE CASCADE;
===== 2. Zdefiniowanie interfejsów do prezentacji, edycji i obsługi danych =====
{{:pl:dydaktyka:ztb:2011:projekty:gielda:scr1.jpg|}}
Strona startowa
{{:pl:dydaktyka:ztb:2011:projekty:gielda:scr2.jpg|}}
Ekran logowania
{{:pl:dydaktyka:ztb:2011:projekty:gielda:scr3.jpg|}}
Ekran rejestracji nowego użytkownika
{{:pl:dydaktyka:ztb:2011:projekty:gielda:scr4.jpg|}}
Ekran dodawania sieci neuronowej
{{:pl:dydaktyka:ztb:2011:projekty:gielda:scr5.jpg|}}
Ekran wyświetlający rekomendacje
{{:pl:dydaktyka:ztb:2011:projekty:gielda:scr6.jpg|}}
Ekran dodawania nowej rekomendacji
===== 3. Zdefiniowanie dokumentów do przetwarzania i prezentacji danych =====
Aplikacja nie używa dokumentów do prezentacji danych.
Jedynym dokumentem wykorzystywanym jest plik .csv, pobierany za pośrednictwem API, zawierający dane giełdowe.
===== 4. Zdefiniowanie panelu sterowania aplikacji =====
Na tym etapie rozwoju aplikacja nie wymagała stworzenia panelu sterowania.
===== 5. Zdefiniowanie makropoleceń dla realizacji typowych operacji =====
Typowe operacje na bazie danych wykonywane są przy pomocy frameworka do realizacji warstwy dostępu do danych [[http://www.hibernate.org/|Hibernate]]. Pełni on funkcję mapera obiektowo-relacyjnego (ORM) i wykonuje podstawowe zapytania do bazy danych.
Z wielu dostępnych narzędzi tego typu, powyższe zostało wybrane z racji dojrzałości projektu, jak i dostarczonej do niego dokumentacji.
===== 6. Uruchamianie i testowanie aplikacji =====
Aplikacja uruchamiana oraz testowana była na lokalnych środowiskach jej twórców. Poszczególne komponenty i funkcjonalności były regularnie testowane w miarę rozwoju projektu, w celu możliwie szybkiego wyeliminowania ewentualnych niepoprawnych zachowań i innych sytuacji nieporządanych.
===== 7. Wprowadzanie danych =====
System opiera swe działanie o dane dostarczane przez serwis [[http://finance.yahoo.com|Charts - Yahoo! Finance]] za pośrednictwem API http://finance.yahoo.com/charts.
Fragment kodu (w języku Java), budujący adres uri dla danych do pobrania:
StringBuilder uri = new StringBuilder();
uri.append("http://ichart.finance.yahoo.com/table.csv");
uri.append("?s=").append(company.getSymbol());
uri.append("&a=").append(start.getMonth());
uri.append("&b=").append(start.getDay());
uri.append("&c=").append(start.getYear() + 1900);
uri.append("&d=").append(end.getMonth());
uri.append("&e=").append(end.getDay());
uri.append("&f=").append(end.getYear() + 1900);
uri.append("&g=d");
Aplikacja "odpytuje" API poprzez (zbudowane z powyższego) żądanie HTTP GET do Yahoo!, a serwis zwraca oczekiwane wartości (lub komunikat o błędzie, w przypadku przekazania niepoprawnych parametrów).
Tym sposobem otrzymujemy wartości dzienne danego, sprecyzowanego wskaźnika z określonego przedziału czasowego.
Na potrzeby implementacji oraz weryfikacji działania, aplikacja pozwala na import informacji o cenach złota, ropy oraz wartości indeksu Dow Jones. Na chwilę obecną import przeprowadzany jest ręcznie, docelowo wykonywane będzie to automatycznie.
===== 8. Wdrażanie systemu do użytkowania =====
W celu uruchomienia aplikacji na nowej maszynie produkcyjnej, należy wykonać następujące czynności:
* zaimportować strukturę bazodanową do docelowego serwera MySQL,
* zaktualizować sekcję dotyczącą parametrów bazy w pliku konfiguracyjnym projektu,
* uruchomić kontener servletów TomCat,
* wdrożyć projekt na serwer produkcyjny,
===== 9. Przeprowadzenie szkolenia użytkowników =====
Aplikacja nie jest bardzo skomplikowana, a interfejs w miarę intuicyjny. Korzystanie z niej nie powinno sprawić problemów użytkownikom systemu.
===== 10. Zapewnienie dokumentacji technicznej i użytkowej =====
Jedyną rzeczą jaką dobrzy byłoby dostarczyć użytkownikom aplikacji są podstawowe informacje o sieciach neuronowych oraz sposobie ich konstruowania i wykorzystania do przewidzenia danych giełdowych.
===== 11. Zapewnienie obsługiwania systemu po wdrożeniu =====
Obsługa aplikacji po wdrożeniu to zarówno kontrola poprawności działania aplikacji i bazy danych jak również moderacja zawartości. Autorzy powinni umożliwić i reagować na feedback od użytkowników. Ważne jest także skalowalność czyli przygotowanie bazy, serwera jak i aplikacji do znacznego wzrostu obciążenia w przypadku zwiększenia liczby użytkowników.
===== 12. Rozwijanie i modyfikowanie aplikacji =====
Podstawowym kierunkiem dalszego rozwoju aplikacji powinno być dodanie obsługi większej ilości spółek.
Kolejnym dobrym pomysłem będzie dodanie większej ilości parametrów do modułu tworzenia sieci neuronowych w celu umożliwienia dokładniejszych obliczeń.
Dodanie szaty graficznej znacznie wpłynęło by na komfort i wrażenia wizualne użytkowników.
===== 13. Opracowanie doświadczeń wynikających z realizacji projektu =====
Realizacja omawianego projektu wiązała się z koniecznością poznania nieużywanych przez nas do tej pory technologii i rozwiązań. Przede wszystkim dotyczy to frameworków Google Web Toolkit (GWT) oraz Hibernate.
O ile same w sobie są raczej przyjazne dla developerów, wykorzystanie ich razem - w jednym projekcie - nastręczyło nam dość sporych trudności i było znaczącą przyczyną opóźnienia dalszych prac. Niestety na chwilę obecną brakuje wyczerpujących dokumentacji dotyczących podpinania Hibernate'a do aplikacji tworzonej w GWT, dlatego też nie obyło się bez "eksperymentowania", którego normalnie bylibyśmy w stanie uniknąć.
Google Web Toolkit dla twórców aplikacji internetowych jest niewątpliwie ciekawym rozwiązaniem. Pozwala on na tworzenie serwisów AJAXowych z wykorzystaniem języka Java. Jest to możliwe poprzez mechanizmy przeprowadzające kompilację kodu Javowego stanowiącego część kliencką aplikacji do JavaScriptu, HTMLa i CSSa.
Hibernate natomiast, niezwykle upraszcza i przyspiesza wykonywanie operacji na strukturach bazodanowych. Pełni on funkcję mapera obiektowo-relacyjnego, co w konsekwencji pozwala na budowanie zapytań do bazy w oparciu o struktury obiektowe. Przy korzystaniu z tego typu rozwiązań, pod rozwagę należy wziąć kwestie wydajnościowe. Mapowanie obiektowo-relacyjne niewątpliwie jest wygodne (i atrakcyjne), w szczególności z punktu widzenia programisty nieobytego w językach SQLowych. Bez praktycznej znajomości SQLa można swobodnie wykonywać większość operacji bazodanowych. Jednak należy pamiętać, że "odpytywanie" bazy w taki sposób wymaga więcej zasobów, z racji samej natury translacji O-R. Dlatego też, w sytuacjach, gdzie wydajność staje się czynnikiem krytycznym, nieraz bardziej odpowiednie okaże się korzystanie ze "standardowych" zapytań.
===== 14. Wykaz literatury, linki i załączniki =====
[[http://finance.yahoo.com/charts|Charts - Yahoo! Finance]]
[[http://www.hibernate.org/|Hibernate: Relational Persistence for Java and .NET]]
[[http://en.wikipedia.org/wiki/Object-relational_mapping|Object-relational mapping]]
[[http://code.google.com/intl/pl-PL/webtoolkit/|Google Web Toolkit]]