SQL и биржевой график (Создание торговой системы)
Публикация пятая
Создание торговой системы
Подготовим необходимую инфраструктуру для разработки и отладки торговых стратегий
Создадим таблицы
Это таблица балансов, где будут сохраняться сведения о общем и накопительном итогах наших торговых операций, таблица позиций , для просмотра текущих позиций и непосредственно таблица торговых операций - сделок.
-- Create table create table TRADES ( ticker VARCHAR2(5) , opendate DATE , openprice NUMBER , closedate DATE , closeprice NUMBER , position NUMBER ) ; -- Add comments to the table comment on table TRADES is 'Сделки'; -- Add comments to the columns comment on column TRADES.ticker is 'Тикер инструмента'; comment on column TRADES.opendate is 'Дата открытия сделки'; comment on column TRADES.openprice is 'Цена открытия'; comment on column TRADES.closedate is 'Дата закрытия'; comment on column TRADES.closeprice is 'Цена закрытия'; comment on column TRADES.position is 'Позиция'; -- Create/Recreate indexes create unique index TRADES_IDX on TRADES (TICKER, opendate); -- Create table create table POSITIONS ( ticker VARCHAR2(5) , position NUMBER , positionprice NUMBER ) ; -- Add comments to the table comment on table POSITIONS is 'Позиции'; -- Add comments to the columns comment on column POSITIONS.ticker is 'Тикер инструмента'; comment on column POSITIONS.position is 'Дата открытия сделки'; comment on column POSITIONS.positionprice is 'Позиция в рублях'; -- Create/Recreate indexes create unique index POSITIONS_IDX on POSITIONS (ticker); drop table BALANCE; -- Create table create table BALANCE ( ticker VARCHAR2(5) , tradedate date , balancedelta NUMBER , balanceall NUMBER , balanceallticker NUMBER , balancedeltarur NUMBER , balanceallrur NUMBER , balancealltickerrur NUMBER ) ; -- Add comments to the table comment on table BALANCE is 'Баланс'; -- Add comments to the columns comment on column BALANCE.ticker is 'Тикер инструмента'; comment on column BALANCE.tradedate is 'Дата трейда'; comment on column BALANCE.balancedelta is 'Дельта баланса'; comment on column BALANCE.balanceall is 'Накопительная сумма баланса'; comment on column BALANCE.balanceallticker is 'Накопительная сумма баланса по инструментам'; comment on column BALANCE.balancedeltarur is 'Дельта баланса в рублях'; comment on column BALANCE.balanceallrur is 'Накопительная сумма баланса в рублях'; comment on column BALANCE.balancealltickerrur is 'Накопительная сумма баланса по инструментам в рублях'; -- Create/Recreate indexes create unique index BALANCE_IDX on BALANCE (ticker, tradedate);
далее создадим необходимые нам в работе сервисные функции
вспомогательные функции для работы с ценами актива
так же это функции, отвечающие за правила открытия и закрытия позиций
а так же функция. которая отвечает за управление капиталом
Обратите внимание , что некоторые из функций связаны с пакетом tradesystem_pkg, поэтому после создания пакета tradesystem_pkg потребуется повторная компиляция этих функций.
create or replace function priorind(priceticker varchar2, operdate date ) return priceind%rowtype -- строка индикатора на n дней назад is vr_return priceind%rowtype; begin vr_return := null; -- открываем позицию только в случае , если не позиции по данному инструменту select * into vr_return from priceind where priceind.ticker = priceticker and priceind.dateprice = ( select max(priceind.dateprice) nc from priceind where priceind.dateprice<operdate ) ; return vr_return; exception when others then dbms_output.put_line(operdate); return null; end priorind; create or replace function getpriceind(priceticker varchar2, operdate date, n number) return priceind%rowtype -- строка инддикатора на n дней назад is vr_return priceind%rowtype; begin vr_return := null; -- открываем позицию только в случае , если не позиции по данному инструменту select * into vr_return from priceind where priceind.ticker = priceticker and priceind.dateprice = ( select nc from (select priceind.dateprice dateprice, Lead(dateprice, n, priceind.dateprice) over(order by dateprice desc) nc from priceind where ticker = priceticker and priceind.dateprice <= operdate and priceind.dateprice > operdate - n*2 ) where dateprice = operdate ) ; return vr_return; end getpriceind; create or replace function ind(priceticker varchar2 , operdate date) return priceind%rowtype -- строка индикатора текущая дата is vr_return priceind%rowtype; begin vr_return := null; -- открываем позицию только в случае , если не позиции по данному инструменту select * into vr_return from priceind where priceind.ticker = priceticker and priceind.dateprice = operdate ; return vr_return; end ind; create or replace function closerules(priceticker varchar2, operdate date) return number -- правила закрытия позиции is vr_return number; rind priceind%rowtype; price priceind%rowtype; begin vr_return := 0; for i in (select * from trades where trades.ticker = priceticker and trades.closedate is null) loop -- проверка только в том случае если есть открытые трейды rind := priorind(priceticker , operdate); price := ind(priceticker, operdate); if price.c < rind.min20 then vr_return := 1; end if; end loop; return vr_return; end closerules; create or replace function openrules(priceticker varchar2, operdate date) return number -- правила открытия позиции is vr_return number; vr_count number; rind priceind%rowtype; price priceind%rowtype; begin vr_return := 0; -- проверка только в том случае если есть открытые трейды select /* +first_rows(1)*/ count(1) into vr_count from trades where trades.ticker = priceticker and trades.closedate is null and rownum<2; if vr_count=0 then rind := priorind(priceticker , operdate); price := tradesystem_pkg.indnow; if price.c > price.avg200 and rind.vti5 < rind.vti20/3 and price.c > rind.c and price.v > rind.v then vr_return := 1; end if; end if; return vr_return; end openrules; create or replace function moneyposition(priceticker varchar2, operdate date) return number -- правил управления капиталом , возвращает позицию в количестве акций которые можно купить is vr_return number; rw priceind%rowtype; begin vr_return := 0; -- открываем позицию только в случае , если не позиции по данному инструменту rw := tradesystem_pkg.indnow; vr_return := trunc(tradesystem_pkg.moneybalance / 10 / rw.c); return vr_return; end moneyposition;
создадим пакет обеспечивающий инфраструктуру для обеспечения наших торговых стратегий
create or replace package body report_pkg is -- Function and procedure implementations -- Общая прибыль function getsumwin(priceticker varchar2 default null) return number is vr_return number; begin select sum(balance.balancedeltarur) into vr_return from balance where (balance.ticker = priceticker or priceticker is null); return vr_return; end getsumwin; -- Средняя прибыльная сделка function getavgwintrade(priceticker varchar2 default null) return number is vr_return number; begin select avg(balance.balancedeltarur) into vr_return from balance where (balance.balancedelta>0) and (balance.ticker = priceticker or priceticker is null); return vr_return; end getavgwintrade; -- Средняя убыточная сделка function getavglosstrade(priceticker varchar2 default null) return number is vr_return number; begin select avg(balance.balancedeltarur) into vr_return from balance where (balance.balancedelta<0) and (balance.ticker = priceticker or priceticker is null); return vr_return; end getavglosstrade; -- Максимальная просадка function getmaxloss(priceticker varchar2 default null) return number is vr_return number; begin if priceticker is null then select max(balance.balanceallrur)-min(balance.balanceallrur) into vr_return from balance; else select max(balance.balancealltickerrur)-min(balance.balancealltickerrur) into vr_return from balance where balance.ticker = priceticker; end if; return vr_return; end getmaxloss; -- Общее количество сделок function gettradescount(priceticker varchar2 default null) return number is vr_return number; begin select count(1) into vr_return from balance where (balance.ticker = priceticker or priceticker is null); return vr_return; end gettradescount; -- Общее прибыльных сделок function gettradeswincount(priceticker varchar2 default null) return number is vr_return number; begin select count(1) into vr_return from balance where balance.balancedelta>0 and (balance.ticker = priceticker or priceticker is null); return vr_return; end gettradeswincount; -- Общее количество убыточных сделок function getlosscount(priceticker varchar2 default null) return number is vr_return number; begin select count(1) into vr_return from balance where balance.balancedelta<0 and (balance.ticker = priceticker or priceticker is null); return vr_return; end getlosscount; -- макс Количество убыточных сделок подряд function gettradeslosscount(priceticker varchar2 default null) return number is vr_return number:=0; vr_count number:=0; begin for i in ( select balance.balancedeltarur r from balance where (balance.ticker = priceticker or priceticker is null) order by balance.tradedate ) loop if i.r > 0 then vr_count:=0; end if; if i.r < 0 then vr_count:=vr_count+1 ; if vr_count>vr_return then vr_return := vr_count; end if; end if; end loop; return vr_return; end gettradeslosscount; -- Максимальный убыток function gettradeslosstrade(priceticker varchar2 default null) return number is vr_return number; begin select min(balance.balancedeltarur) into vr_return from balance where balance.balancedelta<0 and (balance.ticker = priceticker or priceticker is null); return vr_return; end gettradeslosstrade; begin -- Initialization null; end report_pkg;
очистим таблицы и запустим тестирование стратегии на исторических данных для инструмента сбербанк
проверим сформированные торговые сделки позиции и баланс.
select * from positions select * from balance select * from tradesПросмотров: 1012