Skip to content

Commit cfef880

Browse files
Merge pull request #135 from naveedkhan1998/revert-134-copilot/add-options-viewing-graph
Revert "feat: Options chain viewer on instrument graph page"
2 parents 25b2a04 + 2fc6b40 commit cfef880

8 files changed

Lines changed: 2 additions & 912 deletions

File tree

‎backend/apps/core/services/alpaca_service.py‎

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -159,59 +159,5 @@ def get_historic_bars(
159159
url = f"{self.data_base_url}/v2/stocks/{symbol}/bars"
160160
return self._make_request("GET", url, params=params)
161161

162-
def get_option_snapshots(
163-
self,
164-
underlying_symbol: str,
165-
feed: str = "indicative",
166-
expiration_date_gte: str | None = None,
167-
expiration_date_lte: str | None = None,
168-
option_type: Literal["call", "put"] | None = None,
169-
limit: int = 200,
170-
page_token: str | None = None,
171-
) -> dict:
172-
"""Fetch option chain snapshots (quotes + greeks) for an underlying symbol."""
173-
params: dict = {"feed": feed, "limit": limit}
174-
if expiration_date_gte:
175-
params["expiration_date_gte"] = expiration_date_gte
176-
if expiration_date_lte:
177-
params["expiration_date_lte"] = expiration_date_lte
178-
if option_type:
179-
params["type"] = option_type
180-
if page_token:
181-
params["page_token"] = page_token
182-
183-
url = f"{self.data_base_url}/v1beta1/options/snapshots/{underlying_symbol}"
184-
return self._make_request("GET", url, params=params)
185-
186-
def get_option_bars(
187-
self,
188-
symbols: str | list[str],
189-
timeframe: str = "1Day",
190-
start: str | None = None,
191-
end: str | None = None,
192-
limit: int = 1000,
193-
page_token: str | None = None,
194-
sort: Literal["asc", "desc"] = "asc",
195-
) -> dict:
196-
"""Fetch historical OHLCV bars for option contract symbols."""
197-
if isinstance(symbols, list):
198-
symbols = ",".join(symbols)
199-
200-
params: dict = {
201-
"symbols": symbols,
202-
"timeframe": timeframe,
203-
"limit": limit,
204-
"sort": sort,
205-
}
206-
if start:
207-
params["start"] = start
208-
if end:
209-
params["end"] = end
210-
if page_token:
211-
params["page_token"] = page_token
212-
213-
url = f"{self.data_base_url}/v1beta1/options/bars"
214-
return self._make_request("GET", url, params=params)
215-
216162

217163
alpaca_service = AlpacaService()

‎backend/apps/core/views/main.py‎

Lines changed: 0 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -605,119 +605,6 @@ def candles_v3(self, request, pk=None):
605605
"""
606606
return get_candles_v3(self, request, pk)
607607

608-
@staticmethod
609-
def _parse_limit(request, default: int, maximum: int) -> int:
610-
"""Parse and clamp the 'limit' query parameter."""
611-
try:
612-
return min(int(request.query_params.get("limit", default)), maximum)
613-
except (ValueError, TypeError):
614-
return default
615-
616-
@action(detail=True, methods=["get"], url_path="option_chain")
617-
def option_chain(self, request, pk=None):
618-
"""
619-
Fetch the options chain (snapshots with quotes and greeks) for an underlying equity asset.
620-
621-
Query Parameters:
622-
expiration_date_gte: Filter options expiring on or after this date (YYYY-MM-DD).
623-
expiration_date_lte: Filter options expiring on or before this date (YYYY-MM-DD).
624-
type: Option type filter – 'call' or 'put'.
625-
limit: Maximum number of contracts to return (default 200, max 1000).
626-
page_token: Pagination token from a previous response.
627-
628-
Returns:
629-
{
630-
"msg": "Ok",
631-
"data": {
632-
"snapshots": { "<symbol>": { "details": {...}, "greeks": {...}, ... } },
633-
"next_page_token": null
634-
}
635-
}
636-
"""
637-
asset = self.get_object()
638-
639-
if asset.asset_class != "us_equity":
640-
return Response(
641-
{"msg": "Options chain is only available for equity assets"},
642-
status=status.HTTP_400_BAD_REQUEST,
643-
)
644-
645-
expiration_date_gte = request.query_params.get("expiration_date_gte")
646-
expiration_date_lte = request.query_params.get("expiration_date_lte")
647-
option_type = request.query_params.get("type")
648-
limit = self._parse_limit(request, default=200, maximum=1000)
649-
page_token = request.query_params.get("page_token")
650-
651-
try:
652-
data = alpaca_service.get_option_snapshots(
653-
underlying_symbol=asset.symbol,
654-
expiration_date_gte=expiration_date_gte,
655-
expiration_date_lte=expiration_date_lte,
656-
option_type=option_type,
657-
limit=limit,
658-
page_token=page_token,
659-
)
660-
return Response({"msg": "Ok", "data": data}, status=status.HTTP_200_OK)
661-
except Exception as e:
662-
logger.error(
663-
f"Error fetching option chain for {asset.symbol}: {e}", exc_info=True
664-
)
665-
return Response(
666-
{"msg": "Error fetching option chain"},
667-
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
668-
)
669-
670-
@action(detail=False, methods=["get"], url_path="option_bars")
671-
def option_bars(self, request):
672-
"""
673-
Fetch historical OHLCV bars for a specific option contract.
674-
675-
Query Parameters:
676-
symbol: Option contract symbol (required), e.g. AAPL240119C00180000.
677-
timeframe: Bar timeframe – '1Min', '5Min', '1Hour', '1Day' (default '1Day').
678-
start: Start date/time in ISO 8601 format.
679-
end: End date/time in ISO 8601 format.
680-
limit: Maximum number of bars to return (default 1000, max 10000).
681-
682-
Returns:
683-
{
684-
"msg": "Ok",
685-
"data": {
686-
"bars": { "<symbol>": [{"t": ..., "o": ..., "h": ..., "l": ..., "c": ..., "v": ...}] },
687-
"next_page_token": null
688-
}
689-
}
690-
"""
691-
symbol = request.query_params.get("symbol")
692-
if not symbol:
693-
return Response(
694-
{"msg": "symbol parameter is required"},
695-
status=status.HTTP_400_BAD_REQUEST,
696-
)
697-
698-
timeframe = request.query_params.get("timeframe", "1Day")
699-
start = request.query_params.get("start")
700-
end = request.query_params.get("end")
701-
limit = self._parse_limit(request, default=1000, maximum=10000)
702-
703-
try:
704-
data = alpaca_service.get_option_bars(
705-
symbols=symbol,
706-
timeframe=timeframe,
707-
start=start,
708-
end=end,
709-
limit=limit,
710-
)
711-
return Response({"msg": "Ok", "data": data}, status=status.HTTP_200_OK)
712-
except Exception as e:
713-
logger.error(
714-
f"Error fetching option bars for {symbol}: {e}", exc_info=True
715-
)
716-
return Response(
717-
{"msg": "Error fetching option bars"},
718-
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
719-
)
720-
721608

722609
class WatchListViewSet(PublicReadOnlyMixin, viewsets.ModelViewSet):
723610
"""

‎frontend/src/features/graphs/components/controls/ChartToolbar.tsx‎

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,11 @@ import {
4242
LayoutTemplate,
4343
Settings2,
4444
FunctionSquare,
45-
TrendingUp,
4645
} from 'lucide-react';
4746
import type { SeriesType } from 'lightweight-charts';
4847
import { timeframeOptions } from '@/lib/constants';
4948
import { useIndicatorUI } from '../../context';
5049
import { useRequireAuth } from '@/hooks/useRequireAuth';
51-
import type { Asset } from '@/types/common-types';
5250

5351
const chartTypeOptions: {
5452
value: SeriesType;
@@ -99,13 +97,7 @@ const presetOptions = [
9997
},
10098
];
10199

102-
export default function ChartToolbar({
103-
asset,
104-
onOptionsClick,
105-
}: {
106-
asset?: Asset;
107-
onOptionsClick?: () => void;
108-
}) {
100+
export default function ChartToolbar() {
109101
const dispatch = useAppDispatch();
110102
const timeframe = useAppSelector(selectTimeframe);
111103
const chartType = useAppSelector(selectChartType);
@@ -267,21 +259,6 @@ export default function ChartToolbar({
267259
)}
268260
</Button>
269261

270-
{/* Options Button (equity only) */}
271-
{asset?.asset_class === 'us_equity' && onOptionsClick && (
272-
<Button
273-
variant="ghost"
274-
size="sm"
275-
className="h-8 px-2 gap-1.5 text-muted-foreground hover:text-foreground"
276-
onClick={onOptionsClick}
277-
>
278-
<TrendingUp className="w-4 h-4" />
279-
<span className="hidden text-xs font-medium sm:inline">
280-
Options
281-
</span>
282-
</Button>
283-
)}
284-
285262
{/* Settings Popover */}
286263
<Popover>
287264
<PopoverTrigger asChild>

0 commit comments

Comments
 (0)