piątek, 9 listopada 2018

Giełda - pCreateBuyTransaction - rozszerzenie

Przy okazji tworzenia procedury "Czyszczenia rynku" z przeterminowanych akcji, potrzeba zmusiła mnie do rozszerzenia procedury pCreateBuyTransaction o obsługę zleceń "kPKC" oraz "kCU". Wcześniejsza wersja robiła tylko inserta do  tabeli MarketSquare bez uwzględnienia różnic pomiędzy typami zleceń.
Poniżej wstawię calą procedurę gdyż zmian jest dość dużo.
Naj wązniejsza zmiana to rozróżnienie  zlecenia o statusie kPKC i kCU. Pokażdej cenie mamy cenę równą 0 (zero), cenę pobieramy z tabeli Stock i na tej podstawie wyliczamy ile pieniędzy potrzebujemy zabrać z portfela, a przy okazji czyszczenia rynku pieniądze będą zwracane (jeżeli zlecenie się przeterminuje) na podstawie wyliczonej wartości zlecenia przy składaniu transakcji ( pCreateBuyTransaction). Przy realizacji zlecenia na rynku istnieje rekord w którym mamy zarezerwowaną pewną kwotę  (to jakby zaliczka), wtedy będzie ponownie sprawdzona cena na rynku i z równania wyjdzie nam różnica którą użytkownik musi zapłacić lub zostanie mu zwrócona albo się wstrzeli w cenę i nie będzie musiał dopłacać.

KOD:


BEGIN
--pomocnicze
declare @wallet_id int
declare @stock_id int
declare @stockN_id int
declare @walletMoneyLimit money
declare @userLogin varchar(50)
--wyszukanie portfela oraz akcji
select @wallet_id = wal_id from UserTable where usr_id =@user_id
select @walletMoneyLimit = wal_MoneyLimit from Wallet where wal_id = @wallet_id
select @stockN_id = stockN_id from StockName where stockN_name = @stock_name
select @stock_id = stock_id from Stock where stockN_id = @stockN_id

if (@priceStatusId = 1)
        begin
        -- sprawdzenie portfela
        declare @result money
        declare @PriceTransaction money
        set @result = @numberBuyStock * @stockPrice
        --transakcja na rynek
                        if(@result <= @walletMoneyLimit)
                        begin
                          INSERT INTO [dbo].[MarketSquare]
                                  ([stock_id],[wal_id],[mark_numberOfShares]
                                  ,[mark_aktywny],[mark_sharePriceBuy]
                                  ,[bs_id],[mark_sharePriceSell]
                                   ,[mark_dataStart],[mark_dataEnd]
                                   ,[mark_TransactionPrice],[priceStatus_id])
                                VALUES                                                         (@stock_id,@wallet_id,@numberBuyStock,1,@stockPrice,2,0,GETDATE(),@dataEnd,@result,@priceStatusId)
                        --get money from wallet and set to transaction
                               set @PriceTransaction = @walletMoneyLimit - @result
                               update Wallet set
                                       wal_MoneyLimit = @PriceTransaction
                               where
                                       wal_id = @wallet_id
                        end
                        else
                        begin
                               select @userLogin = usr_login 
                                from UserTable 
                                where 
                                     usr_id = @user_id
                               exec pAddInfoToLog 2,@userLogin,
                                    'zamałe srodki na zakup akcji, zmniejsz liczbe akcji, kCU'
                        end
        end
        if(@priceStatusId = 3)
        begin
        declare @stockPriceFromStockTable money
        declare @priceInThisTime money
                --priceStatus = kPKC stockPrice = 0, get price of stock from Stock Table
                select @stockPriceFromStockTable = stock_priceBuy 
                 from Stock 
                      where stock_id = @stock_id
                set @priceInThisTime = @stockPriceFromStockTable * @numberBuyStock
                        if(@result <= @walletMoneyLimit)
                        begin
                               INSERT INTO [dbo].[MarketSquare]
                                          ([stock_id],[wal_id],[mark_numberOfShares]
                                          ,[mark_aktywny],[mark_sharePriceBuy]
                                          ,[bs_id],[mark_sharePriceSell]
                                          ,[mark_dataStart],[mark_dataEnd]
                                          ,[mark_TransactionPrice],[priceStatus_id])
                                VALUES
                                          (@stock_id,@wallet_id,@numberBuyStock,1,0e,2,0,GETDATE(),@dataEnd,@priceInThisTime,@priceStatusId)
                        --get money from wallet and set to transaction
                               set @PriceTransaction = @walletMoneyLimit - @result
                               update Wallet set
                                       wal_MoneyLimit = @PriceTransaction
                               where
                                       wal_id = @wallet_id
                        end
                        else
                        begin
                               select @userLogin = usr_login 
                               from UserTable 
                               where 
                                    usr_id = @user_id
                               exec pAddInfoToLog 2,@userLogin
                                    ,'zamałe srodki na zakup akcji, zmniejsz liczbe akcji, kPKC'
                        end
        end
end


czwartek, 8 listopada 2018

Giełda - Usunięcie przeterminowanych zleceń


Procedury nie ma sensu omawiać gdyż jest za prosta. W założeniu ma czyścić rynek z przeterminowanych zleceń.
Dodatkowo używam tu funkcji fDateDiff, która sprawdza dwa czasy i zwraca wynik z odejmowania dat, jeżeli mniejsze od zera to przeterminowany jeżeli większy to nieprzeterminowany
Mam dwa parametry, pomyślałem o jobie w nim będę puszczał tę procedurę, jeden to id tabeli MarketSquare drugi to interwał czasowy (mamy trzy do wyboru minuta, godzina, dzień), wszystko zależy jaki cykl giełdy che mieć. 
Procedura pOrderOverdue musi również zadbać o to żeby nastąpił zwrot środków do portfela przy zleceniu kupna ilości środków pieniężnych a przy zleceniu sprzedaży ilość akcji.
Problem widzę gdy mam zlecenia PKC czy  to kupna czy sprzedaży.


  • Przy kPKC chę kupić okręloną ilość akcji ale nie podaje ceny.
  • Przy sPKC chcę sprzedać określoną ilość akcji ale nie podaje ceny.
Zaglądając na procedury zlecenie kupna widzę że nie ma tam uwzględnionego statusu kPKC oraz sPKC.
Jakie jest rozwiązanie na teraz?
  1. Przy sprzedaży po każdej cenie mogę brać cenę z tabeli Stock i przeliczać wartość zakupionych (zlecenia kupna) akcji i ujmować odpowiednią kwotę z portfela.
  2. W zleceniu wpisuje tylko ilość akcji jaką chcę kupić nie odejmuje z portfela wartości bo póki nie jest zrealizowane nie wiem jaka aktualnie cena jest i w konsekwencji wartość zlecenia.
  3. Ostatnie co przychodzi mi na myśl to połączenie tych dwóch punktów czyli wystawiam zlecenie na pewną ilość akcji po cenie jak jest aktualnie na rynku, zabieram tę kwotę z portfela (rezerwuje ją), następnie jak zlecenie się przeterminowywuje (nowe słowo do słownika) to kwotę tą zwracam do portfela, w przeciwnym wypadku realizuje zlecenie ale cena w tedy już jest inna (bądź będzie inna) w tabeli Stock  dla danej akcji. Aby otrzymać kwotę jaką należy zabrać z portfela składającego zlecenie, powinienem pobrać ilość akcji ze zlecenia na rynku oraz znaleźć różnicę  w wartości akcji. W skład tego równania wejdzie ilość wartość zlecenia kupna w chwili jego składania (ilość akcji i cena akcji według tabeli Stock na tamtą chwilę) oraz ilość akcji razy aktualna cena z tabeli Stock.Jeżeli otrzymam wartość ujemną to oznacza że muszę pobrać dodatkową kwotę z portfela, w przeciwnym wypadku muszę do portfela dodać, a jeżeli zero to nic nie robię. Przed założeniem takiego zlecenia trzeba użytkownika ostrzec przed konsekwencjami, tylko co jeżeli braknie mu kasy na razie dług i komornik.   

PROCEDURE [dbo].[pOrderOverdue](
   @mark_id int,
   @interval int
)
AS
BEGIN
declare @dateEnd Datetime
declare @result int
declare @walId int
declare @info varchar(50)
--wallet state before order deactivate
declare @wallCountStocks int
declare @wallCountAllMoney decimal

--market square value
declare @marketSquareCountStocks int
declare @marketSquareCountMoney decimal
declare @marketSqureOrderStatusId int
--
declare @userLogin varchar(50) = 'baza-pOrderOverdue'
select @dateEnd = mark_dataEnd, @walId = wal_id,@marketSqureOrderStatusId = bs_id  
from MarketSquare
where
mark_id = @mark_id
-- wazna uwaga zlecenia kupna roznia sie od zlecen sprzedazy
-- kupno daje pieniadze nie trace ilosci
-- sprzedaz trace ilosc pieniadze bez zmian

select @result = dbo.fDateDiff(1,@dateEnd)
        if(@result < 0)
        begin
                declare @userLoginWallet varchar(50)
                --get login from user table
                select @userLoginWallet = usr_login  from UserTable where wal_id = @walId

                update MarketSquare set
                mark_aktywny = 0
                where
                mark_id = @mark_id
                --get old value from wallet
                select @wallCountStocks = wal_numberOfShares
                     , @wallCountAllMoney = wal_MoneyLimit
                from Wallet
                where
                        wal_id = @walId
                --overdue transaction in status = 2
                --buy
                if(@marketSqureOrderStatusId = 2)
                begin
                        declare @resultMoneyFromStock money
                        --get value from market square
                        select @marketSquareCountMoney = mark_TransactionPrice 
                        from MarketSquare 
                        where mark_id = @mark_id
                        set @resultMoneyFromStock = @marketSquareCountMoney 
                                                  + @wallCountAllMoney
                        update Wallet set
                               wal_MoneyLimit = @resultMoneyFromStock
                        where
                                wal_id = @walId

                        set @info = 'kupno, zwrot pieniedzy = ' 
                                  + CAST(@marketSquareCountMoney as varchar(10))
                        exec pAddInfoToLog 2,@userLoginWallet, @info
                end
                --sell
                if(@marketSqureOrderStatusId = 3)
                begin
                        declare @resultCountStock int
                        --get how many stock i sell transaction in market square
                        select @marketSquareCountStocks = mark_numberOfShares 
                        from MarketSquare 
                        where mark_id = @mark_id
                        set @resultCountStock = @marketSquareCountStocks 
                                              + @wallCountStocks   
                        update Wallet set
                               wal_numberOfShares = @resultCountStock
                        where
                               wal_id = @walId

                        set @info = 'sprzedaz, zwrot akcji = ' 
                                  + CAST(@marketSquareCountMoney as varchar(10))
                        exec pAddInfoToLog 2,@userLoginWallet, @info
                end
                --emission
                if(@marketSqureOrderStatusId = 4)
                begin
                              
                       exec pAddInfoToLog 2,@userLogin,'emisja akcji'
                end
                --return
                if(@marketSqureOrderStatusId = 5)
                begin
                              
                      exec pAddInfoToLog 2,@userLogin,'skup akcji'
                end
  end
END


FUNCTION [dbo].[fDateDiff]
(
   @interval int,
   @dateEnd datetime
)
RETURNS int
AS
 BEGIN
  DECLARE @result int

  if(@interval = 1)
  begin
      SELECT @result = DATEDIFF(minute, GetDAte(),@dateEnd)
   end
  if(@interval = 2)
  begin
     SELECT @result = DATEDIFF(HOUR, GetDAte(),@dateEnd)
  end
  if(@interval = 3)
  begin
    SELECT @result = DATEDIFF(DAY, GetDAte(),@dateEnd)
  end
RETURN @result

END