Projekt konceptualny
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:
Dodawanie rekomendacji
Użytkownik ze swojej strony głównej wybiera odnośnik „Dodaj nową rekomendację”
Użytkownik wypełnia odpowiednie pola formularza:
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
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ą
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)
8. Wybór encji (obiektów) i ich atrybutów
Użytkownik
Spółka
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
9. Powiązania pomiędzy encjami (ERD - Entity-Relationship Diagram)
10. Diagramy przejść między stanami (STD - State Transition Diagram)
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:
Przedstawiana baza jest 2NF.
Trzecia postać normalna (3NF)
Wymagania:
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
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
Strona startowa
Ekran logowania
Ekran rejestracji nowego użytkownika
Ekran dodawania sieci neuronowej
Ekran wyświetlający rekomendacje
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 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 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