SQL и биржевой график (Создание торговой системы)

добавлено: 11 окт 14
понравилось:0
просмотров: 3290
комментов: 7

теги:

Автор: Myp3_u_K

Публикация пятая
Создание торговой системы

Чалышев М.М www.orasource.ru
изучаем SQL группа в контакте - присоединяйтесь

1. SQL и биржевой график. Получение истории котировок с сервиса РБК
2. SQL и биржевой график. Зачем нужна СИСТЕМА
3. SQL и биржевой график. Основные показатели фондового рынка
4. SQL и биржевой график. Анализ рыночных показателей
5. SQL и биржевой график. Создание торговой системы
6. SQL и биржевой график. Анализ эффективности торговой стратегии
7. SQL и биржевой график. Оптимизация торговой системы + Управление капиталом = 41% годовых
8. 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

Комментарии


  • от дат 2009 года очень удобно "тестировать" более тупые стратегии, вроде "просто прийти на рынок" и "случайно выбрать именно сбербанк". Давайте огласим результаты работы стратегии за последний год, два года , ну чтобы непосвященные прониклись :)

  • нормальный бизнес планируется не на год два , а на 30 - 50 лет
    это не стратегия , на основе данной инфраструктуры вы можете реализовать любые правила
    и пересечение средних это тоже не стратегия, мой вам совет , не торгуйте

  • Нормальный бизнес может быть спланирован на столько, на сколько есть возможность привлечь финансовые ресурсы, в данный момент на 30 лет привлечь могут структуры масштаба мировых ЦБ...

    Если Вы считаете себя настолько успешным биржевым гуру чтобы раздавать советы, зачем какими-то мини-отелями заниматься, создали бы контору а ля LTCM :)

  • в Европе нормальное явление - семейный магазинчик, который существует 50 - 100 лет бизнес передается там от отца к сыну... о каких мировых ЦБ вы говорите...

  • я никакой не гуру , я рядовой инвестор ...
    совет я вам дал потому как вы хотите, судя по вашим постам, много и сразу , а это как правило ничем хорошим не заканчивается
    нормальная доходность торговой стратегии 30% - 35% в год...
    стандартный результат работы на финансовых рынках минус 100% инвестиционного капитала за первый год работы
    по отелям - вы что нибудь о диверсификации слышали?

  • семейный магазинчик - это не бизнес, в Европе это форма того, что в России обзывают самозанятостью.

    мои посты появились потому, что предлагая непонятно кому обсчитывать стратегию в sql-плюсе и взяв
    для примера почти идеальный интервал исторических данных , Вы стратегию с доходностью 30%*5 лет не
    показали...

    тот кто может разобрать предложенный PL\SQL, как большинство читателей этого сайта , просто пишет
    программу которая обсчитывает ТС прямо из файла

    и минус 100% за первый год работы - нестандартный результат, из тех двоих трейдеров которых
    я имею возможность наблюдать, включая меня, ни у одного таких потерь не было,
    на рынок пришли раньше 2009...

  • понятно магазинчик не бизнес , студия красоты не бизнес , солярий не бизнес , ресторан семейный тоже не бизнес...
    ну просвятите тогда меня что такое бизнес...
    тот кто может... вы несете чушь и даже не прочитали, что здесь написано

    минус 100% абсолютно стандартный результат , согласно блумберг более половины всех кто приходит на рынок теряют все деньги предназначенные для инвестиций

    портфель риск менеджмент, тоже из файла будете считать ...
    раньше году этак в 1980 все данные рассчитывались исключительно из текстовых файлов
    потом появились базы данных - это прогресс называется

    лучше тогда Метастоком воспользоваться
    он 1500$ единиц стоит и неплохо продается, если у вас есть возможнось написать продукт такого уровня ...

    да, комментируйте , здоровая критика всегда приветствуется



Необходимо войти на сайт, чтобы оставлять комментарии